From b50990af3ce49685072d676f6f6473d183bd53e4 Mon Sep 17 00:00:00 2001 From: Peter Benjamin Date: Wed, 14 Sep 2016 16:11:53 -0700 Subject: [PATCH] Add basic CFn templates, restacker parameter templates, userdata templates --- .../CloudFormation/securitygroup.json | 23 ++ .../CloudFormation/singleinstance.json | 3 + .../CloudFormation/webapp-example.json | 297 ++++++++++++++++++ .../Parameters/webapp-parameter-example.yml | 25 ++ .../webapp-userdata-example.sh} | 0 README.md | 2 +- docs/03-CLOUDFORMATION.md | 2 +- 7 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 Infrastructure/CloudFormation/securitygroup.json create mode 100644 Infrastructure/CloudFormation/webapp-example.json create mode 100644 Infrastructure/Parameters/webapp-parameter-example.yml rename Infrastructure/{CloudFormation/webapp.json => userdata/webapp-userdata-example.sh} (100%) diff --git a/Infrastructure/CloudFormation/securitygroup.json b/Infrastructure/CloudFormation/securitygroup.json new file mode 100644 index 0000000..78762fd --- /dev/null +++ b/Infrastructure/CloudFormation/securitygroup.json @@ -0,0 +1,23 @@ +{ + "InstanceSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { + "Ref": "myVPC" + }, + "SecurityGroupIngress": [{ + "IpProtocol": "tcp", + "FromPort": "80", + "ToPort": "80", + "CidrIp": "0.0.0.0/0" + }], + "SecurityGroupEgress": [{ + "IpProtocol": "tcp", + "FromPort": "80", + "ToPort": "80", + "CidrIp": "0.0.0.0/0" + }] + } + } +} diff --git a/Infrastructure/CloudFormation/singleinstance.json b/Infrastructure/CloudFormation/singleinstance.json index e69de29..077404a 100644 --- a/Infrastructure/CloudFormation/singleinstance.json +++ b/Infrastructure/CloudFormation/singleinstance.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/Infrastructure/CloudFormation/webapp-example.json b/Infrastructure/CloudFormation/webapp-example.json new file mode 100644 index 0000000..8df4362 --- /dev/null +++ b/Infrastructure/CloudFormation/webapp-example.json @@ -0,0 +1,297 @@ +{ + "AWSTemplateFormatVersion" : "2010-09-09", + + "Description" : "Generic Restacker CFn Template for Web Applications.", + + "Parameters" : { + "InstanceType" : { + "Description" : "EC2 instance type", + "Type" : "String", + "Default" : "m3.medium", + "AllowedValues" : ["m3.medium","m3.large","m3.xlarge","m3.2xlarge", + "c4.large","c4.xlarge","c4.2xlarge", + "r3.2xlarge", "r3.large", + "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge"], + "ConstraintDescription" : "must be a valid EC2 instance type support HVM." + }, + "EbsVolumeSize" : { + "Description" : "The size of the EBS volume to be created as root", + "Type" : "String" + }, + "KeyName" : { + "Description" : "The EC2 Key Pair to allow SSH access to the instances", + "Type" : "String" + }, + "ApplicationSecurityGroups": { + "Type": "List", + "Description" : "The security group ID that will grant access to the Service from the ELB.", + "ConstraintDescription": "Must be list of EC2 security group ids" + }, + "ElbSecurityGroups": { + "Type": "List", + "Description" : "The security group ID that will grant access to the ELB.", + "ConstraintDescription": "Must be list of EC2 security group ids" + }, + "AppSubnets": { + "Type": "String", + "Description" : "A subnet ID where the app will run" + }, + "PublicSubnets": { + "Type": "String", + "Description" : "A subnet ID where ELB will run" + }, + "VpcId": { + "Type": "String", + "Description": "The VPC ID holding Subnets specified above." + }, + "InstanceProfileName": { + "Type": "String", + "Description" : "Instance Profile to associate with this instance." + }, + "ServicePlane" : { + "Description" : "The plane (all lowercase) where this stack will be stood up", + "Type" : "String", + "AllowedPattern" : "[a-z]+" + }, + "Environment" : { + "Description" : "The deployment environment or color, e.g., blue, green, dev, test, prod, etc.", + "Type" : "String" + }, + "ServiceName": { + "Type": "String", + "Description" : "The lowercase service name to be used to tag instances (alphanumeric with dashes).", + "AllowedPattern" : "[a-z0-9\\-]+" + }, + "TimeStamp": { + "Type": "String", + "Description" : "The stack creation timestamp in the format of %Y%m%d-%H%M" + }, + "AmiId": { + "Type": "String", + "Description" : "Default AMI for this instance." + }, + "StackCreator" : { + "Type": "String", + "Description" : "IAM User ID of the stack creator" + }, + "EnvironmentParameters" : { + "Type": "String", + "Description" : "Comma sepparated key/value pairs of environment parameters in the form of ENV1=VAL1,ENV2=VAL2, to be placed in /etc/profile.d/.sh" + }, + "S3LoggingBucket": { + "Type": "String", + "Description" : "The S3 bucket to be used for ELB logging." + }, + "S3InstallersBucket": { + "Type": "String", + "Description" : "The S3 bucket that contains the Service application code." + }, + "UserDataScript": { + "Type": "String", + "Description" : "The GPG encrypted userdata.sh scipt to be executed after init. Expected to live in S3 Bucket." + }, + "ApplicationBundle": { + "Type": "String", + "Description" : "The GPG encrypted application bundle to be installed by userdata. Expected to live in S3 Bucket." + }, + "SecurityTagKey": { + "Type": "String", + "Description" : "The security tag key to be used for all resources." + }, + "SecurityTagValue": { + "Type": "String", + "Description" : "The security tag value to be used for all resources." + }, + "NotificationTopic" : { + "Type": "String", + "Description" : "The ARN of an SNS topic to use for service health alerts." + }, + "ASGMin": { + "Type": "String", + "Description": "The minimum number of Instances for the Autoscale group.", + "Default" : "1" + }, + + "ASGDesired": { + "Type": "String", + "Description": "The Desired number of Instances for the Autoscale group.", + "Default" : "1" + }, + + "ASGMax": { + "Type": "String", + "Description": "The maximum number of Instances for the Autoscale group.", + "Default" : "1" + }, + + "LoadBalancerName": { + "Type": "String", + "Description": "The load balancer name" + }, + + "InstancePort": { + "Type": "Number", + "Description": "The load balancer listener instance port", + "Default" : "443" + }, + + "LoadBalancerPort": { + "Type": "Number", + "Description": "The load balancer listener port", + "Default" : "443" + } + }, + + "Resources" : { + "ServiceGroup" : { + "Type" : "AWS::AutoScaling::AutoScalingGroup", + "Properties" : { + "VPCZoneIdentifier": [{ "Ref": "AppSubnets" }], + "LaunchConfigurationName" : { "Ref" : "ServiceLaunchConfig" }, + "LoadBalancerNames" : [ { "Ref" : "ServiceLoadBalancer" } ], + "MinSize" : { "Ref" : "ASGMin" }, + "DesiredCapacity" : { "Ref" : "ASGDesired" }, + "MaxSize" : { "Ref" : "ASGMax" }, + "NotificationConfiguration" : { + "NotificationTypes" : [ "autoscaling:EC2_INSTANCE_LAUNCH", "autoscaling:EC2_INSTANCE_LAUNCH_ERROR", "autoscaling:EC2_INSTANCE_TERMINATE", "autoscaling:EC2_INSTANCE_TERMINATE_ERROR" ], + "TopicARN" : { "Ref" : "NotificationTopic" } + }, + "Tags" : [ + { "Key" : "CreatedBy", "Value" : { "Ref" : "StackCreator"}, "PropagateAtLaunch": "true" }, + { "Key" : "Name", "Value" : {"Fn::Join" : [ "-", [ { "Ref" : "ServicePlane"} ,{ "Ref" : "ServiceName"}, { "Ref" : "Environment" } , { "Ref" : "TimeStamp" } ]]}, "PropagateAtLaunch": "true" }, + { "Key" : { "Ref" : "SecurityTagKey"}, "Value" : { "Ref" : "SecurityTagValue"}, "PropagateAtLaunch": "true" }, + { "Key" : "Service", "Value" : { "Ref" : "ServiceName"}, "PropagateAtLaunch": "true" } + ] + } + }, + + + "ServiceLaunchConfig" : { + "Type" : "AWS::AutoScaling::LaunchConfiguration", + "Properties" : { + "IamInstanceProfile" : { "Ref" : "InstanceProfileName" }, + "KeyName" : { "Ref" : "KeyName" }, + "ImageId" : { "Ref" : "AmiId" }, + "PlacementTenancy" : "dedicated", + "SecurityGroups" : { "Ref" : "ApplicationSecurityGroups" } , + "InstanceType" : { "Ref" : "InstanceType" }, + "BlockDeviceMappings" : [ {"DeviceName" : "/dev/sda1", "Ebs" : { "VolumeType":"gp2","VolumeSize" : { "Ref" : "EbsVolumeSize" } } }], + "UserData" : { "Fn::Base64" : { "Fn::Join" : [ "", [ + "#!/bin/bash\n", + "# insert rest of bash script here..." + ]]}} + } + }, + "ServiceLoadBalancer": { + "Type": "AWS::ElasticLoadBalancing::LoadBalancer", + "Properties": { + "LoadBalancerName": { + "Ref": "LoadBalancerName" + }, + "AccessLoggingPolicy": { + "EmitInterval": 5, + "Enabled": "true", + "S3BucketName": { + "Ref": "S3LoggingBucket" + } + }, + "CrossZone": "true", + "HealthCheck": { + "HealthyThreshold": "3", + "Interval": "30", + "Target": { + "Fn::Join": ["", ["TCP:", { + "Ref": "InstancePort" + }]] + }, + "Timeout": "5", + "UnhealthyThreshold": "5" + }, + "Listeners": [{ + "InstancePort": { + "Ref": "InstancePort" + }, + "InstanceProtocol": "TCP", + "LoadBalancerPort": { + "Ref": "LoadBalancerPort" + }, + "Protocol": "TCP" + }], + "Scheme": "internet-facing", + "SecurityGroups": { + "Ref": "ElbSecurityGroups" + }, + "Subnets": [{ + "Ref": "PublicSubnet1" + }, { + "Ref": "PublicSubnet2" + }], + "Tags": [{ + "Key": { + "Ref": "SecurityTagKey" + }, + "Value": { + "Ref": "SecurityTagValue" + } + }, { + "Key": "Plane", + "Value": { + "Ref": "ServicePlane" + } + }, { + "Key": "Service", + "Value": { + "Ref": "ServiceName" + } + }, { + "Key": "CreatedBy", + "Value": { + "Ref": "StackCreator" + } + }] + } + }, + + "ServiceCloudWatch": { + "Type": "AWS::CloudWatch::Alarm", + "Properties": { + "AlarmDescription": "Alarm when UnHealthyHostCount is less than 1", + "AlarmName": { + "Ref": "LoadBalancerName" + }, + "AlarmActions": [{ + "Ref": "NotificationTopic" + }], + "ActionsEnabled": true, + "ComparisonOperator": "GreaterThanThreshold", + "Dimensions": [{ + "Name": "LoadBalancerName", + "Value": { + "Fn::Join": ["", [{ + "Ref": "ServiceName" + }, "-", { + "Ref": "Environment" + }]] + } + }], + "EvaluationPeriods": 1, + "InsufficientDataActions": [{ + "Ref": "NotificationTopic" + }], + "MetricName": "UnHealthyHostCount", + "Namespace": "AWS/ELB", + "Period": 300, + "Statistic": "Average", + "Threshold": 0, + "Unit": "Count" + } + } + }, + "Outputs": { + "ELB": { + "Value": { + "Fn::GetAtt": ["ServiceLoadBalancer", "DNSName"] + } + } + } +} diff --git a/Infrastructure/Parameters/webapp-parameter-example.yml b/Infrastructure/Parameters/webapp-parameter-example.yml new file mode 100644 index 0000000..22d76df --- /dev/null +++ b/Infrastructure/Parameters/webapp-parameter-example.yml @@ -0,0 +1,25 @@ +InstanceType: m3.medium +EbsVolumeSize: 100 +KeyName: ssh-key-name +ApplicationSecurityGroups: [sg-1a2b3c4d, sg-5e6f7g8h] +ElbSecurityGroups: [sg-1a2b3c4d, sg-5e6f7g8h] +AppSubnets: [subnet-1a2b3c4d, subnet-5e6f7g8h] +PublicSubnets: [subnet-1a2b3c4d, subnet-5e6f7g8h] +VpcId: vpc-a1b2c3d4 +InstanceProfileName: instance-role-name +ServicePlane: plane-name +Environment: blue +ServiceName: MyServiceApp +AmiId: ami-1ab2c3d4 +EnvironmentParameters: SERVICE_NAME=service_name,STACK_COLOR=blue +ApplicationBundle: application.zip.gpg +S3InstallersBucket: my-bucket +UserDataScript: userdata.sh.gpg +SecurityTagKey: security-tag-key-name +SecurityTagValue: security-tag-value +NotificationTopic: sns-topic-arn +# ASGMin: 1 +# ASGDesired: 1 +# ASGMax: 1 +# InstancePort: 443 +# LoadBalancerPort: 443 diff --git a/Infrastructure/CloudFormation/webapp.json b/Infrastructure/userdata/webapp-userdata-example.sh similarity index 100% rename from Infrastructure/CloudFormation/webapp.json rename to Infrastructure/userdata/webapp-userdata-example.sh diff --git a/README.md b/README.md index f03f208..c19aad5 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ OPTIONS -e, --environment-params=PARAMS Parameters to add to the instance environment (/etc/profile.d) in the form of k1=v1,k2=v2. E.g., -p SCORING_URL=https://scoring... -h, --help Prints these wonderful lines... - -l, --location=LOCATION Where to deploy, ksp, kvp, kcp... + -l, --location=LOCATION Location to deploy -m, --migrate-module=MODULE Migration module to execute -n, --name=NAME Stack prefix stack name (alphanumeric with dashes) -o, --migrate-options=OPTIONS Options required by migration module to migrate from green to diff --git a/docs/03-CLOUDFORMATION.md b/docs/03-CLOUDFORMATION.md index 7abd26b..841b63e 100644 --- a/docs/03-CLOUDFORMATION.md +++ b/docs/03-CLOUDFORMATION.md @@ -1,2 +1,2 @@ # CLOUDFORMATION TEMPLATES -CloudFormation Templates to be used by Restacker before deployment on AWS. \ No newline at end of file +CloudFormation Templates to be used by Restacker for AWS deployments. \ No newline at end of file