Cover photo

AWS CloudFormation 介绍

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

post image

CloudFormation相关权限

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

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

post image

此时还要注意,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失败。