path | title |
---|---|
/learnings/aws_cloudformation |
Learning AWS: CloudFormation |
- >
- See Also
- Book Recommendations
---
AWSTemplateFormatVersion: "2010-09-09" <-- currently only version (Nov 2017)
Description: <-- human description
String
Metadata: <-- can add config tasks for cfn-init-helper here!
template metadata
Parameters: <-- specify stack parameters, default or allowed values
ParameterLogicalId:
Type: DataType <-- String, Number, List<$WHATEVER>, CommaDelimitedList,
AWS::EC2::AvailabilityZone::Name, AWS::EC2::Image::Id
AWS::EC2::Instance::Id, AWS::EC2::KeyPair::KeyName,
AWS::EC2::SecurityGroup::GroupName, AWS::EC2::SecurityGroup::Id,
AWS::EC2::Subnet::Id, AWS::EC2::Volume::Id, AWS::EC2::VPC::Id,
AWS::Route53::HostedZone::Id
NoEcho: true <-- don't echo this value back
Description: "" <-- human name
Mappings: <-- if you wanted a set of values based on region, you can use this
set of mappings
Conditions: <-- sets a boloean / value you can refer to later to conditionally create resources
set of conditions
Transform: <-- use AWS Serverless Application model here (AWS SAW)
<-- can also do AWS::Include transform to include libraries
set of transforms
Resources: <-- only required section!!!
set of resources
Outputs: <-- lets you mark values for import into other stacks
set of outputs
If you use the AWS Management Console, AWS will pre-populate AWS specific param types with values
If you use CLI you can't
$ aws get-template-summary
--template-body or --template-uli # <-- url must point to an S3 bucket
--stack-name # <-- name or stack ID of stack
--cli-input-json
--generate-cli-skeleton
AWSTemplateFormatVersion: "2010-09-09"
Mappings:
RegionMap:
us-east-1:
"32": "ami-6411e20d"
"64": "ami-7a11e213"
us-west-1:
"32": "ami-c9c7978c"
"64": "ami-cfc7978a"
Resources:
myEC2Instance:
Type: "AWS::EC2::Instance"
Properties:
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", 32]
InstanceType: m1.small
Here's an example of using an environment parameter you pass in to control resources for that deployment environment.
Parameters:
EnvType:
Description: Environment type.
Default: test
Type: String
AllowedValues:
- prod
- test
ConstraintDescription: must specify prod or test.
Conditions:
CreateProdResources: !Equals [ !Ref EnvType, prod ]
Resources:
EC2Instance:
Type: "AWS::EC2::Instance"
Condition: CreateProdResources
Properties:
ImageId: "ami-20b65349"
-
it's a pre-processor:
- you can not mix JSON and YAML
- processor resolves transforms first, then processes the template
-
can not have multiple AWS::Include transforms at both top level and embedded in section
- Fn::FindInMap
- Ref
- Fn::GetAtt <-- get an attribute from a resource in the template
- Fn::ImportValue <-- get values exported from another stack (some restrictions apply)
- Fn::GetAZs
- Fn::Join
- Fn::Split
- Fn::And
- Fn::Equals
- Fn:If
- Fn::Not
- Fn::Sub <-- subs variables in an input string with values you specify. You can use this to construct commands or output values that may not be avail until you construct the stack (but also could use it just to
cat
)
Type: "AWS::EC2::Instance"
Properties:
UserData:
Fn::Base64:
Fn::Join:
- "-"
- - '#!/bin/bash'
- apt-get update
- apt-get upgrade -y
- apt-get install apache2 -y
or can...
Type: "AWS::EC2::Instance"
Properties:
UserData:
Fn::Base64: !Sub |
#!/bin/bash
apt-get update
apt-get upgrade -y
apt-get install apache2 -y
Use some of the tools built into the Amazon AMI or installable via yum: cfn-init
, cfn-get-metadata
.
(Can also use something like cfn-hup
to poll for changes and do action...)
Example:
In UserData
of resource do something like this: if you have a list of packages to install you've hidden in metadata for a resource...
/opt/aws/bin/cfn-init -v --stack { "Ref" : "AWS::StackName" } --resource WebServerInstance --configsets InstallAndRun --region { "Ref" : "AWS::Region" }
Resources:
EC2Instance:
Type: "AWS::EC2::Instance"
Properties:
ImageId: "ami-20b65349"
LB:
Type: "AWS::ElasticLoadBalancing::LoadBalancer"
DependsOn: "EC2Instance"
Instances:
- !Ref EC2Instance
# now imagine the following attribute (doesn't actually exist). Need to get an attribute of an already created resource
PrivateIPs:
- !GetAtt EC2Instance.PublicIp
Cloud Formation calls resource implemented following ways:
- implemented on SNS topic
- AWS lambda function ARN
On request CF includes info like request type and pre-signed S3 URL where custom resource sends responses too.
Send response of SUCCESS or FAILURE to pre-signed S3 URL. Can also provided pre-named pairs.
Stacks = template + parameters for template + additional parameters, per region.
Can receive notification of build complete based on SNS
Can create stack set, and upload template via file upload, point to S3 resource, use premade template.
First do: $ aws cloudformation create-stack-set --stack-set-name ... --template-url https://s3.amazonaws.com/....yml --parameters= WhateverKey=value,OneMore=thing
Then add stack instances...
$ aws cloudformation create-stack-instances --stack-set-name=... --regions=... --cli-input-json...
- Be sure that global resources (S3, IAM) don't conflict if created in > 1 region
- Remember stack set has single template and parameter set
- For testing: create a test stack set with template and a test account you can test this on (then destroy resource after testing)
- StackSets don't currently support transforms
- 20 stack sets in admin account, max 50 stack instances per stack set
- Not immutable infrastructure
- Attempts to be idempotent (does not apply to some resources)
In the documentation the sections of the CloudFormation templates may be documented on seperate places, click the monospaced name that doesn't look like a link but really is to see the documentation for that.