[AWS] Introduction to CloudFormation

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

Read: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#aws-properties-ec2-instance-return-values

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.

原文地址:https://www.cnblogs.com/Answer1215/p/14769643.html