aws cloudformation masterclass

81
Masterclass [email protected] @IanMmmm Ian Massingham — Technical Evangelist AWS CloudFormation

Upload: ian-massingham

Post on 16-Jul-2015

181 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: AWS CloudFormation Masterclass

Masterclass

[email protected]@IanMmmm

Ian Massingham — Technical Evangelist

AWS CloudFormation

Page 2: AWS CloudFormation Masterclass

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

Page 3: AWS CloudFormation Masterclass

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

Page 4: AWS CloudFormation Masterclass

AWS CloudFormation

Don’t reinvent the wheel Declarative & Flexible

Transparent and Open

No Extra Charge

Integration Ready

Customized via Parameters

Page 5: AWS CloudFormation Masterclass

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

Page 6: AWS CloudFormation Masterclass

Agenda

Creating TemplatesUsing a Template to Create and Manage a Stack

Working with the CloudFormation APIWorking with AWS Resources

Bootstrapping Applications and Handling Updates

Page 7: AWS CloudFormation Masterclass

CREATING TEMPLATES

Page 8: AWS CloudFormation Masterclass

CLOUDFORMATION TEMPLATES

Familiar JSON Format

ReusableManage Relationships

Automate Generation Avoid Collisions

Provide Feedback

Write & GoLook Up Resources

Page 9: AWS CloudFormation Masterclass

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”  }  

Page 10: AWS CloudFormation Masterclass

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

Page 11: AWS CloudFormation Masterclass

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

Page 12: AWS CloudFormation Masterclass

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

Page 13: AWS CloudFormation Masterclass

SOURCE CODE REPOSITORY

DNS

CONTINUOUS INTEGRATION SERVER

PROJECT MANAGEMENT SERVER

BUILDS

Page 14: AWS CloudFormation Masterclass

CLOUDFORMATION TEMPLATE

Page 15: AWS CloudFormation Masterclass

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

Page 16: AWS CloudFormation Masterclass

CREATING & MANAGING STACKS

Page 17: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 18: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 19: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 20: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 21: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 22: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 23: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 24: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 25: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 26: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 27: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 28: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 29: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 30: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 31: AWS CloudFormation Masterclass

Incorrect Syntax

Using a template to create and manage a stack

Page 32: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 33: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 34: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 35: AWS CloudFormation Masterclass

Provides Feedback

Using a template to create and manage a stack

Page 36: AWS CloudFormation Masterclass

Provides Feedback

Using a template to create and manage a stack

Page 37: AWS CloudFormation Masterclass

Correct Syntax

Using a template to create and manage a stack

Page 38: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 39: AWS CloudFormation Masterclass

Replaces Resources

Using a template to create and manage a stack

Page 40: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 41: AWS CloudFormation Masterclass

Using a template to create and manage a stack

Page 42: AWS CloudFormation Masterclass

Cleans Up Resources

Using a template to create and manage a stack

Page 43: AWS CloudFormation Masterclass

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

Page 44: AWS CloudFormation Masterclass

Using a template to create and manage a stack via the AWS CLI

Page 45: AWS CloudFormation Masterclass

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

Page 46: AWS CloudFormation Masterclass

$  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

Page 47: AWS CloudFormation Masterclass

$  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

Page 48: AWS CloudFormation Masterclass

WORKING WITH AWS RESOURCES

Page 49: AWS CloudFormation Masterclass

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

Page 50: AWS CloudFormation Masterclass

"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

Page 51: AWS CloudFormation Masterclass

"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

Page 52: AWS CloudFormation Masterclass

• 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:

Page 53: AWS CloudFormation Masterclass

REFERENCING THE PROPERTIES OF ANOTHER RESOURCE

Page 54: AWS CloudFormation Masterclass

{  "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

Page 55: AWS CloudFormation Masterclass

{  "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

Page 56: AWS CloudFormation Masterclass

REFERENCING INPUT PARAMETERS

Page 57: AWS CloudFormation Masterclass

{"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

Page 58: AWS CloudFormation Masterclass

Input Parameters

Page 59: AWS CloudFormation Masterclass

"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

Page 60: AWS CloudFormation Masterclass

CONDITIONAL VALUES

Page 61: AWS CloudFormation Masterclass

{"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

Page 62: AWS CloudFormation Masterclass

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

Page 63: AWS CloudFormation Masterclass

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

Page 64: AWS CloudFormation Masterclass

BOOTSTRAPPING APPLICATIONS AND HANDLING UPDATES

Page 65: AWS CloudFormation Masterclass

"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

Page 66: AWS CloudFormation Masterclass

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

Page 67: AWS CloudFormation Masterclass

"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

Page 68: AWS CloudFormation Masterclass

 "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

Page 69: AWS CloudFormation Masterclass

 "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

Page 70: AWS CloudFormation Masterclass

"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

Page 71: AWS CloudFormation Masterclass

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

Page 72: AWS CloudFormation Masterclass

Find out more here: aws.amazon.com/cloudformation/aws-cloudformation-articles-and-tutorials/

What about Chef? and/or What about Puppet?

Page 73: AWS CloudFormation Masterclass

SUMMARY

Page 74: AWS CloudFormation Masterclass

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

Page 75: AWS CloudFormation Masterclass

RESOURCES YOU CAN USETO LEARN MORE

Page 76: AWS CloudFormation Masterclass

aws.amazon.com/cloudformation/

Page 77: AWS CloudFormation Masterclass

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/

Page 78: AWS CloudFormation Masterclass

{      "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

Page 79: AWS CloudFormation Masterclass

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

Page 80: AWS CloudFormation Masterclass

LONDON

15 APRIL 2015

aws.amazon.com/summits/london/

AWS CloudFormation will be featured in the Deep Dive: Infrastructure-as-Code breakout session

Page 81: AWS CloudFormation Masterclass

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