aws cloudformation 理解常见资源的部署和使用

news2025/3/1 8:10:32

参考

  • cfn101-workshop
  • aws cli cloudformation

cloudformation是aws的iac工具,以下简称cfn

环境搭建——cfn命令行工具

创建堆栈

aws cloudformation create-stack --stack-name testtemp \
    --template-body file://testtemp.yaml
    # --parameters ParameterKey=KeyPairName,ParameterValue=TestKey

删除堆栈

aws cloudformation delete-stack \
    --stack-name testtemp

查看堆栈event

aws cloudformation describe-stack-events \
    --stack-name  \
    --max-items 2

切换格式,json和yaml的转换

pip install cfn-flip
cfn-flip --version
cfn-flip example_parameter.json example_parameter.yaml

方便起见可以编写脚本将常用测试命令整合在一起,只需要修改参数即可快速重复测试模板

#!/bin/bash
WEBURL=$2
FILE_NAME=resources.yaml
BUCKET_NAME=zhaojiew-test
FILEPATH=cfn
BUCKET_FILEPATH=s3://$BUCKET_NAME/$FILEPATH/
STACK_NAME=aws
CHANGESET_NAME=awsset
ROLE_ARN=arn:aws-cn:iam::xxxxxxxx:role/MyCloudfotmationRole

echo STACK_NAME   "====>" $STACK_NAME
echo FILE_NAME    "====>" $FILE_NAME 
echo ROLE_ARN     "====>" $ROLE_ARN 
echo BUCKET_NAME  "====>" $BUCKET_NAME
echo FILEPATH     "====>" $FILEPATH

case $1 in
    "create")
        echo " =================== create stack ===================";
        aws cloudformation create-stack --stack-name $STACK_NAME\
            --template-body file://$FILE_NAME \
	        --role-arn $ROLE_ARN \
            --capabilities CAPABILITY_IAM
            # --tags Key=who,Value=justtest \
            # --parameters ParameterKey=InstanceType,ParameterValue=t2.small \
            #              ParameterKey=SubnetIDs,ParameterValue=SubnetID1\\,SubnetID2
    ;;
    "urlcreate")
        echo " =================== create stack from url ===================";
        aws s3 cp $FILE_NAME $BUCKET_FILEPATH
        TEMPURL=https://$BUCKET_NAME.s3.cn-north-1.amazonaws.com.cn/$FILEPATH/$FILE_NAME
        echo $TEMPURL
        aws cloudformation create-stack --stack-name $STACK_NAME\
            --template-url $TEMPURL \
	        --role-arn $ROLE_ARN 
            # --tags Key=who,Value=justtest \
            # --parameters ParameterKey=InstanceType,ParameterValue=t2.small \
            #              ParameterKey=SubnetIDs,ParameterValue=SubnetID1\\,SubnetID2
    ;;
    "delete")
        echo " =================== delete stack ==================="
        aws cloudformation delete-stack --stack-name $STACK_NAME
    ;;
    "createset")
        echo " =================== create stackset ==================="
        aws cloudformation create-change-set \
            --stack-name $STACK_NAME \
            --change-set-name $CHANGESET_NAME \
            --template-body file://$FILE_NAME\
             --capabilities CAPABILITY_IAM
    ;;
    "event")
        echo " =================== describe stack event ==================="
        aws cloudformation describe-stack-events --stack-name aws --max-items 5 \
            --query 'StackEvents[].{CStatus: ResourceStatus,Rreason: ResourceStatusReason}' --output table 
    ;;
    "download")
        echo " =================== download external url ==================="
        wget -nc $WEBURL -O $FILE_NAME
        echo "file name is =====>>>>> " ${WEBURL##*/}
    ;;
    "upload")
        echo " =================== upload file to bucket ==================="
        aws s3 cp $FILE_NAME $BUCKET_FILEPATH
        echo https://$BUCKET_NAME.s3.cn-north-1.amazonaws.com.cn/$FILEPATH/$FILE_NAME
    ;;
    "valid")
        echo " =================== validate templaet ==================="
        aws cloudformation validate-template --template-body file://$FILE_NAME
    ;;
    *)
        echo "Input Args Error..."
    ;;
esac

cfn基础——顶级字段

cfn顶级字段,只有resource是必须的,关于cloutformation的模板剖析

AWSTemplateFormatVersion: 'version date' (optional) # version of the CloudFormation template. Only accepted value is '2010-09-09'
Description: 'String' (optional) # a text description of the Cloudformation template
Metadata: 'template metadata' (optional) # objects that provide additional information about the template
Parameters: 'set of parameters' (optional) # a set of inputs used to customize the template
Rules: 'set of rules' (optional) # a set of rules to validate the parameters provided at deployment/update
Mappings: 'set of mappings' (optional) # a mapping of keys and associated values
Conditions: 'set of conditions' (optional) # conditions that control whether certain resources are created
Transform: 'set of transforms' (optional) # for serverless applications
Resources: 'set of resources' (required) # a components of your infrastructure
Hooks: 'set of hooks' (optional) # Used for ECS Blue/Green Deployments
Outputs: 'set of outputs' (optional) # values that are returned whenever you view your stack's properties

堆栈是cfn模板的部署,单个cfn模板可以创建多个stack

如果堆栈创建失败会回滚,删除所有已创建的资源。如果无法删除则会保留资源直到能够成功删除堆栈

创建堆栈——cfn 权限

通过iam权限控制cfn访问,控制台使用cfn需要比cli和api更多的额外权限,例如上传文件到s3(每个区域都有默认的cf模板的存储桶),列出下拉参数所需的desctibe*权限。可见如果通过cli创建堆栈,实际上并不会将文件上传到s3桶中

cfn创建资源的api调用来自cfn的ip地址,因此不要使用aws:SourceIp条件键进行限制

通过--role-arn可以指定cfn可以使用的角色,cfn的所有堆栈操作都通过该角色完成。如果不指定,则使用之前关联过的角色。如果没有可用角色,则会从用户凭证生成临时会话

aws cloudformation create-stack --stack-name testtemp \
	--role-arn arn:aws-cn:iam::xxxxxxx:role/MyCloudfotmationRole
    --template-body file://testtemp.yaml

Amazon CloudFormation will use this role for all stack operations. Other users that have permissions to operate on this stack will be able to use this role, even if they don’t have permission to pass it. Ensure that this role grants least privilege.

这意味着如果其他用户有权访问堆栈,即使cfn的角色没有传递,其他用户也能通过cfn间接使用该角色

创建资源——简单创建s3桶

简单s3 bucket 模板

#testtemp.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: AWS CloudFormation workshop - Template and stack
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256

使用cli创建堆栈

aws cloudformation create-stack --stack-name temptest \
    --template-body file://temptest.yaml

内置函数——具备profile的ec2实例

由于该行为会创建iam 角色,因此在cli命令和console中要进行确认 --capabilities CAPABILITY_IAM

在模板中使用了内置函数ref引用其他资源,可以在output中验证

  • 如果引用资源会返回物理id(对特定资源例如ec2实例会返回实例id
  • 如果是参数会返回参数值

policy策略有两种写法,内联和托管策略,以下为用户创建的托管策略

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Version: '2009-05-15'
    Properties:
      ImageId: ami-0ab68f4313c5aff87
      InstanceType: t2.micro
      Monitoring: 'true'
      DisableApiTermination: 'false'
      IamInstanceProfile:
        !Ref RootInstanceProfile
  RootRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - ec2.amazonaws.com.cn
          Action:
          - sts:AssumeRole
      Path: "/"
  RolePolicies:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: s3readonly
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action: 
          - "s3:Get*"
          - "s3:List*"
          Resource: "*"
      Roles:
      - !Ref RootRole
  RootInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: "/"
      Roles:
      - !Ref RootRole

Outputs:
  InstanceId:
    Description: Instance ID of the instance you create
    Value: !Ref myEC2Instance
  RoleID:
    Description: role ID of the instance you create
    Value: !Ref RootRole

伪参数——打包lambda获取ssm参数

使用伪参数获取堆栈id,区域和账号等信息,例如以下使用AWS::Partition获取中国区分区为aws-cn

意味着可以动态适配不同账号和区域的环境进行堆栈部署。

创建lambada函数使用zip对inline function进行打包,大小不超过4MB

使用内置函数sub对伪参数进行替换,sub可以分为有mapping和无mapping两种,对于伪参数的用法为无map。

sub函数中使用${paramater}能间接获取refFn::GetAttr等函数的调用结果

$(!parameter)将原样解析不进行替换

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Pseudo parameters (uksb-1q9p31idr).

Parameters:
  DatabaseUsername:
    Description: Value to be used with the dbUsername SSM parameter. The default value is set to 'alice', which users can override when creating a CloudFormation stack.
    Type: String
    Default: alice
    AllowedPattern: ^[a-z0-9]{5,12}$

  S3BucketNamePrefix:
    Description: The prefix to use for your S3 bucket
    Type: String
    Default: my-demo-bucket
    AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$
    ConstraintDescription: Bucket name prefix can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-).
    MinLength: 3

Resources:
  BasicParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Name: dbUsername
      Type: String
      Value: !Ref DatabaseUsername
      Description: SSM Parameter for database username.

  DemoRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: ssm-least-privilege
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: ssm:GetParameter
                Resource: !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${BasicParameter}'

  DemoLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.lambda_handler
      Role: !GetAtt DemoRole.Arn
      Runtime: python3.8
      Code:
        ZipFile: |
          import boto3
          client = boto3.client('ssm')
          def lambda_handler(event, context):
              response = client.get_parameter(Name='dbUsername')
              print(f'SSM dbUsername parameter value: {response["Parameter"]["Value"]}')

  DemoBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub '${S3BucketNamePrefix}-${AWS::Region}-${AWS::AccountId}'

映射——动态指定实例类型

map是个键值对,通过Fn::FindInMap(简写为!FindInMap)获取对应键的值

以下获取ec2实例的id实际是对应键EnvironmentType.Test.InstanceType 的值而已

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Mappings (uksb-1q9p31idr).

Parameters:
  EnvironmentType:
    Description: 'Specify the Environment type of the stack.'
    Type: String
    Default: Test
    AllowedValues:
      - Test
      - Prod
    ConstraintDescription: 'Specify either Test or Prod.'
    
Mappings:
  EnvironmentToInstanceType:
    Test:
      InstanceType: t2.micro
    Prod:
      InstanceType: t2.small

Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0ab68f4313c5aff87
      InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref EnvironmentType, InstanceType]

输出——带eip的ec2实例

可以从cloudformation资源和属性参考中查找对应资源的返回值信息,可以查看refgetattr分别能够获取的值

getattrrefsub的区别在于

  • ref返回特定参数(参数值)和资源(物理id/资源id/资源名称)的值
  • getattr返回特定资源的属性值
  • 能够通过${}简介使用以上两者
AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Outputs (uksb-1q9p31idr).
    
Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-xxxxxx
      InstanceType: t2.micro

  WebServerEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      InstanceId: !Ref WebServerInstance

Outputs:
  WebServerPublicDNS:
    Description: Public DNS of EC2 instance
    Value: !GetAtt WebServerInstance.PublicDnsName

  WebServerElasticIP:
    Description: Elastic IP assigned to EC2
    Value: !Ref WebServerEIP

返回值——带策略s3桶和带安全组ec2实例

创建ec2实例时,可以指定从ssm参数中获取最新的ami

每个ami都拥有公开的ssm参数空间,如下

# 获取公共ami列表
aws ssm get-parameters-by-path --path "/aws/service/ami-amazon-linux-latest"
# 使用公共ssm参数查询ami
aws ssm get-parameters --names /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

模板如下

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Resource Return Values Lab (uksb-1q9p31idr).

Parameters:
  LatestAmiId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
    
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      Tags:
        - Key: Purpose
          Value: AWS CloudFormation Workshop

  S3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Action:
              - s3:*
            Effect: Deny
            Resource:
              - !GetAtt S3Bucket.Arn
              - !Sub '${S3Bucket.Arn}/*'
            Principal: '*'
            Condition:
              Bool:
                aws:SecureTransport: false
	
  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: t2.micro
      SecurityGroups:
        - !Ref InstanceSecurityGroup

  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow http to client host
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
      
Outputs:
  S3BucketDomainName:
    Description: IPv4 DNS name of the bucket.
    Value: !GetAtt S3Bucket.DomainName
    
  InstanceID:
    Description: The ID of the launched instance
    Value: !Ref Ec2Instance

  PublicIP:
    Description: Public IP of the launched instance
    Value: !GetAtt Ec2Instance.PublicIp

  SecurityGroupId:
    Description: ID of the security group created
    Value: !GetAtt InstanceSecurityGroup.GroupId

开启ssm和使用userdata——定制ec2实例

开启ssm控制台登录功能的ec2实例

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Session manager (uksb-1q9p31idr).

Resources:
  SSMIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws-cn:iam::aws:policy/AmazonSSMManagedInstanceCore

  WebServerInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref SSMIAMRole

  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref WebServerInstanceProfile
      ImageId: ami-0ab68f4313c5aff87
      InstanceType: t2.micro


Outputs:
  WebServerPublicDNS:
    Description: Public DNS of EC2 instance
    Value: !GetAtt WebServerInstance.PublicDnsName

使用userdata,userdata需要通过内置函数base64进行编码

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - User data (uksb-1q9p31idr).

Resources:

  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref WebServerInstanceProfile
      ImageId: ami-xxxxxx
      InstanceType: t2.micro
      UserData: !Base64 |
        #!/bin/bash
        yum update -y
        yum install -y httpd php
        systemctl start httpd
        systemctl enable httpd
        usermod -a -G apache ec2-user
        chown -R ec2-user:apache /var/www
        chmod 2775 /var/www
        find /var/www -type d -exec chmod 2775 {} \;
        find /var/www -type f -exec chmod 0664 {} \;
        cat << 'EOF' > /var/www/html/index.php
          <!DOCTYPE html>
          <html>
          <body>
            <center>
              <?php
              # Get the instance ID from meta-data and store it in the $instance_id variable
              $url = "http://169.254.169.254/latest/meta-data/instance-id";
              $instance_id = file_get_contents($url);
              # Get the instance's availability zone from metadata and store it in the $zone variable
              $url = "http://169.254.169.254/latest/meta-data/placement/availability-zone";
              $zone = file_get_contents($url);
              ?>
              <h2>EC2 Instance ID: <?php echo $instance_id ?></h2>
              <h2>Availability Zone: <?php echo $zone ?></h2>
            </center>
          </body>
          </html>
        EOF

helper脚本——监听cfn资源变动

helper脚本能够在原来的模板上对应用程序进行微调(不需要重新部署和创建堆栈资源),默认helper可以不需要凭证,请求会被限制在堆栈中的实例中

帮助脚本比较难理解一共有4个

  • cfn-init,通过获取stack元数据对实例进行配置,包括安装包,创建文件和启动服务
  • cfn-signal,当ec2创建和配置完毕向cfn发送信号。当结合creationpolicy和asg的WaitOnResourceSignals策略,会形成类似waitgroup的机制,暂停执行堆栈操作,收到指定数量的信号之后继续执行堆栈行为。因此signal程序可以发送信号给cfn
  • cfn-get-metadata,获取cfn元数据,可以手动获取看看和cfn中的配置一致
sudo /opt/aws/bin/cfn-get-metadata  --region cn-north-1 --stack aws -r WebServerInstance
{
    "AWS::CloudFormation::Init": {
        "config": {
            "files": {
                "/etc/cfn/cfn-hup.conf": {
                    "mode": "256",
                    "owner": "root",
                    "content": "[main]\nstack=arn:aws-cn:cloudformation:cn-north-1:xxxxxxx:stack/aws/aa931910-6ee0-11ed-9669-0e2f05fc8512\nregion=cn-north-1\ninterval=1\n",
                    "group": "root"
                },
                "/var/www/html/index.php": {
                    "mode": "420",
                    "owner": "apache",
                    "content": "<!DOCTYPE html>\n<html>\n<body>\n  <center>\n    <h2>EC2 Instance ID: <?php echo hello world ?></h2>\n  </center>\n</body>\n</html>\n",
                    "group": "apache"
                },
                "/etc/cfn/hooks.d/cfn-auto-reloader.conf": {
                    "content": "[cfn-auto-reloader-hook]\ntriggers=post.update\npath=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\naction=/opt/aws/bin/cfn-init --stack aws --resource WebServerInstance --region cn-north-1\nrunas=root\n"
                }
            },
            "services": {
                "sysvinit": {
                    "cfn-hup": {
                        "files": [
                            "/etc/cfn/cfn-hup.conf",
                            "/etc/cfn/hooks.d/cfn-auto-reloader.conf"
                        ],
                        "ensureRunning": "true",
                        "enabled": "true"
                    },
                    "httpd": {
                        "ensureRunning": "true",
                        "enabled": "true"
                    }
                }
            },
            "packages": {
                "yum": {
                    "php": [],
                    "httpd": []
                }
            }
        }
    }
}
  • cfn-hup,后台进程检测cfn元数据的变更,配置文件为cfn-hup.conf,钩子文件在hooks.d

以下将模板精简之后可以看到在WebServerInstance资源中主要分为MetadataProperties两部分

  • Metadata是对cfn资源元数据的设置,通过init对实例进行配置,分为packages, groups, users, sources, files, commands, services,当调用/opt/aws/bin/cfn-init时会执行全部配置

  • 在实例内部安装aws-cfn-bootstrap,在al2类型实例上已经预装

  • cfn-hup后台启动并读取配置文件,指定检查元数据间隔interval为1分钟,定期调用钩子。可以检查cfn资源,cfn资源物理id和cfn元数据。action指定检测到更改后执行的行为,实际上就是个shell脚本,下面的配置表明重新执行了cfn-init文件。此时如果在更改集中修改了ec2实例元数据中的php脚本则会触发更改刷新网页内容

    [cfn-auto-reloader-hook]
    triggers=post.update
    path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
    action=/opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource WebServerInstance --region 
    runas=root
    
  • cfn-signal使用cfn-init的返回结果$?进行调用,此时如果实例配置失败则堆栈会回滚

  • 创建WebServerInstance资源使用了CreationPolicy策略,此时只有ec2实例使用cfn-signal发送信号之后,才会完成ec2实例资源的创建。指定需要收到信号数量为1,超时时间为10分钟
    (https://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/aws-attribute-creationpolicy.html)资源策略

      WebServerInstance:
        CreationPolicy:
          ResourceSignal:
            Count: 1
            Timeout: PT10M
    
  • cfn-signal可以和资源策略相结合,但是只有部分资源支持CreationPolicy。同样指定UpdatePolicy配置WaitOnResourceSignals可以在更新asg时触发信号等待,确保asg中的每个实例都已经配置完成

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Helper scripts (uksb-1q9p31idr).

Resources:

  WebServerInstance:
    CreationPolicy:
      ResourceSignal:
        Count: 1
        Timeout: PT10M
    Type: AWS::EC2::Instance
    Metadata:
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              httpd: []
              php: []
          files:
            /var/www/html/index.php:
              content: |
                <!DOCTYPE html>
                <html>
                <body>
                  <center>
                    <h2>EC2 Instance ID: <?php echo helloworld ?></h2>
                  </center>
                </body>
                </html>
              mode: 000644
              owner: apache
              group: apache
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
                interval=1
              mode: 000400
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Sub |
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
                action=/opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
                runas=root
          services:
            sysvinit:
              httpd:
                enabled: true
                ensureRunning: true
              cfn-hup:
                enabled: true
                ensureRunning: true
                files:
                  - /etc/cfn/cfn-hup.conf
                  - /etc/cfn/hooks.d/cfn-auto-reloader.conf
    Properties:
      ImageId: ami-02c8191b43515df27
      KeyName: "temp-key"
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
      InstanceType: t2.micro
      UserData: !Base64
        Fn::Sub: |
          #!/bin/bash -xe
          # Update aws-cfn-bootstrap to the latest
          yum install -y aws-cfn-bootstrap
          # Call cfn-init script to install files and packages
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
          # Call cfn-signal script to send a signal with exit code
          /opt/aws/bin/cfn-signal --exit-code $? --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}

条件判断——有条件地创建ec2的挂载卷

根据参数不同指定资源的创建与否,还可以根据条件指定属性和输出值

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Conditions at resource level (uksb-1q9p31idr).

Parameters:
  EnvType:
    Description: Specify the Environment type of the stack.
    Type: String
    AllowedValues:
      - test
      - prod
    Default: test
    ConstraintDescription: Specify either test or prod.

Conditions:
  IsProduction: !Equals
    - !Ref EnvType
    - prod

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: !If [IsProduction, t2.small, t2.micro]

  MountPoint:
    Type: AWS::EC2::VolumeAttachment
    Properties:
      InstanceId: !Ref EC2Instance
      VolumeId: !Ref Volume
      Device: /dev/sdh
    Condition: IsProduction

  Volume:
    Type: AWS::EC2::Volume
    Properties:
      Size: 2
      AvailabilityZone: !GetAtt EC2Instance.AvailabilityZone
      Encrypted: true
    Condition: IsProduction
    
Outputs:
  VolumeId:
    Value: !Ref Volume
    Condition: IsProduction

资源依赖——指定资源创建的现后顺序

在cfn中资源的依赖可以分为

  • 显式依赖,使用dependon参数
  • 隐式依赖,使用refgetattr参数

在没有依赖的情况下,cfn创建资源的方式时并行的。下面的sg隐式依赖ingressrule,sns显式依赖s3桶

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Resource Dependencies Lab with Ref and Fn::GetAtt Intrinsic Functions (uksb-1q9p31idr).

Resources:

  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Example Security Group

  SecurityGroupIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt SecurityGroup.GroupId
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: 0.0.0.0/0

  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:

  SNSTopic:
    Type: AWS::SNS::Topic
    DependsOn: S3Bucket
    Properties:

动态引用——设置lamda获取secret和parameter

提前在ssm中创建参数

aws ssm put-parameter \
    --name "/golden-images/amazon-linux-2" \
    --value YOUR_AMI_ID \
    --type "String" \
    --region YOUR_REGION

在cfn中动态引用参数,固定写法

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: !Select ["0", !GetAZs ""]
      InstanceType: t2.micro
      ImageId: '{{resolve:ssm:/golden-images/amazon-linux-2}}'
   
  DatabaseConnParams:
    Type: AWS::SecretsManager::Secret
    Properties:
      Description: Database Connection Parameters.
      Name: DatabaseConnParams
      SecretString: !Sub |
        {
          "RDS_HOSTNAME": "${Database.Endpoint.Address}",
          "RDS_PORT": "${Database.Endpoint.Port}",
          "RDS_USERNAME": "${DBUsername}",
          "RDS_PASSWORD": "${DBPassword}"
        }
  FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
        Version: "2012-10-17"
      ManagedPolicyArns:
        - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
      Path: /

  HelloWorldFunction:
    Type: AWS::Lambda::Function
    Properties:
      Role: !GetAtt FunctionExecutionRole.Arn
      Handler: index.handler
      Environment:
        Variables:
          RDS_HOSTNAME: '{{resolve:secretsmanager:DatabaseConnParams:SecretString:RDS_HOSTNAME}}'
          RDS_PORT: '{{resolve:secretsmanager:DatabaseConnParams:SecretString:RDS_PORT}}'
      Runtime: python3.7
      Code:
        ZipFile: |
          import os
          def handler(event, context):
              RDS_HOSTNAME=os.getenv('RDS_HOSTNAME')
              RDS_PORT=os.getenv('RDS_PORT')
              return "Database: {}:{}".format(RDS_HOSTNAME,RDS_PORT)

嵌套堆栈——将模板化整为零

所谓嵌套堆栈就是将原本cfn模板中的资源单独分离出来,便于复用和灵活组合。使用时只需要在root template中进行引用即可。

例如创建一个root堆栈,引用vpc,ec2和iam的堆栈

在这里插入图片描述
对于需要引用的堆栈资源需要使用AWS::CloudFormation::Stack类型

以下模板创建stack资源,并指定了模板所在的s3 url和初始参数。stack资源之间相互引用output,通过Fn: : GetAtt 将值从子堆栈传递到根堆栈

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Nested stacks - Root template (uksb-1q9p31idr).

Parameters:
  S3BucketName:
    Type: String

  AvailabilityZones:
    Type: List<AWS::EC2::AvailabilityZone::Name>

  VPCName:
    Type: String
    Default: cfn-workshop-vpc

  VPCCidr:
    Type: String
    Default: 10.0.0.0/16

  PublicSubnet1Cidr:
    Type: String
    Default: 10.0.0.0/24

  PublicSubnet2Cidr:
    Type: String
    Default: 10.0.1.0/24

Resources:
  VpcStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com.cn/vpc.yaml
      TimeoutInMinutes: 20
      Parameters:
        AvailabilityZones: !Join
          - ','
          - !Ref AvailabilityZones
        VPCCidr: !Ref VPCCidr
        VPCName: !Ref VPCName
        PublicSubnet1Cidr: !Ref PublicSubnet1Cidr
        PublicSubnet2Cidr: !Ref PublicSubnet2Cidr

  IamStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com.cn/iam.yaml
      TimeoutInMinutes: 10

  EC2Stack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub https://${S3BucketName}.s3.amazonaws.com.cn/ec2.yaml
      TimeoutInMinutes: 20
      Parameters:
        EnvironmentType: Dev
        VpcId: !GetAtt VpcStack.Outputs.VpcId
        SubnetId: !GetAtt VpcStack.Outputs.PublicSubnet1
        WebServerInstanceProfile: !GetAtt IamStack.Outputs.WebServerInstanceProfile

Outputs:
  WebsiteURL:
    Value: !GetAtt EC2Stack.Outputs.WebsiteURL

vpc/ec2和iam的堆栈模板如同往常一样,由于在参数中使用ref进行了引用,实际上形成了隐式依赖关系

创建嵌套堆栈需要开启权限CAPABILITY_AUTO_EXPAND

If you want to create a stack from a stack template that contains macros and nested stacks, you must create the stack directly from the template using this capability.

开启nested视图后可以看到标记
在这里插入图片描述
删除嵌套堆需要删除root堆栈,否则会导致不一致

Deleting this stack will delete all stack resources. Resources will be deleted according to their DeletionPolicy.
It is recommended to delete through the root stack
Deleting a nested stack may result in an unstable state where the nested stack is out-of-sync with its root stack.

分层堆栈——堆栈间互通有无

嵌套堆栈的问题在于无法创建一对多关系,因为所有资源都在root中进行维护,本质上其实还是一个堆栈。分层堆栈就是创建多个堆栈,并实现跨堆栈的资源引用。

在这里插入图片描述
创建iam堆栈,并export instance profile

AWSTemplateFormatVersion: "2010-09-09"

Resources:
  SSMIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

  WebServerInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref SSMIAMRole

Outputs:
  WebServerInstanceProfile:
    Value: !Ref WebServerInstanceProfile
    Export:
      Name: cfn-workshop-WebServerInstanceProfile

导出的值可以在控制台看到
在这里插入图片描述

创建ec2并引用iam堆栈的instance profile

AWSTemplateFormatVersion: "2010-09-09"

Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      SubnetId: sub-xxxx
      IamInstanceProfile: !ImportValue cfn-workshop-WebServerInstanceProfile
      ImageId: ami-xxxx
      InstanceType: t2.micro

打包和部署

我们在之前部署过lambda资源以及嵌套堆栈。lambda使用zip的方式将code打包,嵌套堆栈则是提前将模板上传到s3中进行引用,如果这样的组件很多工作量会非常大。

使用cfn打包功能可以简化步骤

package-and-deploy
├── infrastructure.template
└── lambda/
    ├── lambda_function.py
    └── requirements.txt

查看程序

cat lambda_function.py
from datetime import datetime
from pytz import timezone, utc
def handler(event, context):
    payload = event["time_zone"]
    message = "Current date/time in TimeZone *{}* is: {}".format(
        payload, _timezone(payload)
    )

    return {"message": message}
def _timezone(time_zone):
    utc_now = utc.localize(datetime.utcnow())
    compare_to_utc = utc_now.astimezone(timezone(time_zone))

    return compare_to_utc.strftime("%Y-%m-%d %H:%M")
    
cat requirements.txt
pytz==2021.3

模板如下

AWSTemplateFormatVersion: "2010-09-09"

Description: AWS CloudFormation workshop - Package and deploy (uksb-1q9p31idr).

Resources:
  LambdaBasicExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

  PythonFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: cfn-workshop-python-function
      Description: Python Function to return specific TimeZone time
      Runtime: python3.8
      Role: !GetAtt LambdaBasicExecutionRole.Arn
      Handler: lambda_function.handler
      Code: lambda/

对模板打包

aws cloudformation package \
  -         -template-file ./infrastructure.template \
            --s3-bucket "${BUCKET_NAME}" \
            --s3-prefix "${FILEPATH}" \
            --output-template-file ./infrastructure-packaged.template

打包后的模板,bucketname中的prefix/9497159249ecec70572a11a73f15e601文件实际上就是lambda/目录的压缩包

AWSTemplateFormatVersion: '2010-09-09'
Description: AWS CloudFormation workshop - Package and deploy (uksb-1q9p31idr).
Resources:
  LambdaBasicExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: lambda.amazonaws.com
          Action: sts:AssumeRole
      Path: /
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  PythonFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: cfn-workshop-python-function
      Description: Python Function to return specific TimeZone time
      Runtime: python3.8
      Role:
        Fn::GetAtt:
        - LambdaBasicExecutionRole
        - Arn
      Handler: lambda_function.handler
      Code:
        S3Bucket: buckname
        S3Key: prefix/9497159249ecec70572a11a73f15e601
Outputs:
  LambdaFunction:
    Description: AWS Lambda Python Function
    Value:
      Ref: PythonFunction

更新堆栈

堆栈的更新行为有以下几种

  • Update with No Interruption,
  • Updates with Some Interruption,
  • Replacement

AWS资源类型参考中介绍了每个属性的更新行为

使用更改集更新堆栈能够预览堆栈的变动并确认修改

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/44405.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二叉树的循环问题

目录 一、二叉树的完全性检验 二、前序遍历的非递归写法 三、中序遍历的非递归写法 四、后序遍历的非递归写法 一、二叉树的完全性检验 给定一个二叉树的 root &#xff0c;确定它是否是一个 完全二叉树 。 在一个 完全二叉树 中&#xff0c;除了最后一个关卡外&#xff0c…

Vue脚手架

脚手架 安装步骤 全局安装vue/cli npm install -g vue/cli 安装之后使用不了vue的命令&#xff0c;查看nodejs文件发现我把vue装在了node_globalnpm这个文件夹中。 解决方法&#xff1a;新增一条path指向该文件夹 切换到你要创建的目录创建脚手架 vue create 项目名称 根据…

[附源码]Python计算机毕业设计Django保护濒危动物公益网站

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【Hack The Box】linux练习-- Talkative

HTB 学习笔记 【Hack The Box】linux练习-- Talkative &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月27日&#x1f334; &#x…

初始数据结构

目录 1. 集合的框架 集合框架的重要性 数据结构的介绍 算法的介绍 容器背后对应的数据结构 2. 时间复杂度和空间复杂度 算法效率 时间复杂度 时间复杂度的概念 大O的渐进表示法 常见的时间复杂度的计算 空间复杂度 空间复杂度的概念 从本章开始又要开始新的篇章&a…

[附源码]Python计算机毕业设计Django班级事务管理论文2022

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

k8s上部署Harbor通过Nginx-Ingress域名访问

目录 1、k8s集群环境&#xff0c;通过kubesphere安装部署。 1.1 集群基本信息 1.2 集群节点信息 2、安装Harbor 2.1、使用Helm添加Harbor仓库 2.2 、通过openssl生成证书 2.3、 创建secret 2.4、 创建nfs存储目录 2.5、 创建pv 2.6、创建pvc 2.7、values.yaml配置文件 2.…

3-UI自动化-八大元素定位,xpath定位方式和相关的常问面试题

3-UI自动化-八大元素定位&#xff0c;xpath定位方式和相关的常问面试题八大元素定位八大元素定位的使用通过xpath定位xpath语法1. xpath逻辑运算定位2. 层级条件定位3. 索引定位4. 文本定位text()WebElement对象WebElement对象常用属性WebElement对象常用方法find_element()和 …

【Mybatis编程:插入和根据id删除相册数据】

目录 1. Mybatis编程&#xff1a;插入相册数据 2. Mybatis编程&#xff1a;根据id删除相册数据 1. Mybatis编程&#xff1a;插入相册数据 当某个数据表中的id被设计为“自动编号”的&#xff08;auto_increment&#xff09;&#xff0c;在配置<insert>标签时&#xff0…

开心公寓房屋出租管理系统的设计与实现(系统源码+技术文档+论文)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

基于51单片机病房呼叫系统(64位病床)

资料编号&#xff1a;189 下面是仿真演示&#xff1a; 189-基于51单片机病房呼叫系统&#xff08;64位病床&#xff09;&#xff08;仿真源程序原理图全套资料&#xff09;功能介绍&#xff1a; 设计一个可容64张床位的比那个房呼叫系统。 1、每个床位都有一个按钮&#xf…

InnoDB存储引擎简介

InnoDB存储引擎是一种兼顾高可靠性和高性能的通用存储引擎&#xff0c;在MySQL5.5之后&#xff0c;被选为MySQL的默认存储引擎 InnoDB的特点 1 DML操作循环ACID模型&#xff0c;支持事务 这里就印出了我们之前的知识点 DML操作就是我们对数据进行 增删除查改操作 ACID分别代表…

HTML小游戏14 —— H5横版冒险游戏《无限生机》(附完整源码)

&#x1f482; 网站推荐:【神级源码资源网】【摸鱼小游戏】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】&#x1f4ac; 免费且实用的计…

[ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(三)CSRF相关面试题

​ &#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成…

Azure CDN

Azure CDN Azure CDN 是服务器的分发网络&#xff0c;可以将网页内容更高效地分发给终端用户。 CDN在POP点的边缘服务器缓存内容&#xff0c;这样更临近终端用户&#xff0c;延迟低。 Azure CDN 给开发者提供全球解决方案&#xff0c;能够将内容放在全球各个节点&#xff0c;提…

MotoSimEG-VRC软件:龙门架外部设备添加以及示教编程与仿真运行

目录 概述 龙门架添加与属性配置 龙门架软限位设定 龙门架示教编程 仿真运行 概述 龙门架是工业生产中十分常见的自动化设备&#xff0c;由于其具备三维空间内的多自由度运动特性&#xff0c;通常被作为堆垛机&#xff0c;广泛应用在仓储物流领域。也可以作为直角坐标机器…

如何通过 Hardhat 来验证智能合约

在很大程度上&#xff0c;由于部署到通用区块链的智能合约的不变性&#xff0c;安全始终是用户和企业的首要任务。因此&#xff0c;在以太坊上开发智能合约的关键步骤之一是初始部署后的 Etherscan 验证。Etherscan 使任何人&#xff0c;从用户到经验丰富的开发人员和 bug hunt…

计算机组成原理课程设计(1)

指令设计 计算机组成原理课程设计 1、完成以下9条指令的设计&#xff1a; LDI Rd,#data&#xff0c;LDA Rd,adr&#xff0c;STA adr,Rs&#xff0c;LDR Rd,Rs&#xff0c;ADD Rd,Rs&#xff0c;XOR Rd,Rs&#xff0c;JMP adr&#xff0c;JZ adr&#xff0c;HALT 2.指令设计 …

全球著名漫画家蔡志忠创作的“EIS元宇宙之门”数字艺术品限量发售!11.29正式开售

开启宇宙之门 2022年12月3日&#xff0c;EIS我们将一起迎接一个新的爆发机会——品牌将正式接轨元宇宙一个全新的营销时代即将来临&#xff01;首次集结千位元宇宙领域品牌营销头号玩家&#xff0c;找到通往元宇宙智慧的不二法门&#xff01; 品牌营销领域一次全新的风向标&am…

SPARK数据分析

有了 DataFrame 之后&#xff0c;我们该如何在 DataFrame 之上做数据探索、数据分析&#xff0c;以及各式各样的数据转换呢&#xff1f;在数据处理完毕之后&#xff0c;我们又该如何做数据展示与数据持久化呢&#xff1f;今天这一讲&#xff0c;我们就来解答这些疑问。 为了给开…