aws cloudformation masterclass
TRANSCRIPT
Masterclass
Intended to educate you on how to get the best from AWS services
Show you how things work and how to get things done
A technical deep dive that goes beyond the basics
AWS CloudFormation
An easy way to create & manage a collection of AWS resources Allows orderly and predictable provisioning and updating of resources
Allows you to version control your AWS infrastructure Deploy and update stacks using console, command line or API
You only pay for the resources you create
AWS CloudFormation
Don’t reinvent the wheel Declarative & Flexible
Transparent and Open
No Extra Charge
Integration Ready
Customized via Parameters
CloudFormation - Components & Technology
Template CloudFormation Stack
JSON formatted file
Parameter definition Resource creation
Configuration actions
Configured AWS services
Comprehensive service support Service event aware
Customisable
Framework
Stack creation Stack updates
Error detection and rollback
Agenda
Creating TemplatesUsing a Template to Create and Manage a Stack
Working with the CloudFormation APIWorking with AWS Resources
Bootstrapping Applications and Handling Updates
CREATING TEMPLATES
CLOUDFORMATION TEMPLATES
Familiar JSON Format
ReusableManage Relationships
Automate Generation Avoid Collisions
Provide Feedback
Write & GoLook Up Resources
High Level Template Structure
{ "Description" : "A text description for the template usage", "Parameters": { // A set of inputs used to customize the template per deployment }, "Resources" : { // The set of AWS resources and relationships between them }, "Outputs" : { // A set of values to be made visible to the stack creator }, "AWSTemplateFormatVersion" : "2010-‐09-‐09” }
A Simple Template that creates an EC2 Instance{ "Description": "Create an EC2 instance running the latest Amazon Linux AMI.", "Parameters": { "KeyPair": { "Description": "The EC2 Key Pair to allow SSH access to the instance", "Type": "String" } }, "Resources": { "Ec2Instance": { "Properties": { "ImageId": "ami-‐9d23aeea", "InstanceType" : "m3.medium", "KeyName": { "Ref": "KeyPair" } }, "Type": "AWS::EC2::Instance" } }, "Outputs": { "InstanceId": { "Description": "The InstanceId of the newly created EC2 instance", "Value": { "Ref": "Ec2Instance" } } }, "AWSTemplateFormatVersion": "2010-‐09-‐09"}
You will be asked to enter values for these parameters when you create your stack
A Simple Template that creates an EC2 Instance{ "Description": "Create an EC2 instance running the latest Amazon Linux AMI.", "Parameters": { "KeyPair": { "Description": "The EC2 Key Pair to allow SSH access to the instance", "Type": "String" } }, "Resources": { "Ec2Instance": { "Properties": { "ImageId": "ami-‐9d23aeea", "InstanceType" : "m3.medium", "KeyName": { "Ref": "KeyPair" } }, "Type": "AWS::EC2::Instance" } }, "Outputs": { "InstanceId": { "Description": "The InstanceId of the newly created EC2 instance", "Value": { "Ref": "Ec2Instance" } } }, "AWSTemplateFormatVersion": "2010-‐09-‐09"}
Includes statically defined properties (ImageID & Instance Type) plus a reference to the KeyPair parameter. ImageID is the AMI specific to the region that you will launch this stack in, in this case the eu-west-1 region
A Simple Template that creates an EC2 Instance{ "Description": "Create an EC2 instance running the latest Amazon Linux AMI.", "Parameters": { "KeyPair": { "Description": "The EC2 Key Pair to allow SSH access to the instance", "Type": "String" } }, "Resources": { "Ec2Instance": { "Properties": { "ImageId": "ami-‐9d23aeea", "InstanceType" : "m3.medium", "KeyName": { "Ref": "KeyPair" } }, "Type": "AWS::EC2::Instance" } }, "Outputs": { "InstanceId": { "Description": "The InstanceId of the newly created EC2 instance", "Value": { "Ref": "Ec2Instance" } } }, "AWSTemplateFormatVersion": "2010-‐09-‐09"}
These outputs will be returned once the template has completed execution
SOURCE CODE REPOSITORY
DNS
CONTINUOUS INTEGRATION SERVER
PROJECT MANAGEMENT SERVER
BUILDS
CLOUDFORMATION TEMPLATE
github.com/cloudtools/troposphere
… but remember that a CloudFormation template is just JSON, so any tool that can generate output in JSON can be used
CREATING & MANAGING STACKS
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Incorrect Syntax
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Provides Feedback
Using a template to create and manage a stack
Provides Feedback
Using a template to create and manage a stack
Correct Syntax
Using a template to create and manage a stack
Using a template to create and manage a stack
Replaces Resources
Using a template to create and manage a stack
Using a template to create and manage a stack
Using a template to create and manage a stack
Cleans Up Resources
Using a template to create and manage a stack
aws cloudformation create-‐stack -‐-‐stack-‐name ec2InstanceCmdLineDemo -‐-‐template-‐url https://s3-‐eu-‐west-‐1.amazonaws.com/cf-‐templates-‐1fhelryvrdrbr-‐eu-‐west-‐1/2014174d0r-‐ec2Instance.template -‐-‐parameters ParameterKey=KeyPair,ParameterValue=ManagementKeyPair
arn:aws:cloudformation:eu-‐west-‐1:554625704737:stack/ec2InstanceCmdLineDemo/42cc6150-‐fad7-‐11e3-‐8f4d-‐5017e1aef4e7
Using a template to create and manage a stack via the AWS CLI
Returns the details of the created stack, in the output format of your choice
Using a template to create and manage a stack via the AWS CLI
cancel-‐update-‐stack get-‐stack-‐policycreate-‐stack get-‐templatedelete-‐stack list-‐stack-‐resourcesdescribe-‐stack-‐events list-‐stacksdescribe-‐stack-‐resource set-‐stack-‐policydescribe-‐stack-‐resources update-‐stackdescribe-‐stacks validate-‐template
$ aws cloudformation update-‐stack help
Other AWS CLI actions for CloudFormation
As usual, you can get more details via the AWS CLI
$ aws cloudformation update-‐stack help
SYNOPSIS update-‐stack -‐-‐stack-‐name <value> [-‐-‐template-‐body <value>] [-‐-‐template-‐url <value>] [-‐-‐use-‐previous-‐template | -‐-‐no-‐use-‐previous-‐template] [-‐-‐stack-‐policy-‐during-‐update-‐body <value>] [-‐-‐stack-‐policy-‐during-‐update-‐url <value>] [-‐-‐parameters <value>] [-‐-‐capabilities <value>] [-‐-‐stack-‐policy-‐body <value>] [-‐-‐stack-‐policy-‐url <value>] [-‐-‐notification-‐arns <value>]
Help via the AWS CLI
$ aws cloudformation update-‐stack help
SYNOPSIS update-‐stack -‐-‐stack-‐name <value> [-‐-‐template-‐body <value>] [-‐-‐template-‐url <value>] [-‐-‐use-‐previous-‐template | -‐-‐no-‐use-‐previous-‐template] [-‐-‐stack-‐policy-‐during-‐update-‐body <value>] [-‐-‐stack-‐policy-‐during-‐update-‐url <value>] [-‐-‐parameters <value>] [-‐-‐capabilities <value>] [-‐-‐stack-‐policy-‐body <value>] [-‐-‐stack-‐policy-‐url <value>] [-‐-‐notification-‐arns <value>]
Built using the
CloudFormation API
CloudFormation API Reference : docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/Welcome.html
WORKING WITH AWS RESOURCES
Designed to use your existing experience with AWS
Each resource has a set of parameters with names that are identical to the names used to create the
resources through their native API
Template reference: docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-reference.html
"myVolume" : { "Type" : "AWS::EC2::Volume", "Properties" : { "Size" : "10", "SnapshotId" : "snap-‐7b8fd361", "AvailabilityZone" : "eu-‐west-‐1a" } }
This example defines an Amazon EBS Volume with a logical name ‘myVolume’. Its type is "AWS::EC2::Volume”
If you’ve used EBS previously, the properties should look very familiar
"InstanceSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable SSH access via port 22", "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : "0.0.0.0/0" } ] } }
Creating a Security Group resource
• Auto Scaling• Amazon CloudFront• AWS CloudWatch• Amazon DynamoDB• Amazon EC2• Amazon ElastiCache• AWS Elastic Beanstalk• AWS Elastic Load Balancing• AWS Identity and Access Management
• Amazon RDS• Amazon Redshift• Amazon Route 53• Amazon S3• Amazon SimpleDB• Amazon SNS• Amazon SQS• Amazon VPC
Supported AWS Services:
REFERENCING THE PROPERTIES OF ANOTHER RESOURCE
{ "Resources" : { "Ec2Instance" : { "Type" : "AWS::EC2::Instance", "Properties" : { "SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ], "KeyName" : "mykey", "ImageId" : "ami-‐7a11e213” } }, "InstanceSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable SSH access via port 22", "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" :"0.0.0.0/0" } ] } } } }
Reference
Function
{ "Resources" : { "Ec2Instance" : { "Type" : "AWS::EC2::Instance", "Properties" : { "SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" }, , "MyExistingSG" ], "KeyName" : "mykey", "ImageId" : "ami-‐7a11e213" } }, "InstanceSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable SSH access via port 22", "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" :"0.0.0.0/0" } ] } } } }
Literal
References
REFERENCING INPUT PARAMETERS
{"Parameters" : { "KeyPair" : { "Description" : "The EC2 Key Pair to allow SSH access to the instance", "Type" : "String" },"Resources" : { "Ec2Instance" : { "Type" : "AWS::EC2::Instance", "Properties" : { "SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" }], "KeyName" : { "Ref" : "KeyPair"}, "ImageId" : "" } }, … } }
Input Parameters
Input Parameters
"WordPressUser": { "Default": "admin", "Description" : "The WordPress database admin account username", "Type": "String", "MinLength": "1", "MaxLength": "16", "AllowedPattern" : "[a-‐zA-‐Z][a-‐zA-‐Z0-‐9]*" },
Validate your input parameters with :
Maxlength, MinLength, MaxValue, MinValue, AllowedPattern, AllowedValues
Input Parameters
CONDITIONAL VALUES
{"Mappings" : { "RegionMap" : { "us-‐east-‐1" : { "AMI" : "ami-‐76f0061f" }, "us-‐west-‐1" : { "AMI" : "ami-‐655a0a20" }, "eu-‐west-‐1" : { "AMI" : "ami-‐7fd4e10b" }, "ap-‐southeast-‐1" : { "AMI" : "ami-‐72621c20" }, "ap-‐northeast-‐1" : { "AMI" : "ami-‐8e08a38f" } } }, "Resources" : { "Ec2Instance" : { "Type" : "AWS::EC2::Instance", "Properties" : { "KeyName" : { "Ref" : "KeyName" }, “ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]} } } } }
Mappings
Other intrinsic functions and pseudo parameters
Pseudo parametersAWS::NotificationARNs
AWS::RegionAWS::StackId
AWS::StackName
Intrinsic functionsFn::Base64
Fn::FindInMapFn::GetAttFn::GetAZs
Fn::JoinFn::Select
Ref
Working with non-AWS Resources
Defining custom resources allows you to include non-AWS resources in a
CloudFormation stack
More on Custom Resources in ‘AWS CloudFormation under the Hood’ from re:Invent 2013: http://youtu.be/ZhGMaw67Yu0 AWS CloudFormation Custom Resource Walkthrough documentation:
docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-walkthrough.html
BOOTSTRAPPING APPLICATIONS AND HANDLING UPDATES
"Resources" : { "Ec2Instance" : { "Type" : "AWS::EC2::Instance", "Properties" : { "KeyName" : { "Ref" : "KeyName" }, "SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ], "ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]}, "UserData" : { "Fn::Base64" : { "Fn::Join" : ["",[ "#!/bin/bash -‐ex","\n", "yum -‐y install gcc-‐c++ make","\n", "yum -‐y install mysql-‐devel sqlite-‐devel","\n", "yum -‐y install ruby-‐rdoc rubygems ruby-‐mysql ruby-‐devel","\n", "gem install -‐-‐no-‐ri -‐-‐no-‐rdoc rails","\n", "gem install -‐-‐no-‐ri -‐-‐no-‐rdoc mysql","\n", "gem install -‐-‐no-‐ri -‐-‐no-‐rdoc sqlite3","\n", "rails new myapp","\n", "cd myapp","\n", "rails server -‐d","\n", "curl -‐X PUT -‐H 'Content-‐Type:' -‐-‐data-‐binary '{\"Status\" : \"SUCCESS\",", "\"Reason\" : \"The application myapp is ready\",", "\"UniqueId\" : \"myapp\",", "\"Data\" : \"Done\"}' ", "\"", {"Ref" : "WaitForInstanceWaitHandle"},"\"\n" ]]}} } }
Option 1: Continue to use EC2 UserData, which is available as a property of AWS::EC2::Instance resources
cfn-hup
cfn-signal
cfn-get-metadata
Amazon EC2AWS CloudFormation
cfn-init
Metadata Key — AWS::CloudFormation::Init
Cfn-init reads this metadata key and installs the packages listed in this key (e.g., httpd, mysql, and php). Cfn-init also retrieves and expands files listed as sources.
Option 2: AWS CloudFormation provides helper scripts for deployment within your EC2 instances
"Resources" : { "WebServer": { "Type": "AWS::EC2::Instance", "Metadata" : { "Comment1" : "Configure the bootstrap helpers to install the Apache Web Server and PHP", "Comment2" : "The website content is downloaded from the CloudFormationPHPSample.zip file",
"AWS::CloudFormation::Init" : { "config" : { "packages" : { "yum" : { "mysql" : [], "mysql-‐server" : [], "mysql-‐libs" : [], "httpd" : [], "php" : [], "php-‐mysql" : [] } },
"sources" : { "/var/www/html" : "https://s3.amazonaws.com/cloudformation-‐examples/CloudFormationPHPSample.zip" } } } }
Installing Packages
& Expanding Files
"Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "KeyName" : { "Ref" : "KeyName" }, "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -‐v\n", "yum update -‐y aws-‐cfn-‐bootstrap\n",
"# Install packages\n", "/opt/aws/bin/cfn-‐init -‐s ", { "Ref" : "AWS::StackName" }, " -‐r WebServer ", " -‐-‐region ", { "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-‐init'\n" ]]}} } },
The UserData key allows you to execute shell commands.
This template issues two shell commands: the first command installs the AWS CloudFormation helper scripts; the second executes the cfn-init script.
Installing & executing
CloudFormation helper
"files" : { "/tmp/setup.mysql" : { "content" : { "Fn::Join" : ["", [ "CREATE DATABASE ", { "Ref" : "DBName" }, ";\n", "GRANT ALL ON ", { "Ref" : "DBName" }, ".* TO '", { "Ref" : "DBUsername" }, "'@localhost IDENTIFIED BY '", { "Ref" : "DBPassword" }, "';\n" ]]}, "mode" : "000644", "owner" : "root", "group" : "root" } }
The files key allows you to write files to the instance filesystem
Creating files on
Instance Filesystems
"services" : { "sysvinit" : { "mysqld" : { "enabled" : "true", "ensureRunning" : "true" }, "httpd" : { "enabled" : "true", "ensureRunning" : "true" } }
The services key allows you ensures that the services are not only running when cfn-init finishes (ensureRunning is set to true); but that they are also restarted upon reboot (enabled is set to true).
Controlling Services
More on Deploying Applications with AWS CloudFormation: docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/deploying.applications.html
Yes! All this functionality is available for
Windows instances too!
Bootstrapping AWS CloudFormation Windows Stacks: docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-windows-stacks-bootstrapping.html
Find out more here: aws.amazon.com/cloudformation/aws-cloudformation-articles-and-tutorials/
What about Chef? and/or What about Puppet?
SUMMARY
An easy way to create & manage a collection of AWS resources1
Allows orderly and predictable provisioning and updating of resources2
Allows you to version control your AWS infrastructure 3
Deploy and update stacks using console, command line or API4
RESOURCES YOU CAN USETO LEARN MORE
aws.amazon.com/cloudformation/
Getting Started with AWS CloudFormation:
aws.amazon.com/cloudformation/getting-started/
AWS CloudFormation Templates & Samples:
aws.amazon.com/cloudformation/aws-cloudformation-templates/
AWS cfncluster HPC deployment framework:
github.com/awslabs/cfncluster/
{ "AWSTemplateFormatVersion" : "2010-‐09-‐09",
"Description" : "AWS CloudFormation Sample Template WordPress_Multi_AZ: WordPress is web software you can use to create a beautiful website or blog. This template installs a highly-‐available, scalable WordPress deployment using a multi-‐az Amazon RDS database instance for storage. It demonstrates using the AWS CloudFormation bootstrap scripts to deploy WordPress. **WARNING** This template creates an Amazon EC2 instance, an Elastic Load Balancer and an Amazon RDS database instance. You will be billed for the AWS resources used if you create a stack from this template.",
"Parameters" : {
"KeyName": { "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances", "Type": "AWS::EC2::KeyPair::KeyName", "ConstraintDescription" : "must be the name of an existing EC2 KeyPair." },
"InstanceType" : { "Description" : "WebServer EC2 instance type", "Type" : "String", "Default" : "m1.small", "AllowedValues" : [ "t1.micro", "t2.micro", "t2.small", "t2.medium", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"] , "ConstraintDescription" : "must be a valid EC2 instance type." },
"SSHLocation": { "Description": "The IP address range that can be used to SSH to the EC2 instances", "Type": "String", "MinLength": "9", "MaxLength": "18", "Default": "0.0.0.0/0", "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x." },
"DBClass" : { "Description" : "Database instance class", "Type" : "String", "Default" : "db.m1.small", "AllowedValues" : [ "db.t1.micro", "db.m1.small", "db.m1.medium", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge", "db.m3.medium", "db.m3.large", "db.m3.xlarge", "db.m3.2xlarge", "db.r3.large", "db.r3.xlarge", "db.r3.2xlarge", "db.r3.4xlarge", "db.r3.8xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge", "db.cr1.8xlarge"] , "ConstraintDescription" : "must select a valid database instance type." },
"DBName" : { "Default": "wordpressdb", "Description" : "The WordPress database name", "Type": "String", "MinLength": "1", "MaxLength": "64", "AllowedPattern" : "[a-‐zA-‐Z][a-‐zA-‐Z0-‐9]*", "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters." },
"DBUser" : { "NoEcho": "true", "Description" : "The WordPress database admin account username", "Type": "String", "MinLength": "1", "MaxLength": "16", "AllowedPattern" : "[a-‐zA-‐Z][a-‐zA-‐Z0-‐9]*", "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters." },
"DBPassword" : { "NoEcho": "true", "Description" : "The WordPress database admin account password", "Type": "String", "MinLength": "8", "MaxLength": "41", "AllowedPattern" : "[a-‐zA-‐Z0-‐9]*", "ConstraintDescription" : "must contain only alphanumeric characters." },
"MultiAZDatabase": { "Default": "false", "Description" : "Create a Multi-‐AZ MySQL Amazon RDS database instance", "Type": "String", "AllowedValues" : [ "true", "false" ], "ConstraintDescription" : "must be either true or false." },
"WebServerCapacity": { "Default": "1", "Description" : "The initial number of WebServer instances", "Type": "Number", "MinValue": "1", "MaxValue": "5", "ConstraintDescription" : "must be between 1 and 5 EC2 instances." },
"DBAllocatedStorage" : { "Default": "5", "Description" : "The size of the database (Gb)", "Type": "Number", "MinValue": "5", "MaxValue": "1024", "ConstraintDescription" : "must be between 5 and 1024Gb." } },
"Mappings" : { "AWSInstanceType2Arch" : { "t1.micro" : { "Arch" : "PV64" }, "t2.micro" : { "Arch" : "HVM64" }, "t2.small" : { "Arch" : "HVM64" }, "t2.medium" : { "Arch" : "HVM64" }, "m1.small" : { "Arch" : "PV64" }, "m1.medium" : { "Arch" : "PV64" }, "m1.large" : { "Arch" : "PV64" }, "m1.xlarge" : { "Arch" : "PV64" }, "m2.xlarge" : { "Arch" : "PV64" }, "m2.2xlarge" : { "Arch" : "PV64" }, "m2.4xlarge" : { "Arch" : "PV64" }, "m3.medium" : { "Arch" : "HVM64" }, "m3.large" : { "Arch" : "HVM64" }, "m3.xlarge" : { "Arch" : "HVM64" }, "m3.2xlarge" : { "Arch" : "HVM64" }, "c1.medium" : { "Arch" : "PV64" }, "c1.xlarge" : { "Arch" : "PV64" }, "c3.large" : { "Arch" : "HVM64" }, "c3.xlarge" : { "Arch" : "HVM64" }, "c3.2xlarge" : { "Arch" : "HVM64" }, "c3.4xlarge" : { "Arch" : "HVM64" }, "c3.8xlarge" : { "Arch" : "HVM64" }, "c4.large" : { "Arch" : "HVM64" }, "c4.xlarge" : { "Arch" : "HVM64" }, "c4.2xlarge" : { "Arch" : "HVM64" }, "c4.4xlarge" : { "Arch" : "HVM64" }, "c4.8xlarge" : { "Arch" : "HVM64" }, "g2.2xlarge" : { "Arch" : "HVMG2" }, "r3.large" : { "Arch" : "HVM64" },
"r3.xlarge" : { "Arch" : "HVM64" }, "r3.2xlarge" : { "Arch" : "HVM64" }, "r3.4xlarge" : { "Arch" : "HVM64" }, "r3.8xlarge" : { "Arch" : "HVM64" }, "i2.xlarge" : { "Arch" : "HVM64" }, "i2.2xlarge" : { "Arch" : "HVM64" }, "i2.4xlarge" : { "Arch" : "HVM64" }, "i2.8xlarge" : { "Arch" : "HVM64" }, "hi1.4xlarge" : { "Arch" : "HVM64" }, "hs1.8xlarge" : { "Arch" : "HVM64" }, "cr1.8xlarge" : { "Arch" : "HVM64" }, "cc2.8xlarge" : { "Arch" : "HVM64" } } , "AWSRegionArch2AMI" : { "us-‐east-‐1" : {"PV64" : "ami-‐8e682ce6", "HVM64" : "ami-‐146e2a7c", "HVMG2" : "ami-‐7200461a"}, "us-‐west-‐2" : {"PV64" : "ami-‐9fc29baf", "HVM64" : "ami-‐dfc39aef", "HVMG2" : "ami-‐0b78203b"}, "us-‐west-‐1" : {"PV64" : "ami-‐f49089b1", "HVM64" : "ami-‐42908907", "HVMG2" : "ami-‐244b5361"}, "eu-‐west-‐1" : {"PV64" : "ami-‐7b3db00c", "HVM64" : "ami-‐9d23aeea", "HVMG2" : "ami-‐4d7cf03a"}, "eu-‐central-‐1" : {"PV64" : "ami-‐0600331b", "HVM64" : "ami-‐04003319", "HVMG2" : "NOT_SUPPORTED"}, "ap-‐northeast-‐1" : {"PV64" : "ami-‐3c87993d", "HVM64" : "ami-‐18869819", "HVMG2" : "ami-‐2e90892f"}, "ap-‐southeast-‐1" : {"PV64" : "ami-‐58ba910a", "HVM64" : "ami-‐96bb90c4", "HVMG2" : "ami-‐3e78526c"}, "ap-‐southeast-‐2" : {"PV64" : "ami-‐1500742f", "HVM64" : "ami-‐d50773ef", "HVMG2" : "ami-‐315e2a0b"}, "sa-‐east-‐1" : {"PV64" : "ami-‐fd9925e0", "HVM64" : "ami-‐af9925b2", "HVMG2" : "NOT_SUPPORTED"}, "cn-‐north-‐1" : {"PV64" : "ami-‐8a1d8fb3", "HVM64" : "ami-‐981d8fa1", "HVMG2" : "NOT_SUPPORTED"} }
},
"Conditions" : { "Is-‐EC2-‐VPC" : { "Fn::Or" : [ {"Fn::Equals" : [{"Ref" : "AWS::Region"}, "eu-‐central-‐1" ]}, {"Fn::Equals" : [{"Ref" : "AWS::Region"}, "cn-‐north-‐1" ]}]}, "Is-‐EC2-‐Classic" : { "Fn::Not" : [{ "Condition" : "Is-‐EC2-‐VPC"}]} },
"Resources" : {
"ElasticLoadBalancer" : { "Type" : "AWS::ElasticLoadBalancing::LoadBalancer", "Properties" : { "AvailabilityZones" : { "Fn::GetAZs" : "" }, "CrossZone" : "true", "LBCookieStickinessPolicy" : [ { "PolicyName" : "CookieBasedPolicy", "CookieExpirationPeriod" : "30" } ], "Listeners" : [ { "LoadBalancerPort" : "80", "InstancePort" : "80", "Protocol" : "HTTP", "PolicyNames" : [ "CookieBasedPolicy" ] } ], "HealthCheck" : { "Target" : "HTTP:80/wordpress/wp-‐admin/install.php", "HealthyThreshold" : "2", "UnhealthyThreshold" : "5", "Interval" : "10", "Timeout" : "5" } } },
"WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP access via port 80 locked down to the load balancer + SSH access", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "SourceSecurityGroupOwnerId" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"]},"SourceSecurityGroupName" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.GroupName"]}}, {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}} ] } },
"WebServerGroup" : { "Type" : "AWS::AutoScaling::AutoScalingGroup", "Properties" : { "AvailabilityZones" : { "Fn::GetAZs" : "" }, "LaunchConfigurationName" : { "Ref" : "LaunchConfig" }, "MinSize" : "1", "MaxSize" : "5", "DesiredCapacity" : { "Ref" : "WebServerCapacity" }, "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ] }, "CreationPolicy" : { "ResourceSignal" : { "Timeout" : "PT15M" } }, "UpdatePolicy": { "AutoScalingRollingUpdate": { "MinInstancesInService": "1", "MaxBatchSize": "1", "PauseTime" : "PT15M", "WaitOnResourceSignals": "true" } } },
"LaunchConfig": { "Type" : "AWS::AutoScaling::LaunchConfiguration", "Metadata" : { "AWS::CloudFormation::Init" : { "configSets" : { "wordpress_install" : ["install_cfn", "install_wordpress" ] }, "install_cfn" : { "files": { "/etc/cfn/cfn-‐hup.conf": { "content": { "Fn::Join": [ "", [ "[main]\n", "stack=", { "Ref": "AWS::StackId" }, "\n", "region=", { "Ref": "AWS::Region" }, "\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" }, "/etc/cfn/hooks.d/cfn-‐auto-‐reloader.conf": { "content": { "Fn::Join": [ "", [ "[cfn-‐auto-‐reloader-‐hook]\n", "triggers=post.update\n", "path=Resources.LaunchConfig.Metadata.AWS::CloudFormation::Init\n", "action=/opt/aws/bin/cfn-‐init -‐v ", " -‐-‐stack ", { "Ref" : "AWS::StackName" }, " -‐-‐resource LaunchConfig ", " -‐-‐configsets wordpress_install ", " -‐-‐region ", { "Ref" : "AWS::Region" }, "\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" } }, "services" : { "sysvinit" : { "cfn-‐hup" : { "enabled" : "true", "ensureRunning" : "true",
"files" : ["/etc/cfn/cfn-‐hup.conf", "/etc/cfn/hooks.d/cfn-‐auto-‐reloader.conf"]} } } },
"install_wordpress" : { "packages" : { "yum" : { "php" : [], "php-‐mysql" : [], "mysql" : [], "httpd" : [] } }, "sources" : { "/var/www/html" : "http://wordpress.org/latest.tar.gz" }, "files" : { "/tmp/create-‐wp-‐config" : { "content" : { "Fn::Join" : [ "", [ "#!/bin/bash\n", "cp /var/www/html/wordpress/wp-‐config-‐sample.php /var/www/html/wordpress/wp-‐config.php\n", "sed -‐i \"s/'database_name_here'/'",{ "Ref" : "DBName" }, "'/g\" wp-‐config.php\n", "sed -‐i \"s/'username_here'/'",{ "Ref" : "DBUser" }, "'/g\" wp-‐config.php\n", "sed -‐i \"s/'password_here'/'",{ "Ref" : "DBPassword" }, "'/g\" wp-‐config.php\n", "sed -‐i \"s/'localhost'/'",{ "Fn::GetAtt" : [ "DBInstance", "Endpoint.Address" ] }, "'/g\" wp-‐config.php\n" ]]}, "mode" : "000500", "owner" : "root", "group" : "root" } }, "commands" : { "01_configure_wordpress" : { "command" : "/tmp/create-‐wp-‐config", "cwd" : "/var/www/html/wordpress" } }, "services" : { "sysvinit" : { "httpd" : { "enabled" : "true", "ensureRunning" : "true" } } } } } }, "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "KeyName" : { "Ref" : "KeyName" }, "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -‐xe\n", "yum update -‐y aws-‐cfn-‐bootstrap\n",
"/opt/aws/bin/cfn-‐init -‐v ", " -‐-‐stack ", { "Ref" : "AWS::StackName" }, " -‐-‐resource LaunchConfig ", " -‐-‐configsets wordpress_install ", " -‐-‐region ", { "Ref" : "AWS::Region" }, "\n",
"/opt/aws/bin/cfn-‐signal -‐e $? ", " -‐-‐stack ", { "Ref" : "AWS::StackName" }, " -‐-‐resource WebServerGroup ", " -‐-‐region ", { "Ref" : "AWS::Region" }, "\n" ]]}} } },
"DBSecurityGroup": { "Type": "AWS::RDS::DBSecurityGroup", "Condition" : "Is-‐EC2-‐Classic", "Properties": { "DBSecurityGroupIngress": { "EC2SecurityGroupName": { "Ref": "WebServerSecurityGroup" } }, "GroupDescription": "database access" } },
"DBEC2SecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Condition" : "Is-‐EC2-‐VPC", "Properties" : { "GroupDescription": "Open database for access", "SecurityGroupIngress" : [{ "IpProtocol" : "tcp", "FromPort" : "3306", "ToPort" : "3306", "SourceSecurityGroupName" : { "Ref" : "WebServerSecurityGroup" } }] } },
"DBInstance" : { "Type": "AWS::RDS::DBInstance", "Properties": { "DBName" : { "Ref" : "DBName" }, "Engine" : "MySQL", "MultiAZ" : { "Ref": "MultiAZDatabase" }, "MasterUsername" : { "Ref" : "DBUser" }, "MasterUserPassword": { "Ref" : "DBPassword" }, "DBInstanceClass" : { "Ref" : "DBClass" }, "AllocatedStorage" : { "Ref" : "DBAllocatedStorage" }, "VPCSecurityGroups": { "Fn::If" : [ "Is-‐EC2-‐VPC", [ { "Fn::GetAtt": [ "DBEC2SecurityGroup", "GroupId" ] } ], { "Ref" : "AWS::NoValue"}]}, "DBSecurityGroups": { "Fn::If" : [ "Is-‐EC2-‐Classic", [ { "Ref": "DBSecurityGroup" } ], { "Ref" : "AWS::NoValue"}]} } } },
"Outputs" : { "WebsiteURL" : { "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}, "/wordpress" ]]}, "Description" : "WordPress Website" } } }
CloudFormation Template to Deploy Wordpress
https://s3-us-west-1.amazonaws.com/cloudformation-templates-us-west-1/WordPress_Multi_AZ.template
Certification
aws.amazon.com/certification
Self-Paced Labs
aws.amazon.com/training/self-paced-labs
Try products, gain new skills, and get hands-on practice working
with AWS technologies
aws.amazon.com/training
Training
Validate your proven skills and expertise with the AWS platform
Build technical expertise to design and operate scalable, efficient applications on AWS
AWS Training & Certification
LONDON
15 APRIL 2015
aws.amazon.com/summits/london/
AWS CloudFormation will be featured in the Deep Dive: Infrastructure-as-Code breakout session
Follow us fo
r more
events
& webina
rs
@AWScloud for Global AWS News & Announcements
@AWS_UKI for local AWS events & news
@IanMmmmIan Massingham — Technical Evangelist