AWS CloudFormation lets you model, provision, and update a collection of AWS resources with JSON templates. You can manage your Infrastructure as Code and deploy stacks from a single Amazon EC2 instance to multi-tier applications. In this session, we will explore CloudFormation best practices in planning and provisioning your AWS infrastructure. We will cover recent product updates that will help users to make the most of this service and demonstrate new features. This session will benefit both new and experienced users of CloudFormation.
Learning Objectives:
• Learn best practices for managing your infrastructure as code using CloudFormation
• Discover new techniques for making the most of CloudFormation
• Hear about the latest product updates and new features released
Who Should Attend:
• Developers, DevOps, IT Operations, Systems Administrators, Solutions Architects
6. Infrastructure as Code workflow
code
version
control
code
review
integrate deploy
Text Editor
Git/SVN/
Perforce
Review
Tools
Syntax
Validation
Tools
AWS
Services
7. Infrastructure as Code workflow
code
version
control
code
review
integrate deploy
“It’s all software”
Text Editor
Git/SVN/
Perforce
Review
Tools
Syntax
Validation
Tools
AWS
Services
8. In-place Blue-Green
Traffic
• Quicker and more cost efficient
• Updates or replaces resources
• Simpler state and data
migration
• Working stack stays intact for
easy roll backs
• Potentially need to sync data
• Shift traffic to new stack
Templates
Stacks
Update like software
Traffic
9. {
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "AWS CloudFormation Sample Template EC2InstanceSample: **WARNING** This template an Amazon EC2 instances. 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 instance",
"Type" : "String"
},
"Environment": {
"Type" : "String",
"Default" : ”Dev",
"AllowedValues" : [”Mgmt", "Dev", ”Staging", "Prod"],
"Description" : "Environment that the instances will run in.”
}
},
"Mappings" : {
"RegionMap" : {
"us-east-1" : { "AMI" : "ami-7f418316" },
"us-west-2" : { "AMI" : "ami-16fd7026" }
}
},
"Conditions" : {
”EnableEBSOptimized" : {"Fn::Equals" : [{"Ref" : " Environment "}, ”Prod"]},
},
"Resources" : {
"Ec2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"KeyName" : { "Ref" : "KeyName" },
"EbsOptimized " : {"Fn::If": [ " EnableEBSOptimized ", {“true”}, {“false”}]},
"ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]},
"UserData" : { "Fn::Base64" : "80" }
}
}
},
"Outputs" : {
"InstanceId" : {
"Description" : "InstanceId of the newly created EC2 instance",
"Value" : { "Ref" : "Ec2Instance" }
},
"PublicDNS" : {
"Description" : "Public DNSName of the newly created EC2 instance",
"Value" : { "Fn::GetAtt" : [ "Ec2Instance", "PublicDnsName" ] }
}
}
}
10. {
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "AWS CloudFormation Sample Template EC2InstanceSample: **WARNING** This template an Amazon EC2 instances. 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 instance",
"Type" : "String"
},
"Environment": {
"Type" : "String",
"Default" : ”Dev",
"AllowedValues" : [”Mgmt", "Dev", ”Staging", "Prod"],
"Description" : "Environment that the instances will run in.”
}
},
"Mappings" : {
"RegionMap" : {
"us-east-1" : { "AMI" : "ami-7f418316" },
"us-west-2" : { "AMI" : "ami-16fd7026" }
}
},
"Conditions" : {
”EnableEBSOptimized" : {"Fn::Equals" : [{"Ref" : " Environment "}, ”Prod"]},
},
"Resources" : {
"Ec2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"KeyName" : { "Ref" : "KeyName" },
"EbsOptimized " : {"Fn::If": [ " EnableEBSOptimized ", {“true”}, {“false”}]},
"ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]},
"UserData" : { "Fn::Base64" : "80" }
}
}
},
"Outputs" : {
"InstanceId" : {
"Description" : "InstanceId of the newly created EC2 instance",
"Value" : { "Ref" : "Ec2Instance" }
},
"PublicDNS" : {
"Description" : "Public DNSName of the newly created EC2 instance",
"Value" : { "Fn::GetAtt" : [ "Ec2Instance", "PublicDnsName" ] }
}
}
}
HEADERS
PARAMETERS
MAPPINGS
RESOURCES
OUTPUTS
CONDITIONALS
11. {
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "AWS CloudFormation Sample Template EC2InstanceSample: **WARNING** This template an Amazon EC2 instances. 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 instance",
"Type" : "String"
},
"Environment": {
"Type" : "String",
"Default" : ”Dev",
"AllowedValues" : [”Mgmt", "Dev", ”Staging", "Prod"],
"Description" : "Environment that the instances will run in.”
}
},
"Mappings" : {
"RegionMap" : {
"us-east-1" : { "AMI" : "ami-7f418316" },
"us-west-2" : { "AMI" : "ami-16fd7026" }
}
},
"Conditions" : {
”EnableEBSOptimized" : {"Fn::Equals" : [{"Ref" : " Environment "}, ”Prod"]},
},
"Resources" : {
"Ec2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"KeyName" : { "Ref" : "KeyName" },
"EbsOptimized " : {"Fn::If": [ " EnableEBSOptimized ", {“true”}, {“false”}]},
"ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]},
"UserData" : { "Fn::Base64" : "80" }
}
}
},
"Outputs" : {
"InstanceId" : {
"Description" : "InstanceId of the newly created EC2 instance",
"Value" : { "Ref" : "Ec2Instance" }
},
"PublicDNS" : {
"Description" : "Public DNSName of the newly created EC2 instance",
"Value" : { "Fn::GetAtt" : [ "Ec2Instance", "PublicDnsName" ] }
}
}
}
HEADERS
PARAMETERS
MAPPINGS
RESOURCES
OUTPUTS
CONDITIONALS
Description of what your stack does, contains, etc
Provision time values that add structured flexibility and
customization
Pre-defined conditional case statements
Conditional values set via evaluations of passed references
AWS resource definitions
Resulting attributes of stack resource creation
12. {
"Description" : "Create an EC2 instance.”,
"Parameters": {
"KeyName": {
"Description" : "Name of an existing EC2 KeyPair to enable SSH
access into the WordPress web server",
"Type": "AWS::EC2::KeyPair::KeyName"
},
"EC2InstanceType" : {
"Description" : "EC2 instance type",
"Type" : "String",
"Default" : "t2.micro",
"AllowedValues" : [ "t2.micro", "t2.small", "t2.medium" ],
"ConstraintDescription" : "Must be t2.micro, t2.small, t2.medium"
},
},
Template Anatomy - Parameters
17. Avoid manual resource modifications
Avoid making quick-fixes out of band
Update your stacks with CloudFormation
Do not manually change resources
Consider using resource based permissions to
limit ability to make changes directly
23. AWS CloudFormation provides helper scripts
for deployment within your EC2 instances
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.
Amazon EC2
AWS CloudFormation
cfn-init
cfn-hup
cfn-signal
cfn-get-
metadata
Bootstrap your applications using helper scripts
26. Ownership based template design
Limit one template to a single service
Aim for reusability across environments (development, testing, production)
Use nested stacks and cross-stack reference to break up large templates
Organize templates according to team structure/job function/line of business
28. Template File
Defining Stack
The entire infrastructure can be
represented in an AWS
CloudFormation template.
Many Stacks & Environments from One Template
29. Template File
Defining Stack
The entire infrastructure can be
represented in an AWS
CloudFormation template.
Use the version
control system of
your choice to
store and track
changes to this
template
Many Stacks & Environments from One Template
Git
Perforce
SVN
…
30. Template File
Defining Stack
Git
Perforce
SVN
…
Dev
Test
Prod
The entire infrastructure can be
represented in an AWS
CloudFormation template.
Use the version
control system of
your choice to
store and track
changes to this
template
Build out multiple
environments, such
as for Development,
Test, Production and
even DR using the
same template
Many Stacks & Environments from One Template
38. Best Practices Summary
CloudFormation Designer
Avoid manual resource modifications
Preview updates with Change Sets
Learn the intrinsic functions
Bootstrap your applications using UserData and helper scripts
Protect critical resources using stack policies
Ownership based template design
Plan for environment and multi-region
Use Pseudo-Parameters
Use Mappings
Use Conditionals
39. YAML formatted templates
Overview of template structure / basics
New function formatting (!Ref / !GetAZs / !FindInMap)
New Intrinsic Function ( Fn::Sub )
Cross Stack References
New function Fn::ImportValue
Allows use of outputs from unrelated stacks with custom resource
New
Key new features
New
40. CloudFormation - YAML
Why YAML?
Better authoring and readability of templates
Native comment support
Simplification as templates get more and more complex
New
41. Cloudformation - YAML
Resources:
VPC1:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: !Ref VPC1Cidr
Tags:
-
Key: "Name"
Value: "TroubleShooting"
Structure is shown through indentation (one or more spaces).
Sequence items are denoted by a dash
Key value pairs within a map are separated by a colon.
Tips: Use a monospace font, don’t use Tab, save using UTF-8
42. All sections are the same as in a JSON template
---
AWSTemplateFormatVersion: "version date"
Description:
String
Metadata:
template metadata
Parameters:
set of parameters
Mappings:
set of mappings
Conditions:
set of conditions
Resources:
set of resources
Outputs:
set of outputs
CloudFormation – YAML Template Structure
43. Two ways to declare Intrinsic functions: Long and Short
Short Form:
!FindInMap [ MapName, TopLevelKey, SecondLevelKey ]
Long Form:
"Fn::FindInMap" : [ "MapName", "TopLevelKey", "SecondLevelKey"]
Tag = ! (Its not Negation operator)
Few things to note with Tags
You cannot use one tag immediately after another
!Base64 !Sub…
Instead, you can do this
"Fn::Base64": !Sub...
!Select [ !Ref Value, [1,2,3]]
CloudFormation – YAML Function Declaration
44. Fn::Base64 Fn::And
Short !Base64 valueToEncode Short !And [condition]
Long "Fn::Base64": valueToEncode Long "Fn::And": [condition]
Fn::Equals Fn::If
Short !Equals [value_1, value_2] Short !If [condition_name, value_if_true, value_if_false]
Long "Fn::Equals": [value_1, value_2] Long "Fn::If": [condition_name, value_if_true, value_if_false]
Fn::Not Fn::Or
Short !Not [condition] Short !Or [condition, ...]
Long "Fn::Not": [condition] Long "Fn::Or": [condition, ...]
CloudFormation – Intrinsic Functions
45. NewCloudFormation – Fn::Sub
Substitute variables in an input string with values
Function accepts a string or a map as a parameter.
Usage
VarName: ${MyVariableValue}
Literal: ${!LiteralValue}
Use | if you are spanning multiple lines
Available in JSON as well
47. CloudFormation – Cross Stack References
Sharing resources made easy
IAM roles, VPC, Security groups
Add an explicit “Export” declaration to stack output
Use the resource in another stack using a new intrinsic function,
Fn::ImportValue`
Few guidelines:
Export names must be unique within an account and region
Cannot create references across regions
Cannot delete a stack that is referenced by another stack (Dependencies
are communicated in errors)
Outputs cannot be modified or removed as long as it is referenced by a
current stack
New
48. The new intrinsic function for accessing exported outputs.
JSON
{ "Fn::ImportValue" : sharedValueToImport }
YAML
"Fn::ImportValue": sharedValueToImport
!ImportValue sharedValueToImport
CloudFormation – Fn::ImportValue