This presentation was prepared with reveal.js and prez.
Hit 'n'
and 'p'
for next and previous slide.
's'
shows the speaker notes.
Why do you need something like CloudFormation?
(or why not just script it?)
Basic Structure (YAML)
AWSTemplateFormatVersion: "2010-09-09"
Description:
Parameters:
Resources:
Outputs:
This may be the simplest template that produces useful infrastructure!
AWSTemplateFormatVersion: "2010-09-09"
Description: >
Simplest CloudFormation Template - An S3 Bucket
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
Save the template file locally, then create a stack with it on CloudFormation
Give the stack to be created from this template a name.
Review settings and create the stack.
CloudFormation reports stack is being created. Note the stack description.
The S3 bucket is being created
The stack is created and an S3 bucket with a generated name exists.
Let's tag the bucket with a purpose. We'll use a parameter to specify the value.
Parameters:
Purpose: <---------------------- add a parameter "Purpose"
Type: String
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
Tags:
- Key: StackPurpose
Value: !Ref Purpose <--- ref the parameter
Parameters may be constrained, helping to catch invalid data earlier.
Parameters:
Purpose:
Type: String
Description: What is this stack for? <----- describe it!
Default: MakingMoney <-------------- set a default value
AllowedValues: <--------------- constrain allowed values
- MakingMoney
- Demo
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
Tags:
- Key: StackPurpose
Value: !Ref Purpose
Select the existing stack and choose "Update Stack"
Select new template to update stack
Set the new parameter value
Review the "Change Set" specified by your update
CloudFormation begins updating the stack
Update is complete... review S3 bucket tags
Before deleting the stack, put something in the S3 bucket.
In CloudFormation, select the stack and choose Delete Stack
We can't automatically delete a non-empty S3 bucket.
aws cloudformation create-stack --stack-name demo-stack --template-url ... --parameters ...
12 SDKs at time of writing
Terraform resource
Refer to parameters, as in tagged bucket example
Parameters:
Purpose: <----------------------- parameter logical name
Type: String
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
Tags:
- Key: StackPurpose
Value: !Ref Purpose <---- cross-reference
Refer to other resources
Resources:
MyS3Bucket: <------------------------ logical name
Type: AWS::S3::Bucket
MyLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Ref MyS3Bucket <--- provisioned bucket name
Compute values at deployment-time, like string joins
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
MyLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Join ["-", [!Ref MyS3Bucket, logs]]
See also Split, Sub, GetAtt, etc.
Values that provided by context, used with !Ref
!Ref "AWS::Region" <-- region stack is deployed in
!Ref "AWS::StackName" <-- name of stack being deployed
...plus a few others.
CloudFormation's way of reusing and composing stacks
AWS Resources...
CloudFormation's way of reusing and composing stacks
...assembled into a stack...
CloudFormation's way of reusing and composing stacks
...makes stuff you want
Our S3 stack can be nested without modification...
Resources:
FirstBucketStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.../01-parameterless-s3-bucket.yaml
SecondBucketStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.../01-parameterless-s3-bucket.yaml
Our S3 stack can be nested without modification...
Generated names are prefixed with stack context
{stack}-{logical}-{rand}-{logical}-{rand}
Nested stacks show how CloudFormation works
Prefer wide and shallow, not narrow and deep!
How to reference something in a nested stack?
Step 1: Define the value as an output
Resources:
ImageBucket: ...
Outputs:
BucketName:
Description: User upload image bucket
Value: !Ref ImageBucket
How to reference something in a nested stack?
Step 2: Ref the value from the parent template
Resources:
ImageBucketStack: ...
Thumbnailer:
Type: ...
Properties:
BucketName: !GetAtt ImageBucketStack.Outputs.BucketName
Export an output value from one stack
Outputs:
BucketName:
Value: !Ref ImageBucket
Export:
Name: !Sub "${AWS::StackName}-BucketName"
Import it into another with Fn::ImportValue
Parameters:
ImageBucketStackName:...
Resources:
MyResource:
Thumbnailer
"Fn::ImportValue":
!Sub "${ImageBucketStackName}-BucketName"
A boxes-and-arrows UI to draw or render a CloudFormation template
I would show you, but it doesn't work with YAML templates.
Verges on useless because of its limitations.
Announced last year, see what an update will do
Save the change set to be applied later. Awesome?
Unfortunately, when you start using Nested Stacks...
...many of your changes look like this.
Provision all the unsupported things!
Provision all the unsupported things!
for example...
Custom::SalesforceSandbox
Custom::PingdomPing
Custom::SlackNotifier
Custom::BleedingEdgeAwsThing
Custom::DatabaseMigration
Handle create, update and delete messages
Updates may "replace" resources!
Replace = create new then delete old
Example:
AppHealthcheck:
Type: Custom::PingdomPing
Properties:
ServiceToken: !GetAtt PingdomPingCustomResource.Arn
PingTargetUrl: !GetAtt AppUrl
Some tips...
CloudFormation will attempt to rollback on error
Rollback Failed
state could occur if:
Rare, if disciplined!
AWS CodePipeline supports CloudFormation artifacts as of Nov 2016!
Simplified spec and deployment support for AWS Lambda-based applications:
But doesn't work as a CloudFormation Nested Stack!
Create "Portfolios" of "Products"
Lets you pack up CloudFormation templates so that IAM users can have push-button launch.
Blog posts suggest it's aimed more at larger enterprises
Feature | CloudFormation | Terraform |
---|---|---|
Rollback on Error | Y | n |
Cross-Provider | n | Y |
Execution Plan | ~ | Y |
Managed State | Y | n |
IAM Integration | Y | n |
Open Source | n | Y |