Skip to content

Instantly share code, notes, and snippets.

@robsquires
Created August 2, 2013 13:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robsquires/79de54eeb04d620d5222 to your computer and use it in GitHub Desktop.
Save robsquires/79de54eeb04d620d5222 to your computer and use it in GitHub Desktop.
{
"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