What is CloudFormation
- Create: Create aws infrastructure based on a template/blueprint
- Update: update the aws infrastructure
- Delete: can any aws infrastructure you've created
Terminology
Change Set
Before updating a Stack, you can generate a changeset
A changeset allows you to see how changes will impact your running resources.
This can be very important for live systems.
Tempalte
Resources
The only required field in Template.
Example:
{ "Resources": { "MyEc2Instance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": "ami-43571250", "instanceType": "t2.micro" } } }
CloudFormation Features
Intrinsic Functions
Built-in functions that help you manage your stacks
Join:
Appends a set of values into a single value
Read: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html
Example:
Resources: EC2I1P0OV: Type: 'AWS::EC2::Instance' Properties: InstanceType: t2.micro ImageId: ami-0d5eff06f840b45e9 Tags: - Key: Name Value: !Join ["-*-", [Something, is, really, bigger]]
Multiple Reourses
We need to make sure creating/deleting the resouces in correct order, otherwise it won't work.
For example: We have EC2 instance with a security group to open port 22 (SSH).
Security group must be created first, then EC2 instance.
Resources: EC2I53H4C: Type: 'AWS::EC2::Instance' Properties: InstanceType: t2.micro ImageId: ami-0d5eff06f840b45e9 Tags: - Key: Name Value: !Join ["-", [Something, bigger, than, yourself]] SecurityGroups: - !Ref 'MySG' MySG: Type: "AWS::EC2::SecurityGroup" Properties: GroupDescription: Enable SSH access via port 22 SecurityGroupIngress: - CidrIp: 0.0.0.0/0 FromPort: '22' IpProtocol: tcp ToPort: '22'
After stack created, you can see from EC2 instance, has linked to newly created Security group:
Pseudo Parameters
Parameters that are predefined by CloudFormation
Similar to Environment Variables, can be relied upon to be set correctly
Reference the parameters with the Ref Intrinsic Function.
Read: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html
Resources: EC2I53H4C: Type: 'AWS::EC2::Instance' Properties: InstanceType: t2.micro ImageId: ami-0d5eff06f840b45e9 Tags: - Key: Name Value: !Join - "" - - "EC2 Instance For" - !Ref AWS::Region SecurityGroups: - !Ref 'MySG' MySG: Type: "AWS::EC2::SecurityGroup" Properties: GroupDescription: Enable SSH access via port 22 SecurityGroupIngress: - CidrIp: 0.0.0.0/0 FromPort: '22' IpProtocol: tcp ToPort: '22'
Mappings
Mappings enable you to use an input balue to determine another value.
For example: How to determine the AMI ID based on the region? Mappings!
To solve this,
1. Pseudo Parameters
2. Intrinsic Functions - FindInMap
3. Mappings
{ "Fn::FindInMap" : [ "MapName", "TopLevelKey", "SecondLevelKey"] }
Define the Mappings In JSON:
Use the Mapping:
For YAML:
Example:
Mappings: RegionMap: us-east-1: AMI: ami-0d5eff06f840b45e9 us-west-1: AMI: ami-bf5540df eu-west-1: AMI: ami-3bfab942 ap-southeast-1: AMI: ami-e2adf99e ap-southeast-2: AMI: ami-43874721 Resources: Ec2Instance: Type: 'AWS::EC2::Instance' Properties: InstanceType: t2.micro ImageId: Fn::FindInMap: - RegionMap - !Ref AWS::Region - AMI SecurityGroups: - !Ref MySecurityGroup Tags: - Key: "Name" Value: !Join - "" - - "EC2 Instance for " - !Ref AWS::Region MySecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Enable SSH access via port 22 SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0
Input Parameters
Input Parameters enable us to input custom values to our template.
They are defined within top level Parameters section.
Each parameter must be assigned a value at runtime, you can optionally specify a default value.
The only required attribute is Type which is the data type.
Example:
Parameters: NameOfService: Description: "The name of the service this stack is to be used for." Type: String KeyName: Description: Name of an existing EC2 KeyPair to enable SSH access into the server Type: AWS::EC2::KeyPair::KeyName Mappings: RegionMap: us-east-1: AMI: ami-1853ac65 us-west-1: AMI: ami-bf5540df eu-west-1: AMI: ami-3bfab942 ap-southeast-1: AMI: ami-e2adf99e ap-southeast-2: AMI: ami-43874721 Resources: Ec2Instance: Type: 'AWS::EC2::Instance' Properties: InstanceType: t2.micro ImageId: Fn::FindInMap: - RegionMap - !Ref AWS::Region - AMI SecurityGroups: - !Ref MySecurityGroup Tags: - Key: "Name" Value: !Ref NameOfService KeyName: !Ref KeyName MySecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Enable SSH access via port 22 SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0
When should you use a parameter?
Ask yourself this:
- Is this CloudFormation resource configuration likely to change in the future?
- If so, make it a parameter.
- You won't have to -re-upload a template to change its content
!GetAtt: is just for the one attribute value.
CloudFormation currently supports the following parameter types:
String – A literal string Number – An integer or float List<Number> – An array of integers or floats CommaDelimitedList – An array of literal strings that are separated by commas AWS::EC2::KeyPair::KeyName – An Amazon EC2 key pair name AWS::EC2::SecurityGroup::Id – A security group ID AWS::EC2::Subnet::Id – A subnet ID AWS::EC2::VPC::Id – A VPC ID List<AWS::EC2::VPC::Id> – An array of VPC IDs List<AWS::EC2::SecurityGroup::Id> – An array of security group IDs List<AWS::EC2::Subnet::Id> – An array of subnet IDs
Outputs
Outputs enable us to get access to information about resources within a stack.
- outputs values that we can import into other stack (if you export them first)
- View from CLI
- You cannot delete a CloudFormation Stack if its outputs are being referenced by another CloudFormation Stack.
- A second template can use the export value of outputs, use Fn::ImportValue.
Example:
Parameters: NameOfService: Description: "The name of the service this stack is to be used for." Type: String KeyName: Description: Name of an existing EC2 KeyPair to enable SSH access into the server Type: AWS::EC2::KeyPair::KeyName Mappings: RegionMap: us-east-1: AMI: ami-1853ac65 us-west-1: AMI: ami-bf5540df eu-west-1: AMI: ami-3bfab942 ap-southeast-1: AMI: ami-e2adf99e ap-southeast-2: AMI: ami-43874721 Resources: Ec2Instance: Type: 'AWS::EC2::Instance' Properties: InstanceType: t2.micro ImageId: Fn::FindInMap: - RegionMap - !Ref AWS::Region - AMI SecurityGroups: - !Ref MySecurityGroup Tags: - Key: "Name" Value: !Ref NameOfService KeyName: !Ref KeyName MySecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Enable SSH access via port 22 SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0 Outputs: ServerDns:
Export:
Name: Server DNS Value: !GetAtt - Ec2Instance - PublicDnsName
Conditions
Rollback
Stack Creation Fails:
- Default: everything rolls back (get deleted). We can look at the log
- Option to disable rollback and troubleshoot what happened. "Rollback on failure"
Stack Update Fails:
- The stack automatically rolls back to the previous known working state
- Ability to see in the log what happened and error message
StackSets
- Update multiple accounts and regions with a single operation
Drift
Drift detection enables you to detect whether a stack's actual configuration differs, or has drifted, from its expected configuration. Use CloudFormation to detect drift on an entire stack, or individual resources within the stack. A resource is considered to have drifted if any of its actual property values differ from the expected property values. This includes if the property or resource has been deleted. A stack is considered to have drifted if one or more of its resources have drifted.
To determine whether a resource has drifted, CloudFormation determines the expected resource property values, as defined in the stack template and any values specified as template parameters. CloudFormation then compares those expected values with the actual values of those resource properties as they currently exist in the stack. A resource is considered to have drifted if one or more of its properties have been deleted, or had their value changed.
You can then take corrective action so that your stack resources are again in sync with their definitions in the stack template, such as updating the drifted resources directly so that they agree with their template definition. Resolving drift helps to ensure configuration consistency and successful stack operations.