利用AWS CloudFormation 管控AWS基础设施

2024年 2月 11日 83.3k 0

一 概述

AWS CloudFormation是一项AWS的托管服务,可用于以声明性模板的形式定义和配置AWS基础设施。它允许您以编程方式创建、更新和管理AWS资源,而无需手动操作。

利用AWS CloudFormation,您可以使用模板定义整个基础设施堆栈,包括计算资源(例如Amazon EC2实例)、存储资源(例如Amazon S3存储桶)和网络资源(例如Amazon VPC)。一旦定义了模板,您可以使用CloudFormation服务创建和管理基础设施堆栈,这样可以确保环境的一致性和可重复性。

以下是利用AWS CloudFormation进行基础设施管理的一般步骤:

  • 编写模板:使用AWS CloudFormation模板语言(JSON或YAML格式)编写模板,描述您想要创建的基础设施。模板可以定义各种AWS资源及其属性,以及资源之间的关系和依赖。
  • 创建堆栈:使用AWS Management Console、AWS命令行界面(CLI)或AWS SDK等工具,将模板上传到CloudFormation服务,并创建一个新的堆栈。在创建堆栈时,可以指定一些参数,以自定义堆栈的行为和配置。
  • 等待创建完成:CloudFormation会自动处理资源的创建过程,并在完成后更新堆栈的状态。您可以通过AWS管理控制台或CLI监视堆栈的创建进度。
  • 更新和扩展:如果您需要对基础设施进行更改,可以更新CloudFormation模板并执行堆栈更新操作。CloudFormation会自动检测到更改,并根据更新的模板进行必要的修改。
  • 删除堆栈:如果不再需要某个堆栈,您可以使用CloudFormation服务删除它。删除堆栈将删除与该堆栈关联的所有资源,并释放使用的AWS资源。
  • 二 目标

    • 在 YAML 中构建 AwS cloudFormation 模板以定义基础设施资源。
    • 创建CloudFormation 堆栈以预置基础架构并查看输出。
    • 检测 AWS CloudFormation 堆栈中的偏差并生成偏差报告。
    • 使用 AwS cloudFormation 更改集更新您的基础设施。

    三 场景

    在本实验中,您的任务是为开发团队创建一个简单的环境。开发团队要求打造一个可以通过 HTTP 和 SSH 访问的 Apache Web 服务器。根据提供给您的要求文档,您需要一个专用 VPC、单个子网,以及一个小型 Amazon Elastic Compute Cloud (Amazon EC2) 实例。您将使用 AwS cloud9 环境来修改现有 AwS cloudFormation 模板,以满足开发团队的要求,修改模板以使用 CloudFormation 的变更集和检测偏差功能。

    首先,使用 Aws cloud9 修改 Aws cloudFormation 模板,以便构建简单的 Amazon Virtual Private cloud (Amazon vPc) 环境,并部署一个包含简单网页的 web 服务器。其次,验证网页是否正常渲染,然后手动修改 AWS Identity and Access Management (IAM)安全组,并使用 Detect drift 命令来检测更改。最后,创建一个更改集,以便将子网添加到环境中。

    img

    四 实战操作

    登陆Cloud9:ap-south-1.console.aws.amazon.com/cloud9/ide/…

    img

    在本任务中,您将连接到 AWS Cloud9 集成开发环境 (IDE, Integrated Development Environment)。

    Cloud9 开发环境预先打包了适用于 40 多种编程语言的 AWS CLI 和工具。在此任务中,您将验证是否已安装 AWS CLl。

    查看aws cli版本

    img

    查看lab1.yaml内容

    img

    AWSTemplateFormatVersion: 2010-09-09
    Description: >-
      AWS CloudFormation Simple Infrastructure Template
      VPC_Single_Instance_In_Subnet: This template will show how to create a VPC and
      add an EC2 instance with an Elastic IP address and a security group.
    Parameters:
      VPCCIDR:
        Description: CIDR Block for VPC
        Type: String
        Default: 10.199.0.0/16
        AllowedValues:
          - 10.199.0.0/16
      PUBSUBNET1:
        Description: Public Subnet 1
        Type: String
        Default: 10.199.10.0/24
        AllowedValues:
          - 10.199.10.0/24
      ## TASK 1.1 - BEGIN: Add the parameter definition for InstanceType
      InstanceType:
        Description: WebServer EC2 instance type
        Type: String
        Default: t2.nano
        AllowedValues:
          - t2.nano
          - t2.micro
          - t2.small
        ConstraintDescription: must be a valid EC2 instance type.
      ## TASK 1.1 - END
      LatestAmiId:
        Description: Find the current AMI ID using System Manager Parameter Store
        Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
        Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
    
    Resources:
      VPC:
        Type: 'AWS::EC2::VPC'
        Properties:
          CidrBlock: !Ref VPCCIDR
          EnableDnsSupport: 'true'
          EnableDnsHostnames: 'true'
          Tags:
            - Key: Application
              Value: !Ref 'AWS::StackId'
            - Key: Name
              Value: CF lab environment
      Subnet:
        Type: 'AWS::EC2::Subnet'
        DependsOn: VPC
        Properties:
          VpcId: !Ref VPC
          CidrBlock: !Ref PUBSUBNET1
          MapPublicIpOnLaunch: 'true'
          AvailabilityZone: !Select 
            - '0'
            - !GetAZs ''
          Tags:
            - Key: Application
              Value: !Ref 'AWS::StackId'
            - Key: Name
              Value: Public Subnet
      InternetGateway:
        Type: 'AWS::EC2::InternetGateway'
        DependsOn: VPC
        Properties:
          Tags:
            - Key: Application
              Value: !Ref 'AWS::StackId'
      AttachGateway:
        Type: 'AWS::EC2::VPCGatewayAttachment'
        DependsOn: VPC
        Properties:
          VpcId: !Ref VPC
          InternetGatewayId: !Ref InternetGateway
      RouteTable:
        Type: 'AWS::EC2::RouteTable'
        DependsOn: VPC
        Properties:
          VpcId: !Ref VPC
          Tags:
            - Key: Application
              Value: !Ref 'AWS::StackId'
    
      ## Route resource
      # TASK 1.2- BEGIN: Add the resource definition for ROUTE
      Route:
        Type: 'AWS::EC2::Route'
        DependsOn:
          - VPC
          - AttachGateway
        Properties:
          RouteTableId: !Ref RouteTable
          DestinationCidrBlock: 0.0.0.0/0
          GatewayId: !Ref InternetGateway
      # TASK 1.2 - END
      SubnetRouteTableAssociation: 
        Type: 'AWS::EC2::SubnetRouteTableAssociation'
        DependsOn:
          - VPC
          - InternetGateway
        Properties:
          SubnetId: !Ref Subnet
          RouteTableId: !Ref RouteTable
      NetworkAcl:
        Type: 'AWS::EC2::NetworkAcl'
        DependsOn:
          - VPC
          - InternetGateway
        Properties:
          VpcId: !Ref VPC
          Tags:
            - Key: Application
              Value: !Ref 'AWS::StackId'
      InboundHTTPNetworkAclEntry:
        Type: 'AWS::EC2::NetworkAclEntry'
        DependsOn:
          - VPC
          - InternetGateway
        Properties:
          NetworkAclId: !Ref NetworkAcl
          RuleNumber: '100'
          Protocol: '6'
          RuleAction: allow
          Egress: 'false'
          CidrBlock: 0.0.0.0/0
          PortRange:
            From: '80'
            To: '80'
      InboundNetworkAclEntry:
        Type: 'AWS::EC2::NetworkAclEntry'
        DependsOn:
          - VPC
          - InternetGateway
        Properties:
          NetworkAclId: !Ref NetworkAcl
          RuleNumber: '101'
          Protocol: '6'
          RuleAction: allow
          Egress: 'false'
          CidrBlock: 0.0.0.0/0
          PortRange:
            From: '22'
            To: '22'
      InboundResponsePortsNetworkAclEntry:
        Type: 'AWS::EC2::NetworkAclEntry'
        DependsOn:
          - VPC
          - InternetGateway
        Properties:
          NetworkAclId: !Ref NetworkAcl
          RuleNumber: '102'
          Protocol: '6'
          RuleAction: allow
          Egress: 'false'
          CidrBlock: 0.0.0.0/0
          PortRange:
            From: '1024'
            To: '65535'
      OutBoundHTTPNetworkAclEntry:
        Type: 'AWS::EC2::NetworkAclEntry'
        DependsOn:
          - VPC
          - InternetGateway
        Properties:
          NetworkAclId: !Ref NetworkAcl
          RuleNumber: '100'
          Protocol: '6'
          RuleAction: allow
          Egress: 'true'
          CidrBlock: 0.0.0.0/0
          PortRange:
            From: '80'
            To: '80'
      OutBoundHTTPSNetworkAclEntry:
        Type: 'AWS::EC2::NetworkAclEntry'
        DependsOn:
          - VPC
          - InternetGateway
        Properties:
          NetworkAclId: !Ref NetworkAcl
          RuleNumber: '101'
          Protocol: '6'
          RuleAction: allow
          Egress: 'true'
          CidrBlock: 0.0.0.0/0
          PortRange:
            From: '443'
            To: '443'
      OutBoundResponsePortsNetworkAclEntry:
        Type: 'AWS::EC2::NetworkAclEntry'
        DependsOn:
          - VPC
          - InternetGateway
        Properties:
          NetworkAclId: !Ref NetworkAcl
          RuleNumber: '102'
          Protocol: '6'
          RuleAction: allow
          Egress: 'true'
          CidrBlock: 0.0.0.0/0
          PortRange:
            From: '1024'
            To: '65535'
      SubnetNetworkAclAssociation:
        Type: 'AWS::EC2::SubnetNetworkAclAssociation'
        Properties:
          SubnetId: !Ref Subnet
          NetworkAclId: !Ref NetworkAcl
      IPAddress:
        Type: 'AWS::EC2::EIP'
        DependsOn: AttachGateway
        Properties:
          Domain: vpc
          InstanceId: !Ref WebServerInstance
      InstanceSecurityGroup:
        Type: 'AWS::EC2::SecurityGroup'
        Properties:
          VpcId: !Ref VPC
          GroupDescription: Enable HTTP via port 80
          SecurityGroupIngress:
            - IpProtocol: tcp
              FromPort: '80'
              ToPort: '80'
        # TASK 4.1 - BEGIN: Change IP Range to 0.0.0.0/0
              CidrIp: 1.1.1.1/32
        # TASK 4.1 - END
      WebServerInstance:
        Type: 'AWS::EC2::Instance'
        DependsOn: AttachGateway
        Metadata:
          Comment: Install a simple application
          'AWS::CloudFormation::Init':
            config:
              packages:
                yum:
                  httpd: []
              files:
                /var/www/html/index.html:
                  content: !Join 
                    - |+
    
                    - - >-
                        <h1>Congratulations, you have successfully deployed a simple
                        infrastructure using AWS CloudFormation.</h1>
                  mode: '000644'
                  owner: root
                  group: root
                /etc/cfn/cfn-hup.conf:
                  content: !Join 
                    - ''
                    - - |
                        [main]
                      - stack=
                      - !Ref 'AWS::StackId'
                      - |+
    
                      - region=
                      - !Ref 'AWS::Region'
                      - |+
    
                  mode: '000400'
                  owner: root
                  group: root
                /etc/cfn/hooks.d/cfn-auto-reloader.conf:
                  content: !Join 
                    - ''
                    - - |
                        [cfn-auto-reloader-hook]
                      - |
                        triggers=post.update
                      - >
                        path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
                      - 'action=/opt/aws/bin/cfn-init -v '
                      - '         --stack '
                      - !Ref 'AWS::StackName'
                      - '         --resource WebServerInstance '
                      - '         --region '
                      - !Ref 'AWS::Region'
                      - |+
    
                      - |
                        runas=root
                  mode: '000400'
                  owner: root
                  group: 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:
          InstanceType: !Ref InstanceType
          ImageId: !Ref LatestAmiId
          Tags:
            - Key: Application
              Value: !Ref 'AWS::StackId'
            - Key: Name
              Value: Lab Host
          NetworkInterfaces:
            - GroupSet:
                - !Ref InstanceSecurityGroup
              AssociatePublicIpAddress: 'true'
              DeviceIndex: '0'
              DeleteOnTermination: 'true'
              SubnetId: !Ref Subnet
          UserData: !Base64 
            'Fn::Join':
              - ''
              - - |
                  #!/bin/bash -xe
                - |
                  yum update -y aws-cfn-bootstrap
                - '/opt/aws/bin/cfn-init -v '
                - '         --stack '
                - !Ref 'AWS::StackName'
                - '         --resource WebServerInstance '
                - '         --region '
                - !Ref 'AWS::Region'
                - |+
    
                - '/opt/aws/bin/cfn-signal -e $? '
                - '         --stack '
                - !Ref 'AWS::StackName'
                - '         --resource WebServerInstance '
                - '         --region '
                - !Ref 'AWS::Region'
                - |+
    
        CreationPolicy:
          ResourceSignal:
            Timeout: PT15M
    ##Outputs
    Outputs:
      MySecurityGroup:
        Description: Application instance's security group name
        Value: 
            !GetAtt 
              - InstanceSecurityGroup
              - GroupId
    # TASK 1.3 - BEGIN: Add the output definition for URL
      AppURL:
        Description: Newly created application URL
        Value: !Sub 'http://${WebServerInstance.PublicIp}'
    # TASK 1.3 - END
    
    • Description(描述):描述模板的文本字符串。
    • Parameters(参数):创建或更新堆栈时在运行时传递给模板的值。
    • Resources(资源):指定堆栈资源及其属性。
    • Outputs(输出):堆栈运行成功完成后,作为堆栈属性返回的值。

    AWS CloudFormation 可以提供一种通用语言,供您在云环境中对资源进行建模和预置。您可以使用 CloudFormation 模板语言(YAML或 JSON 格式)对基础设施进行编码。

    YAML 和 JSON 都是数据序列化语言,但具有不同的功能。AwS cloudFormation 仅处理 JSON 格式的语言;启动堆栈创建时,YAML格式的模板会被转换为JSON 格式的模板。

    • 构建
    aws cloudformation create-stack --stack-name Lab1 --parameters ParameterKey=InstanceType,ParameterValue=t2.micro --template-body file://lab1.yaml
    

    img

    create-stack 命令可以调用指定的 AWS CloudFormation 模板并启动堆栈创建流程。参数 InstanceType 告知 CloudFormation 要部署的 Amazon EC2 实例的大小。

    成功运行 create-stack 命令后,系统将在命令行中返回 Stackld。

    • 验证stack状态
    aws cloudformation describe-stacks --stack-name Lab1
    

    img

    注意:describe-stacks 命令会向终端返回大量信息。它会提供模板定义的每个资源的相关信息、构建流程中的当前状态以及您在运行 describe-stacks 命令时可用的资源的特定属性。AWS CloudFormation 控制面板会以更友好的格式提供这些信息。

    img

    CREATE_COMPLETE 状态代码表示堆栈创建过程已完成。

    img

    img

    此时访问ip无法访问,因为安全中未正确放行端口

    手动添加we端口放行

    img

    查看网页可以正常查看

    img

    由于手动通过web修改配置于基础设施代码发生不一致,通过web进行偏差检测。

    img

    查看偏差结果

    img

    通过偏差检测,您可以检测堆栈的实际配置是否与其预期配置不同。如果某个资源的任何实际属性值与预期的属性值不同,则认为该资源已发生偏差。这包括是否已删除属性或资源。在本实验中,您可以手动更改资源的值。解决这一偏差的最直接的方法是手动将资源修改回预期值。如果更改是因部署其他堆栈造成的,则回滚其他堆栈的更改。如果别无他法,可以删除堆栈,重新部署,但这种方法的破坏性最大。有关偏差的更多信息,请访问此链接:检测对堆栈和资源做出的非托管配置更改,通过CLI 验证 APPURL 是否正常运行。

    aws cloudformation describe-stack-resource-drifts --stack-name Lab1 --stack-resource-drift-status-filters MODIFIED DELETED
    

    img

    • 使用更改集更新堆栈

    img

    • 创建更改集
    aws cloudformation create-change-set --stack-name Lab1 --change-set-name Lab1ChangeSet --parameters ParameterKey=InstanceType,ParameterValue=t2.micro --template-body file://lab1-CS.yaml
    

    预期输出:

    img

    img

    img

    五 总结

    AWS CloudFormation是一种基础设施即代码(Infrastructure as Code)服务,它允许用户以声明性的方式定义和管理AWS基础设施资源。通过编写模板,用户可以描述他们想要创建的资源以及资源之间的关系和配置。然后,通过CloudFormation服务,用户可以创建、更新和删除这些资源的堆栈。

    使用CloudFormation的好处之一是它的可扩展性。用户可以在模板中定义多个资源,包括虚拟私有云(VPC)、子网、负载均衡器、数据库实例等等。通过一次性部署整个堆栈,可以确保资源之间的正确关联和配置,减少了手动部署和配置的错误。

    另一个优点是CloudFormation的自动化特性。一旦定义了模板,用户可以使用API、CLI或控制台工具自动创建和管理堆栈。这意味着可以轻松地进行重复部署、跨不同环境的迁移以及快速恢复操作。此外,CloudFormation还支持版本控制和回滚功能,使得管理和追踪基础设施变更变得更加容易和可控。

    相关文章

    KubeSphere 部署向量数据库 Milvus 实战指南
    探索 Kubernetes 持久化存储之 Longhorn 初窥门径
    征服 Docker 镜像访问限制!KubeSphere v3.4.1 成功部署全攻略
    那些年在 Terraform 上吃到的糖和踩过的坑
    无需 Kubernetes 测试 Kubernetes 网络实现
    Kubernetes v1.31 中的移除和主要变更

    发布评论