利用AWS CloudFormation 管控AWS基础设施

一 概述

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

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

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

  1. 编写模板:使用AWS CloudFormation模板语言(JSON或YAML格式)编写模板,描述您想要创建的基础设施。模板可以定义各种AWS资源及其属性,以及资源之间的关系和依赖。
  2. 创建堆栈:使用AWS Management Console、AWS命令行界面(CLI)或AWS SDK等工具,将模板上传到CloudFormation服务,并创建一个新的堆栈。在创建堆栈时,可以指定一些参数,以自定义堆栈的行为和配置。
  3. 等待创建完成:CloudFormation会自动处理资源的创建过程,并在完成后更新堆栈的状态。您可以通过AWS管理控制台或CLI监视堆栈的创建进度。
  4. 更新和扩展:如果您需要对基础设施进行更改,可以更新CloudFormation模板并执行堆栈更新操作。CloudFormation会自动检测到更改,并根据更新的模板进行必要的修改。
  5. 删除堆栈:如果不再需要某个堆栈,您可以使用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 命令来检测更改。最后,创建一个更改集,以便将子网添加到环境中。

四 实战操作

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

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

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

查看aws cli版本

查看lab1.yaml内容

YAML 复制代码
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 格式的模板。

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

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

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

  • 验证stack状态
Shell 复制代码
aws cloudformation describe-stacks --stack-name Lab1

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

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

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

手动添加we端口放行

查看网页可以正常查看

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

查看偏差结果

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

Shell 复制代码
aws cloudformation describe-stack-resource-drifts --stack-name Lab1 --stack-resource-drift-status-filters MODIFIED DELETED
  • 使用更改集更新堆栈
  • 创建更改集
Plaintext 复制代码
aws cloudformation create-change-set --stack-name Lab1 --change-set-name Lab1ChangeSet --parameters ParameterKey=InstanceType,ParameterValue=t2.micro --template-body file://lab1-CS.yaml

预期输出

五 总结

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

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

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

相关推荐
无所不在的物质3 小时前
Jenkins基础教程
运维·云原生·自动化·jenkins
是芽芽哩!5 小时前
【Kubernetes 指南】基础入门——Kubernetes 基本概念(二)
云原生·容器·kubernetes
SelectDB6 小时前
Apache Doris 创始人:何为“现代化”的数据仓库?
大数据·数据库·云原生
m0_663234016 小时前
云原生是什么
云原生
运维小文8 小时前
K8S中的服务质量QOS
云原生·容器·kubernetes
华为云开发者联盟8 小时前
Karmada v1.12 版本发布!单集群应用迁移可维护性增强
云原生·kubernetes·开源·容器编排·karmada
Hadoop_Liang9 小时前
Kubernetes Secret的创建与使用
云原生·容器·kubernetes
元气满满的热码式9 小时前
K8S集群部署实战(超详细)
云原生·容器·kubernetes
秀儿y11 小时前
单机服务和微服务
java·开发语言·微服务·云原生·架构
运维&陈同学16 小时前
【Beats01】企业级日志分析系统ELK之Metricbeat与Heartbeat 监控
运维·elk·elasticsearch·云原生·kibana·heartbeat·metricbeat