-
-
Save robsquires/79de54eeb04d620d5222 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"AWSTemplateFormatVersion": "2010-09-09", | |
"Description": "UVd Production WebServer Stack", | |
"Parameters": { | |
"KeyName": { | |
"Type": "String", | |
"Description": "Name of an existing EC2 Key Pair to enable SSH access to the webserver", | |
"Default": "uvd" | |
}, | |
"InstanceType": { | |
"Description": "Application Server EC2 instance type", | |
"Type": "String", | |
"Default": "m1.small", | |
"AllowedValues": [ | |
"t1.micro", | |
"m1.small", | |
"m1.medium", | |
"m1.large", | |
"m1.xlarge", | |
"m2.xlarge", | |
"m2.2xlarge", | |
"m2.4xlarge", | |
"c1.medium", | |
"c1.xlarge", | |
"cc1.4xlarge", | |
"cc2.8xlarge", | |
"cg1.4xlarge" | |
], | |
"ConstraintDescription": "must be a valid EC2 instance type." | |
}, | |
"UVdBucket": { | |
"Description": "S3 bucket for the Production WebServer", | |
"Type": "String", | |
"Default": "XXXX" | |
}, | |
"SNSTopic": { | |
"Description": "Email address for notifications.", | |
"Type": "String", | |
"Default": "XXX" | |
}, | |
"SecurityGroup": { | |
"Description": "The security group for the webserver.", | |
"Type": "String", | |
"Default": "production" | |
} | |
}, | |
"Mappings": { | |
"AWSInstanceType2Arch": { | |
"t1.micro": { | |
"Arch": "64" | |
}, | |
"m1.small": { | |
"Arch": "64" | |
}, | |
"m1.medium": { | |
"Arch": "64" | |
}, | |
"m1.large": { | |
"Arch": "64" | |
}, | |
"m1.xlarge": { | |
"Arch": "64" | |
}, | |
"m2.xlarge": { | |
"Arch": "64" | |
}, | |
"m2.2xlarge": { | |
"Arch": "64" | |
}, | |
"m2.4xlarge": { | |
"Arch": "64" | |
}, | |
"c1.medium": { | |
"Arch": "64" | |
}, | |
"c1.xlarge": { | |
"Arch": "64" | |
} | |
}, | |
"AWSRegionArch2AMI": { | |
"us-east-1": { | |
"64": "ami-XXX" | |
}, | |
"us-west-1": { | |
"64": "ami-XXX" | |
}, | |
"us-west-2": { | |
"64": "ami-XXX" | |
}, | |
"eu-west-1": { | |
"64": "ami-XXX" | |
}, | |
"sa-east-1": { | |
"64": "ami-XXX" | |
}, | |
"ap-southeast-1": { | |
"64": "ami-XXX" | |
}, | |
"ap-northeast-1": { | |
"64": "ami-XXX" | |
} | |
} | |
}, | |
"Resources": { | |
"ProductionServerUser": { | |
"Type": "AWS::IAM::User", | |
"Properties": { | |
"Path": "/", | |
"Policies": [ | |
{ | |
"PolicyName": "root", | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"cloudformation:DescribeStackResource", | |
"s3:Get", | |
"ec2:*" | |
], | |
"Resource": "*" | |
} | |
] | |
} | |
} | |
] | |
} | |
}, | |
"HostKeys": { | |
"Type": "AWS::IAM::AccessKey", | |
"DependsOn": "ProductionServerUser", | |
"Properties": { | |
"UserName": { | |
"Ref": "ProductionServerUser" | |
} | |
} | |
}, | |
"BucketPolicy": { | |
"Type": "AWS::S3::BucketPolicy", | |
"DependsOn": "HostKeys", | |
"Properties": { | |
"PolicyDocument": { | |
"Version": "2008-10-17", | |
"Id": "ReadPolicy", | |
"Statement": [ | |
{ | |
"Sid": "ReadAccess", | |
"Action": [ | |
"s3:GetObject" | |
], | |
"Effect": "Allow", | |
"Resource": { | |
"Fn::Join": [ | |
"", | |
[ | |
"arn:aws:s3:::", | |
{ | |
"Ref": "XXX" | |
}, | |
"/*" | |
] | |
] | |
}, | |
"Principal": { | |
"AWS": { | |
"Fn::GetAtt": [ | |
"ProductionServerUser", | |
"Arn" | |
] | |
} | |
} | |
} | |
] | |
}, | |
"Bucket": { | |
"Ref": "XXX" | |
} | |
} | |
}, | |
"AppServerSNSTopic": { | |
"Type": "AWS::SNS::Topic", | |
"Properties": { | |
"Subscription": [ | |
{ | |
"Endpoint": { | |
"Ref": "SNSTopic" | |
}, | |
"Protocol": "email" | |
} | |
] | |
} | |
}, | |
"AppServerGroup": { | |
"Type": "AWS::AutoScaling::AutoScalingGroup", | |
"Properties": { | |
"AvailabilityZones": { | |
"Fn::GetAZs": "" | |
}, | |
"LaunchConfigurationName": { | |
"Ref": "ProductionServer" | |
}, | |
"LoadBalancerNames": [ | |
{ | |
"Ref": "uvdLoadBalancer" | |
} | |
], | |
"MinSize": "1", | |
"MaxSize": "3", | |
"HealthCheckType": "ELB", | |
"HealthCheckGracePeriod": "720", | |
"NotificationConfiguration": { | |
"TopicARN": { | |
"Ref": "AppServerSNSTopic" | |
}, | |
"NotificationTypes": [ | |
"autoscaling:EC2_INSTANCE_LAUNCH", | |
"autoscaling:EC2_INSTANCE_LAUNCH_ERROR", | |
"autoscaling:EC2_INSTANCE_TERMINATE", | |
"autoscaling:EC2_INSTANCE_TERMINATE_ERROR" | |
] | |
} | |
} | |
}, | |
"ProductionServer": { | |
"Type": "AWS::AutoScaling::LaunchConfiguration", | |
"DependsOn": "BucketPolicy", | |
"Metadata": { | |
"AWS::CloudFormation::Init": { | |
"config": { | |
"files": { | |
"/home/ubuntu/.s3cfg": { | |
"content": { | |
"Fn::Join": [ | |
"", | |
[ | |
"[default]\n", | |
"access_key = ", | |
{ | |
"Ref": "HostKeys" | |
}, | |
"\n", | |
"secret_key = ", | |
{ | |
"Fn::GetAtt": [ | |
"HostKeys", | |
"SecretAccessKey" | |
] | |
}, | |
"\n", | |
"use_https = True\n" | |
] | |
] | |
}, | |
"mode": "000644", | |
"owner": "ubuntu", | |
"group": "ubuntu" | |
}, | |
"/home/ubuntu/.s3cfg": { | |
"content": { | |
"Fn::Join": [ | |
"", | |
[ | |
"[default]\n", | |
"access_key = ", | |
{ | |
"Ref": "HostKeys" | |
}, | |
"\n", | |
"secret_key = ", | |
{ | |
"Fn::GetAtt": [ | |
"HostKeys", | |
"SecretAccessKey" | |
] | |
}, | |
"\n", | |
"use_https = True\n" | |
] | |
] | |
}, | |
"mode": "000644", | |
"owner": "ubuntu", | |
"group": "ubuntu" | |
} | |
} | |
} | |
} | |
}, | |
"Properties": { | |
"SecurityGroups": [ | |
{ | |
"Ref": "SecurityGroup" | |
} | |
], | |
"ImageId": { | |
"Fn::FindInMap": [ | |
"AWSRegionArch2AMI", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
{ | |
"Fn::FindInMap": [ | |
"AWSInstanceType2Arch", | |
{ | |
"Ref": "InstanceType" | |
}, | |
"Arch" | |
] | |
} | |
] | |
}, | |
"UserData": { | |
"Fn::Base64": { | |
"Fn::Join": [ | |
"", | |
[ | |
"#!/bin/sh -v\n", | |
"#function error exit defined\n", | |
"error_exit()\n", | |
"{\n", | |
" cfn-signal -e 1 -r \"$1\" '", | |
{ | |
"Ref": "ProductionServerWaitHandle" | |
}, | |
"'\n", | |
" exit 1\n", | |
"}\n", | |
"apt-get -y install python-setuptools\n", | |
"easy_install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-1.0-6.tar.gz\n", | |
"cfn-init -s ", | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
" -r ProductionServer ", | |
" --access-key ", | |
{ | |
"Ref": "HostKeys" | |
}, | |
" --secret-key ", | |
{ | |
"Fn::GetAtt": [ | |
"HostKeys", | |
"SecretAccessKey" | |
] | |
}, | |
" --region ", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
" > /tmp/cfn_init.log || error_exit 'Failed to run cfn-init'\n", | |
"user-data 'production' '", | |
{ | |
"Ref": "ProductionServerWaitHandle" | |
}, | |
"' '", | |
{ | |
"Ref": "AWS::StackName" | |
}, | |
"' '", | |
{ | |
"Ref": "HostKeys" | |
}, | |
"' '", | |
{ | |
"Fn::GetAtt": [ | |
"HostKeys", | |
"SecretAccessKey" | |
] | |
}, | |
"' '", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"'\n", | |
"# If all went well, signal success\n", | |
"cfn-signal -e $? -r 'Production WebServer configuration' '", | |
{ | |
"Ref": "ProductionServerWaitHandle" | |
}, | |
"'\n" | |
] | |
] | |
} | |
}, | |
"KeyName": { | |
"Ref": "KeyName" | |
}, | |
"InstanceType": { | |
"Ref": "InstanceType" | |
} | |
} | |
}, | |
"uvdLoadBalancer": { | |
"Type": "AWS::ElasticLoadBalancing::LoadBalancer", | |
"Properties": { | |
"AvailabilityZones": { | |
"Fn::GetAZs": "" | |
}, | |
"Listeners": [ | |
{ | |
"InstancePort": "80", | |
"LoadBalancerPort": "80", | |
"Protocol": "HTTP", | |
"PolicyNames": [] | |
} | |
] | |
} | |
}, | |
"AppServerScaleUpPolicy": { | |
"Type": "AWS::AutoScaling::ScalingPolicy", | |
"Properties": { | |
"AdjustmentType": "ChangeInCapacity", | |
"AutoScalingGroupName": { | |
"Ref": "AppServerGroup" | |
}, | |
"Cooldown": "60", | |
"ScalingAdjustment": "1" | |
} | |
}, | |
"AppServerScaleDownPolicy": { | |
"Type": "AWS::AutoScaling::ScalingPolicy", | |
"Properties": { | |
"AdjustmentType": "ChangeInCapacity", | |
"AutoScalingGroupName": { | |
"Ref": "AppServerGroup" | |
}, | |
"Cooldown": "60", | |
"ScalingAdjustment": "-1" | |
} | |
}, | |
"CPUAlarmHigh": { | |
"Type": "AWS::CloudWatch::Alarm", | |
"Properties": { | |
"AlarmDescription": "Scale-up if CPU > 75% for 10 minutes", | |
"MetricName": "CPUUtilization", | |
"Namespace": "AWS/EC2", | |
"Statistic": "Average", | |
"Period": "60", | |
"EvaluationPeriods": "10", | |
"Threshold": "75", | |
"AlarmActions": [ | |
{ | |
"Ref": "AppServerScaleUpPolicy" | |
} | |
], | |
"Dimensions": [ | |
{ | |
"Name": "AutoScalingGroupName", | |
"Value": { | |
"Ref": "AppServerGroup" | |
} | |
} | |
], | |
"ComparisonOperator": "GreaterThanThreshold" | |
} | |
}, | |
"CPUAlarmLow": { | |
"Type": "AWS::CloudWatch::Alarm", | |
"Properties": { | |
"AlarmDescription": "Scale-down if CPU < 75% for 10 minutes", | |
"MetricName": "CPUUtilization", | |
"Namespace": "AWS/EC2", | |
"Statistic": "Average", | |
"Period": "60", | |
"EvaluationPeriods": "10", | |
"Threshold": "75", | |
"AlarmActions": [ | |
{ | |
"Ref": "AppServerScaleDownPolicy" | |
} | |
], | |
"Dimensions": [ | |
{ | |
"Name": "AutoScalingGroupName", | |
"Value": { | |
"Ref": "AppServerGroup" | |
} | |
} | |
], | |
"ComparisonOperator": "LessThanThreshold" | |
} | |
}, | |
"ProductionServerWaitHandle": { | |
"Type": "AWS::CloudFormation::WaitConditionHandle" | |
}, | |
"ProductionServerWaitCondition": { | |
"Type": "AWS::CloudFormation::WaitCondition", | |
"DependsOn": "ProductionServer", | |
"Properties": { | |
"Handle": { | |
"Ref": "ProductionServerWaitHandle" | |
}, | |
"Timeout": "300" | |
} | |
} | |
}, | |
"Outputs": { | |
"URL": { | |
"Description": "The URL of the website", | |
"Value": { | |
"Fn::Join": [ | |
"", | |
[ | |
"http://", | |
{ | |
"Fn::GetAtt": [ | |
"uvdLoadBalancer", | |
"DNSName" | |
] | |
} | |
] | |
] | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment