Created by Laurence J MacGuire a.k.a. 刘建明 a.k.a Liu Jian Ming
ThoughtWorks Xi’An, 2017/06/01
What’s a good template that:
Provision everything
Debatably better
Cloudformation wraps all of your infrastructure elements into one logical unit.
---
AWSTemplateFormatVersion: '2010-09-09'
Description: Some Application Stack Template
Parameters:
myParameterName: {}
Resources:
myLogicalResourceName: {}
Outputs:
myOutputName: {}
Conditions:
myConditionName: {}
Mappings:
myMapping: {}
---
Parameters:
myParameterName:
Type: (String,ListOfStrings,Number,Special types)
Default: "XYZ"
Description: "What this parameter means"
AllowedValues: ["option-one", "option-two"]
AllowedPattern: "/^[a-z]+$/"
ConstraintDescription: "Explain the acceptable restrictions"
etc ...
---
Parameters:
ELBSubnets:
Type: List<AWS::EC2::Subnet::Id>
Description: "Which subnets to deploy the ELB in"
Subnet Ids, VPC Ids, SecurityGroupIds, etc. CFN Pre-validates the values, so your stack fails faster. Read more: CFN doco
---
Parameters:
BucketName:
Type: "String"
SNSTopicName:
Type: String
InstanceType:
Type: String
Default: "t2.nano"
AcceptableValues: ["t2.nano", "t2.micro", "t2.small" ...]
MaxInstances:
Type: Number
MinValue: 2
MaxValue: 16
---
Resources:
MyAWSResource:
Type: AWS::Service::Entity
Properties:
FidgetBlobbyThing: "Blah"
DependsOn: []
CreationPolicy: {}
UpdatePolicy: {}
DeletionPolicy: {}
Metadata: {}
Resources:
InstanceGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
MinSize: "2"
MaxSize: "16"
InstanceType: "t2.nano"
LaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
UserData:
"Fn::Base64":
"Fn::Join": [
"\n", [
"#!/usr/bin/bash"
"docker run -e SNS_TOPIC=my-topic -e S3_BUCKET=my-s3-bucket my-image rails s"
]
]
InstanceGroup => InstanceGroup-o98123kjhsdf
Templates can be reused. Resources names cannot.
Each resource has an ID in CFN, and outside of CFN.
---
Resources:
InstanceGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
MinSize: "2"
MaxSize:
Ref: MaxInstances
InstanceType:
Ref: InstanceType
Ref: Parameter
---
Resources:
InstanceGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
LaunchConfiguration:
Ref: LaunchConfig
...
Reference
Return the resource physical id for the given resource logical id
Fn::GetAtt: [ logicalNameOfResource, attributeName ]
Fn::GetAtt: [ “myLoadBalancer”, “DNSName” ]
Resources:
LaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
UserData:
"Fn::Base64":
"Fn::Join": [
"", [
"#!/usr/bin/bash\n"
"docker run -e SNS_TOPIC=", {"Fn::GetAtt", ["my-topic", "TopicName"]}, " -e S3_BUCKET=my-s3-bucket my-image rails s"
]
]
Fn::GetAtt & Ref automatically create dependencies between Parameters and Resources
DependsOn: [“CreateThatFirst”]
If you can’t technically express a dependency, you can explicitely define it using DependsOn.
Conditionals:
IsProduction: !Equals [!Ref EnvType, prod]
Resources:
MyDatabase:
Type: AWS::RDS::Database
Properties:
MultiAZ: !If [IsProduction, "yes", "no" ]
Provides very simple logic. Don’t abuse it.
Outputs:
MyDatabaseUri:
Value:
Fn::GetAtt: ["MyDatabase", "Endpoint.Address"]
CFN is infrastructure building block dependency management
$ # Make sure you've got AWS credentials
$ aws cloudformation create-stack \
--stack-name $(whoami)-example-stack \
--template-body file://example-stack-v1.json \
--parameters file://example-stack-v1-params.json
{
"StackId": "xyz"
}
And go look at the AWS Console
The stack manages a DAG of dependencies
The Stack is stateful
Resources managed within are also stateful
It’s a complete state-machine.
$ # Make sure you've got AWS credentials
$ aws cloudformation update-stack \
--stack-name $(whoami)-example-stack \
--template-body file://example-stack.json \
--parameters file://example-stack-params.json
Updates are stateful as well
Updated elements will potentially affect upstream elements.
Yep. Complete state-machine.
Atomically Create / Update / Delete a stack. And all it’s resources.
Do you feel like managing that graph yourself?
set -e
exit() {
# How do I revert all this?
aws ec2 delete-...
aws ec2 delete-...
aws ec2 delete-...
}
trap exit EXIT
aws ec2 create-vpc ...
aws ec2 create-internet-gateway ...
aws ec2 create-vpc-subnet ...
aws ec2 create-vpc-route-table ...
aws ec2 create-vpc-subnet ...
aws ec2 create-vpc-route-table ...
So use it.
If an AWS feature is NOT in cloudformation (yet), question whether using it is a good idea.
Some tips …
Mostly the same.
Group stack elements by lifecycle
Some things rarely change. Some things change often. Organise accordingly.
Awareness / Control over what is used
Minimise logic. Increase control.
Update Rollback Failed.
An update failed. Then the rollback failed too.
You’re stuck. You have to delete the stack. It really sucks.
If possible, limit the scope of the changes. Limit the URF potential.
comments? rotten tomatoes?