# AWS CloudFormation 介绍

By [eason hao](https://paragraph.com/@eason-hao) · 2022-11-06

---

AWS CloudFormation是一个AWS提供的，可以帮助我们快速创建云资源的工具。

创建AWS资源，可以使用CLI，API或者各种SDK直接创建资源，这些方式对于创建单类资源还好，如果要用来管理整个team或公司的资源就显得力不从心，而CloudFormation是专门用来管理AWS资源的IaC工具，可以清晰的描述和修改资源。

文章目录：

1.  CloudFormation概念
    
2.  如何使用CloudFormation
    
3.  CloudFormation相关权限
    
4.  使用CodePipeline部署CF
    

CloudFormation概念：
-----------------

template：是一个json或yaml格式的文件，里面包含申请的资源

    AWSTemplateFormatVersion: '2010-09-09'
    Description: create ELB for query service
    Parameters:
      EnvName:
        Type: String
        Description: Name of current running environment
    Conditions:
      CreateResourceAllowed: !Equals [ !Ref 'AWS::Region', us-east-1 ]
    Resources:  
      MyEC2Instance: 
        Type: AWS::EC2::Instance
        Condition: CreateResourceAllowed
        Properties: 
          ImageId: "ami-79fd7eee"
          KeyName: "testkey"
          BlockDeviceMappings: 
          - DeviceName: "/dev/sdm"
            Ebs: 
              VolumeType: "io1"
              Iops: "200"
              DeleteOnTermination: "false"
              VolumeSize: "20"
          - DeviceName: "/dev/sdk"
            NoDevice: {}
      Outputs:
        MyEC2InstanceInstanceID:
          Value: !Ref 'MyEC2Instance'
          Description: The ID of MyEC2Instance
          Export:
            Name: 'MyEC2Instance_ID'
    

template主要分为几部分，Parameters用来描述参数，Conditions用来描述创建资源的条件，Resources描述需要的资源，Outputs输入变量，可供其他stack使用。

template可以是本地文件，也可以是放在s3上的文件

stack: 管理资源的集合，一个template对应一个stack

changeset: 描述对一个stack的修改

如何使用CloudFormation
------------------

1.  准备好AWS环境和一个有CloudFormation权限的账户
    
2.  准备aws template，描述要创建的ELB，如下
    

    AWSTemplateFormatVersion: '2010-09-09'
    Description: create ELB for query service
    Parameters:
      EnvName:
        Type: String
        Description: Name of current running environment
    Resources:
      AWSCFELB:
        Type: AWS::ElasticLoadBalancing::LoadBalancer
        Properties:
          LoadBalancerName: !Join
          - ''
          - - aws-cf-lb-
            - !Ref 'EnvName'
          Subnets: 'xxxxx'
          SecurityGroups: 'yyyyy'
          CrossZone: true
          Listeners:
          - LoadBalancerPort: '2443'
            InstancePort: '3443'
            Protocol: TCP
            InstanceProtocol: TCP
          ConnectionSettings:
            IdleTimeout: 300
    

3\. 使用使用CLI，API，SDK或者AWS console创建stac

    aws cloudformation create-stack \
    --stack-name aws-cf-lb-stack \
    --template-body file:///home/eason/aws-cf-lb.yaml \
    --parameters ParameterKey=EnvName,ParameterValue=test
    

之后就可以在CloudFormation里面看到这个stack，也可以修改template，然后使用update-stack命令更新stack

CloudFormation process

![](https://storage.googleapis.com/papyrus_images/9e86c8d46a446a4f05ad9bce2497ae8c793a6b5c54859da6e3e94a0a0fa2ae57.png)

CloudFormation相关权限
------------------

对于要创建CF stack的user，需要CreateStack等权限才能创建CF stack，但是由于资源是由stack创建的，stack并没有创建资源的权限，所以需要给CF stack一个service role，让CF stack代表该role去创建资源。

比如stack的service role是cmsCfRole，cmsCfRole包含了创建sqs的权限，该stack才能创建sqs，否则会失败。

![](https://storage.googleapis.com/papyrus_images/586c4a50ca54a42dfa67e669eed81cfcdefb99dcb0d562f4bf2d4f2fd4b286e6.png)

此时还要注意，user要有将CfRole传递给stack的权限—iam:PassRole。举例，user有ec2:CreateVpc和cloudformation:CreateStack的权限，表示该user可以创建VPC和CF stack，但是该user创建的stack却没有CreateVpc的权限，所以需要PassRole，因此user需要设置PassRole.

    - PolicyName: CloudFormationIAMPRAccess
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Action:
          - 'iam:PassRole'
          Effect: Allow
          Resource:
            - 'arn:aws:iam::*:role/CfRole'
    

> iam:PassRole可能会遇到多级传递的问题，比如user用CodePipeline去创建stack，stack创建的ec2:instance需要ec2Role，那么user需要有CodePipeline等资源的权限，和将CfRole传递下去的PassRole，此时CodePipeline创建的stack的role为CfRole，CfRole需要包含将ec2Role传递下去的PassRole，这样stack创建的ec2才能有ec2Role权限。

如果stack中包含IAM资源，需要执行capabilities, CAPABILITY\_IAM or CAPABILITY\_NAMED\_IAM, 如果包含自定义IAM资源，则需指定为CAPABILITY\_NAMED\_IAM

使用CodePipeline部署CF
------------------

使用CodePipeline可以更细致的部署CF，可以查看CF的changeset再决定是否部署，给运维人员更多的选择。

CodePipeline是一个continuous delivery service，pipeline由stage组成，stage包含action，action是一系列操作的集合。

run CF的pipeline一般由两个stage组成，第一个stage定义CF template位置，第二个stage包含三个action，CreateChangeSet，ApproveChangeSet 和ExecuteChangeSet action，其中create和execute changeSet action需指定有操作stack权限的role，因为这两步会创建或修改stack，如果stack创建的资源需要特定权限，则该role需要有PassRole权限。

因为stack可能会引用其他stack的output，所以stack的创建有顺序的要求，同理CodePipeline的执行也有顺序要求，以避免创建stack失败。

---

*Originally published on [eason hao](https://paragraph.com/@eason-hao/aws-cloudformation)*
