- AWS CloudFormation
- CloudFormation entities
- Template anatomy
- Template Example
- Intrinsic function
- Stack updates - Update Policies
- Large templates management
- Stack Policies
- AWS CloudFormation Helper Scripts
- StackSets - Stack Instance - Permissions
- Service limits
- AWS SAM (Serverless Application Model)
- Example of template.yaml file
- Mappings - Type property / AWS service
AWS CloudFormation
Provides a common language to describe an AWS infrastructure, creates and builds those described resources.
- Based on JSON/YAML templates
- The output of AWS CloudFormation is called a stack. A stack is a collection of AWS resources deployed together as a group.
- To update a stack you can create a changeset, inspect the changes and then run changeset
CloudFormation entities
Stacks
Represents a collection of resources to deploy and manage by AWS CloudFormation.
When you submit a template, the resources you configure are provisioned and then make up the stack itself.
Any modifications to the stack affect underlying resources.
For example, if you remove an AWS::EC2::Instance resource from the template and update the stack, AWS CloudFormation causes the referred instance to terminate.
If you manually update the resource outside of CloudFormation, the result will be inconsistencies between the state CloudFormation expects and the actual resource state. This can cause future stack operations to fail.
Change Sets
Instead of submitting the update directly, you can generate a change set.
A change set is a description of the changes that will occur to a stack submitting the template.
If the changes are acceptable, the change set itself can execute on the stack and implement the proposed modifications.
Permissions
By default CloudFormation functions within the context of the IAM user or role that invoked a stack action.
So, any action that CloudFormation performs is done on your behalf, with your authorizations.
You can provide a service role the stack uses for the create, update, or delete actions.
To create an CloudFormation service role, make sure that the role has a trust policy that allows cloudformation.amazonaws.com
to assume the role.
As a user, your IAM credentials will need to include the ability to pass the role to AWS CloudFormation, using the iam:PassRole
permission.
You can submit a template from a local file or via a URL that points to an object in S3.
If you submit from a local file the template is uploaded on S3, so you need these permissions:
- cloudformation:CreateUploadBucket
- s3:PutObject
- s3:ListBucket
- s3:GetObject
- s3:CreateBucket
Template anatomy
The high-level structure of a template is as follows:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "String Description",
"Metadata": { },
"Parameters": { },
"Mappings": { },
"Conditions": { },
"Transform": { },
"Resources": { },
"Outputs": { }
}
AWSTemplateFormatVersion
Template engine version, always “2010-09-09”
Description
Text description, max 1024 bytes
Metadata
Additional template info, also used by AWS itself.
You cannot update template metadata by itself, you must perform an update to one or more resources when you update the Metadata section.
AWS::CloudFormation:Init
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"packages" : { <yum, apt, python, and others> },
"groups" : { <linux groups> },
"users" : { <linux users> },
"sources" : { "local path", "URL" },
"files" : { <inline file to be written> },
"commands" : { <arbitrary commands to be executed> },
"services" : { <services to be started or stopped on an instance> }
}
}
},
You can organize config keys into configSets, which allow you to call groups of configurations at different times during an instance’s setup process and change the order in which configurations are applied.
AWS::CloudFormation::Interface
This section details how to modify the ordering and presentation of parameters in the AWS CloudFormation console.
It is composed of two sections:
- ParameterGroups: To organize sets of parameters into logical groupings, which are then separated by horizontal lines in the console.
- ParameterLabels: To define friendly names for parameters in the console.
AWS::CloudFormation::Designer
Specifies the visual layout and representation of resources when you design templates in the AWS CloudFormation Designer.
It is not recommended to manually modify this section.
Parameters
Values to pass to the build, ca be set either when you create the stack or when you perform updates
"Parameters": {
"InstanceTypeParam": {
"Type": "String",
"Default": "t2.micro",
"AllowedValues": [ "t2.micro", "m1.small", "m1.large" ],
"Description": "Enter t2.micro, m1.small, or m1.large. Default is t2.micro."
}
}
The Ref intrinsic function can be used to refer to the parameter:
...
"Properties": {
"InstanceType": { "Ref": "InstanceTypeParam" },
...
Supported parameter types:
- String
- Number
- List of numbers
- Comma-delimited list
- AWS parameter types (for AWS account properties like AWS::EC2::KeyPair::KeyName)
- AWS Systems Manager Parameter Store (Systems Manager) parameter types
If a parameter value is sensitive, you can add the NoEcho property, so that the sensitive value will be used normally but will be displayed as asterisks (***).
Pseudoparameters (automatically defined by AWS)
The AWS::Region parameter, for example, resolves to the region code where the stack is being deployed (such as us-east-1).
Mappings
Lookup table for conditional values (only strings allowed).
A common example of mappings usage is to look up Amazon EC2 instance AMI IDs based on the region and architecture type.
To query the values within the mapping you can use the Fn::FindInMap intrinsic function.
"Mappings" : {
"RegionMap" : {
"us-east-1" : { "32" : "ami-6411e20d", "64" : "ami-7a11e213" },
"us-west-1" : { "32" : "ami-c9c7978c", "64" : "ami-cfc7978a" },
"eu-west-1" : { "32" : "ami-37c2f643", "64" : "ami-31c2f645" },
"ap-southeast-1" : { "32" : "ami-66f28c34", "64" : "ami-60f28c32" },
"ap-northeast-1" : { "32" : "ami-9c03a89d", "64" : "ami-a003a8a1" }
}
}
Conditions
Statements to control how and when resources are created.
A common use case would be, for example, to conditionally set an EC2 instance to use a larger instance type if the environment to which you deploy is prod versus dev.
"Conditions" : {
"CreateProdResources" : {"Fn::Equals" : [{"Ref" : "EnvType"}, "prod"]}
},
Transform
Set of macros you can use to reduce the amount of time spent in the authoring process.
Transforms are applied to the template during the change set creation process.
- AWS::Include Transform
Acts as a tool to import template snippets from S3 buckets into the template being developed. When the template is evaluated, a change set is created, and the template snippet is copied from its location and is added to the overall template structure.
You can use this transform anywhere in a template, except the Parameters and AWSTemplateFormatVersion sections. Nested transforms are not supported.{ "Transform" : { "Name" : "AWS::Include", "Parameters" : { "Location" : "s3://MyAmazonS3BucketName/MyFileName.json" } } }
- AWS::Serverless Transform
Can be used to convert AWS Serverless Application Model (AWS SAM) templates to valid AWS CloudFormation templates for deployment.
AWS SAM uses an abbreviated template syntax to deploy serverless applications with Lambda, API Gateway, and DynamoDB.Transform: AWS::Serverless-2016-10-31 Resources: MyServerlessFunctionLogicalID: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: nodejs4.3 CodeUri: 's3://testBucket/mySourceCode.zip'
Resources (required)
What to create, with properties.
A logical ID acts as the resource key, to be referenced in other parts of the template.
{
"Resources": {
"MyBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "MyBucketName1234"
}
}
}
}
Properties can be either optional or required.
Custom Resources
Sometimes custom provisioning logic is required, for example to manage managing resources not currently supported by AWS CloudFormation, interacting with third-party tools, or other situations where more complexity is involved in the provisioning process.
Custom resource providers may be AWS Lambda functions or Amazon Simple Notification Service (Amazon SNS) topics.
Resource Relationships
By default CloudFormation tracks most dependencies between resources.
There are, however, some exceptions, for example, an application server may not function properly until the backend database is up and running.
In this case, you can add a DependsOn attribute to your template to specify the order of creation.
Creation Policies
Instructs CloudFormation not to mark a resource as CREATE_COMPLETE until the resource itself signals back to the service. You can configure the creation policy to require a specific number of signals in a certain amount of time; otherwise, the resource will show CREATE_FAILED.
Wait Conditions
You can use the WaitCondition property to insert arbitrary pauses until resources complete.
Outputs
Values to be returned to the users
"Outputs" : {
"BackupLoadBalancerDNSName" : {
"Description": "The DNSName of the backup load balancer",
"Value" : { "Fn::GetAtt" : [ "BackupLoadBalancer", "DNSName" ]}
}
}
Template Example
This is a complete example of a template, for a DynamoDB table
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "AWS CloudFormation Sample Template DynamoDB_Table: This template demonstrates the creation of a DynamoDB table.",
"Parameters" : {
"HashKeyElementName" : {
"Description" : "HashType PrimaryKey Name",
"Type" : "String",
"AllowedPattern" : "[a-zA-Z0-9]*",
"MinLength": "1",
"MaxLength": "2048",
"ConstraintDescription" : "must contain only alphanumberic characters"
},
"HashKeyElementType" : {
"Description" : "HashType PrimaryKey Type",
"Type" : "String",
"Default" : "S",
"AllowedPattern" : "[S|N]",
"MinLength": "1",
"MaxLength": "1",
"ConstraintDescription" : "must be either S or N"
},
"ReadCapacityUnits" : {
"Description" : "Provisioned read throughput",
"Type" : "Number",
"Default" : "5",
"MinValue": "5",
"MaxValue": "10000",
"ConstraintDescription" : "must be between 5 and 10000"
},
"WriteCapacityUnits" : {
"Description" : "Provisioned write throughput",
"Type" : "Number",
"Default" : "10",
"MinValue": "5",
"MaxValue": "10000",
"ConstraintDescription" : "must be between 5 and 10000"
}
},
"Resources" : {
"myDynamoDBTable" : {
"Type" : "AWS::DynamoDB::Table",
"Properties" : {
"AttributeDefinitions": [ {
"AttributeName" : {"Ref" : "HashKeyElementName"},
"AttributeType" : {"Ref" : "HashKeyElementType"}
} ],
"KeySchema": [
{ "AttributeName": {"Ref" : "HashKeyElementName"}, "KeyType": "HASH" }
],
"ProvisionedThroughput" : {
"ReadCapacityUnits" : {"Ref" : "ReadCapacityUnits"},
"WriteCapacityUnits" : {"Ref" : "WriteCapacityUnits"}
}
}
}
},
"Outputs" : {
"TableName" : {
"Value" : {"Ref" : "myDynamoDBTable"},
"Description" : "Table name of the newly created DynamoDB table"
}
}
}
s
Intrinsic function
-
Fn::Base64
Converts a string into its Base64 equivalent.
The primary purpose is to pass string instructions to an EC2 instance’s UserData property.
{ "Fn::Base64": valueToEncode }
-
Fn::Cidr
Allows you to convert an IP address block, subnet count, and size mask (optional) into a valid CIDR notation.
{ "Fn::Cidr": \[ ipBlock, count, sizeMask ] }
-
Fn::FindInMap
Query information stored in the mapping table.
{ "Fn::FindInMap": \[ "MapName", "TopLevelKey", "SecondLevelKey" ] }
-
Fn::GetAtt
Used to get information from a created resource to be used in other parts of the same template. For example, to get the ARN.
{ "Fn::GetAtt" : \[ "logicalIDOfResource", "attributeName" ] }
-
Fn::GetAZs
Returns a list of availability zones in the region in which the stack is being created.
{ "Fn::GetAZs" : "region" }
-
Fn::ImportValue
Returns the value of an output exported by another stack.
{ "Fn::ImportValue" : sharedValueToImport }
-
Fn::Join
Join string values with a predefined delimiter, which you supply to the function along with a list of strings to join.
{ "Fn::Join" : \[ "delimiter", \[ listOfvalues] ] }
-
Fn::Select
Choose an item in a list based on the zero-based index (out of bounds equals null)
{ "Fn::Select" : \[ index, \[listOfObjects] ] }
-
Fn::Split
Create a list of strings by separating a single string by a known delimiter.
{ "Fn::Split" : \[ "delimiter", "source string" ] }
-
Fn::Sub
Substitutes variables in the format ${MyVarName} with values that you specify.
{ "Fn::Sub" : \[ String, { Var1Name: Var1Value, Var2Name: Var2Value } ] }
-
Ref
Returns the value of the specified parameter or resource.
With resources, will return the name, the ARN or physical ID, depending on the resource type.
{ "Ref" : "logicalName" }
-
Condition Functions:
- Fn::And
- Fn::Equals
- Fn::If
- Fn::Not
- Fn::Or
Stack updates
Update Policies
Can be used to determine how to respond to changes to
AWS::AutoScaling::AutoScalingGroup and AWS::Lambda::Alias resources.
Deletion Policies
Can be used to preserve resources when you delete a stack (set DeletionPolicy to Retain), for example to retain an S3 bucket.
Some resources can instead have a snapshot (set DeletionPolicy to Snapshot).
The following resource types support snapshots:
AWS::EC2::Volume
AWS::ElastiCache::CacheCluster
AWS::ElastiCache::ReplicationGroup
AWS::RDS::DBInstance
AWS::RDS::DBCluster
AWS::Redshift::Cluster
Large templates management
There are two approaches to manage relationships between multiple stacks.
Export and Import Stack Outputs
You can export stack output values and import them into other stacks in the same account and region. For example, create a networking infrastructure in one stack, export the IDs of such resources from this stack and import them into others.
Nesting with the AWS::CloudFormation::Stack Resource
You can manage stacks as resources within the service in AWS CloudFormation.
A single parent stack can create one or more AWS::CloudFormation::Stack resources, which act as child stacks that the parent manages.
Stack Policies
There may be situations where you will want to prevent certain types of updates to stacks themselves. To do so you can assign a stack policy to a stack to allow or deny access to modify certain stack resources, which you can filter by the type of update.
Stack policies apply to all users, regardless of their IAM permissions.
Stack policies are not a replacement for appropriate access control from an IAM policy. Stack policies are an additional fail-safe to prevent accidental updates to critical resources.
AWS CloudFormation Helper Scripts
When you execute custom scripts on EC2 instances as part of your UserData, CloudFormation provides several important helper scripts, located in /opt/aws/bin
.
-
cfn-init
can be used to read init metadata from inside the resource created (packages, users, groups…) for example inside an injected UserData -
cfn-signal
can be used to notify that the instance has completed its configuration, when using a CreationPolicy or a WaitCondition -
cfn-get-metadata
to get arbitrary metadata, supports only top-level keys -
cfn-hup
is a daemon that detects changes in resource metadata and runs user-specified actions when a change is detected
StackSets
CloudFormation StackSets gives users the ability to control, provision, and manage multiple stacks across multiple accounts.
Each stack set contains information about the stacks you deploy to a single target account in one or more regions. You can configure stack sets to deploy to regions in a specific order and how many unsuccessful deployments are required to fail the entire deployment.
The stack set itself exists in one region, and you must manage it there.
Stack Instance
For every account+region pair you need a Stack Instance.
An update to a stack set propagates to all stack instances in all accounts and regions.
Permissions
For an administrator account to deploy to any target accounts, you must create a trust relationship between the accounts.
To do this, you create an IAM role in each account.
The administrator account requires an IAM service role with permissions to execute stack set operations and assume an execution role in any target accounts.
This service role must have a trust policy that allows cloudformation.amazonaws.com.
Target accounts will require an execution role that you create in the administrator account, which the service role can assume.
This execution role will require CloudFormation permissions and permissions to manage any resources you define in the template being deployed by the stack set.
Service limits
Mappings per template | 100 |
---|---|
Outputs per template | 60 |
Parameters per template | 60 |
Resources per template | 200 |
Stacks per account | 200 |
Template body size | 51,200 Bytes (local file) / 460,800 Bytes (S3) |
AWS SAM (Serverless Application Model)
It’s a CloudFormation extension, optimized for serverless.
Every SAM template is “transformed” into a CloudFormation template
- Supports YAML/JSON
- Supports anything AWS CloudFormation supports
- Can mix other non-SAM CloudFormation resources in the same template
- Supports intrinsic functions (i.e., Ref, Sub, Join, Select, Split)
Example of template.yaml file
AWSTemplateFormatVersion: '2010-09-09’
Transform: AWS::Serverless-2016-10-31
Resources:
GetHtmlFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/todo_list.zip
Handler: index.gethtml
Runtime: nodejs6.10
Policies: AmazonDynamoDBReadOnlyAccess
Events:
GetHtml:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
ListTable:
Type: AWS::Serverless::SimpleTable
Mappings - Type property / AWS service
AWS::Serverless::Api | API Gateway (OpenAPI) |
AWS::Serverless::Application | Cloudformation stack |
AWS::Serverless::Connector | Lambda to DynamoDB, SNS, …. |
AWS::Serverless::Function | Lambda+IAM |
AWS::Serverless::GraphQLApi | AWS AppSync GraphQL API |
AWS::Serverless::HttpApi | API Gateway hhtp api |
AWS::Serverless::LayerVersion | layer library for a lambda |
AWS::Serverless::SimpleTable | dynamodb table with single attribute primary key |
AWS::Serverless::StateMachine | Step function |
-
Introduction
- Concepts
- Networking
- Management
- Security, Identity and compliance
- Compute and containers
- Storage
- Databases
- Other services
New pages coming soon...