演练:使用 AWS CloudFormation Designer 修改堆栈的模板 - AWS CloudFormation

演练:使用 AWS CloudFormation Designer 修改堆栈的模板

您可以使用 AWS CloudFormation Designer 轻松修改堆栈模板,然后将其提交到 AWS CloudFormation 以更新堆栈。通常,在修改堆栈时,您需要获取其模板的副本,在文本编辑器中修改模板,然后使用 CloudFormation 更新堆栈。借助 AWS CloudFormation Designer,您可以快速获取任何正在运行的堆栈的模板副本,修改该模板,然后更新堆栈,而不必离开控制台。

在此演练中,我们从一个基本 Web 服务器堆栈开始,然后修改它,以使该 Web 服务器可扩展且持久。

在此演练中,我们将完成以下步骤:

  1. 获取堆栈的模板。

    我们将获取正在运行的堆栈的模板副本 - 与以下演练中的基本 Web 服务器堆栈相同:演练:使用 AWS CloudFormation Designer 创建基本 Web 服务器

  2. 修改模板。

    我们将使用 AWS CloudFormation Designer 修改此堆栈的模板(用自动扩缩组和 Elastic Load Balancing 负载均衡器替换 EC2 实例),以使您的网站可扩展且持久。

  3. 更新堆栈。

    保存修改后,我们将用修改的模板更新此基本 Web 服务器堆栈。

    注意

    CloudFormation 是一种免费服务;但是,您需要为您在堆栈使用的 AWS 资源付费,费用按每种资源的现价收取。有关 AWS 定价的详细信息,请参阅 http://aws.amazon.com 上每种产品的详细信息页。

  4. 删除堆栈。

    我们将删除堆栈,以清理所有资源。

先决条件

本演练假定您具有 Amazon Virtual Private Cloud (Amazon VPC)、Auto Scaling、Elastic Load Balancing 和 CloudFormation 方面的工作经验。为了解上下文,每个过程提供了有关每项资源的一些基本信息。

此外,本演练还假定您已完成下面的演练:演练:使用 AWS CloudFormation Designer 创建基本 Web 服务器。在上述演练中,您应该获得了一个名为 BasicWebServerStack 的正在运行的堆栈。

步骤 1:获取堆栈模板

在此步骤中,我们将使用 AWS CloudFormation Designer 获取正在运行的堆栈的模板副本并将其打开。

获取正在运行的堆栈的模板副本
  1. 通过以下网址打开 CloudFormation 控制台:https://console.aws.amazon.com/cloudformation/

  2. 从堆栈列表中,选择 BasicWebServerStack

  3. 依次选择 ActionsView/Edit template in Designer

CloudFormation 获取 BasicWebServerStack 堆栈的模板副本并在 AWS CloudFormation Designer 中显示它,您可以在其中看到该模板的资源及其关系。在下一步中,我们将使用 AWS CloudFormation Designer 修改该模板。

步骤 2:修改模板

我们将使用 AWS CloudFormation Designer 的拖放界面和集成的 JSON 和 YAML 编辑器修改基本 Web 服务器模板,即,将单个 Amazon EC2 实例替换为自动扩缩组和负载均衡器以使网站可扩展。如果网站的流量突然增多,则使用 Auto Scaling 可快速增加 Web 服务器的数量。负载均衡器会将流量均匀地分配到多个实例上。

修改堆栈模板
  1. 删除 WebServerInstance 资源。

    1. 右键单击 WebServerInstance 资源。

    2. 从资源菜单中选择删除 ( )。

    3. 选择 OK 确认。

  2. Resource types 窗格中,将以下资源添加到 PublicSubnet 资源中:AutoScalingGroupLaunchConfigurationLoadBalancer。添加资源前,您可能需要扩展子网以包含所有资源。

    资源按资源类别组织。自动扩缩组和启动配置位于 AutoScaling 类别中,负载均衡器位于 ElasticLoadBalancing 类别中。

    注意

    这些资源不遵守容器模型,因此,AWS CloudFormation Designer 不会将它们自动关联到子网。我们会在此步骤的稍后部分创建连接。

  3. EC2 类别的 Resource types 窗格,将 SecurityGroup 资源添加到 VPC 中的任意位置,但不要加入到子网中。

    此安全组将负责控制负载均衡器的入站和出站通信。

  4. 重命名资源以使其更易识别:

    • AutoScalingGroup 重命名为 WebServerFleet

    • LaunchConfiguration 重命名为 WebServerLaunchConfig

    • LoadBalancer 重命名为 PublicElasticLoadBalancer

    • SecurityGroup 重命名为 PublicLoadBalancerSecurityGroup

  5. 为添加的资源创建关联。

    1. 将负载均衡器和自动扩缩组资源关联到公有子网:

      • PublicElasticLoadBalancer 资源拖动到 AWS::EC2::Subnet (Property: Subnets) 资源的 PublicSubnet 连接。

      • WebServerFleet 资源拖动到 AWS::EC2::Subnet (Property: VPCZoneIdentifier) 资源的 PublicSubnet 连接。

    2. 将负载均衡器关联到其安全组:

      • PublicElasticLoadBalancer 资源拖动到 AWS::EC2::SecurityGroup (Property: SecurityGroups) 资源的 PublicLoadBalancerSecurityGroup 连接。

    3. 将自动扩缩组关联到负载均衡器和启动配置:

      • WebServerFleet 资源拖动到 AWS::ElasticLoadBalancing::LoadBalancer (Property: LoadBalancerNames) 资源的 PublicElasticLoadBalancer 连接。

      • WebServerFleet 资源拖动到 AWS::ElasticLoadBalancing::LaunchConfiguration (Property: LaunchConfigurationName) 资源的 WebServerLaunchConfig 连接。

    4. 将启动配置关联到安全组:

      • WebServerLaunchConfig 资源拖动到 AWS::EC2::SecurityGroup (Property: SecurityGroups) 资源的 WebServerSecurityGroup 连接。

    5. 为自动扩缩组定义对公有路由的依赖关系:

      • WebServerFleet 资源拖动到 DependsOn 资源的 PublicRoute 连接。

      该依赖关系意味着,在公有路由完成之前,CloudFormation 不会创建 WebServerFleet 资源。否则,如果公有路由在 Web 服务器实例启动时不可用,这些实例将无法在配置和应用程序部署完成时发送信号 (使用 cfn-signal 帮助程序脚本) 通知 CloudFormation。

  6. 为添加的资源指定属性。

    1. 在 AWS CloudFormation Designer 画布上,选择 PublicElasticLoadBalancer 资源。

    2. 在集成编辑器窗格中,选择属性选项卡,然后复制以下代码段并将其粘贴到属性 大括号 ({}) 之间。

      AWS CloudFormation Designer 会自动添加安全组和子网关联,因此,您只需要添加 ListenersHealthCheck 属性。Listeners 属性指定侦听位置及侦听何种类型的流量,HealthCheck 属性描述确定负载均衡器运行状况的设置。

      JSON

      "Listeners": [ { "LoadBalancerPort": "80", "InstancePort": "80", "Protocol": "HTTP" } ], "HealthCheck": { "Target": "HTTP:80/", "HealthyThreshold": "3", "UnhealthyThreshold": "5", "Interval": "90", "Timeout": "60" }, "SecurityGroups": [ { "Ref": "PublicLoadBalancerSecurityGroup" } ], "Subnets": [ { "Ref": "PublicSubnet" } ]

      YAML

      Listeners: - LoadBalancerPort: '80' InstancePort: '80' Protocol: HTTP HealthCheck: Target: 'HTTP:80/' HealthyThreshold: '3' UnhealthyThreshold: '5' Interval: '90' Timeout: '60' SecurityGroups: - !Ref PublicLoadBalancerSecurityGroup Subnets: - !Ref PublicSubnet
    3. 为以下资源重复这一过程:

      WebServerFleet

      添加 MaxSizeMinSizeDesiredCapacity 属性。这些属性指定您可在自动扩缩组中启动的最大、最小实例数及初始启动的实例数。所需容量值通过一个新的参数指定,我们将在此过程的稍后部分添加该参数。

      JSON

      "MinSize": "1", "MaxSize": "10", "DesiredCapacity": { "Ref": "WebServerCount" }, "VPCZoneIdentifier": [ { "Ref": "PublicSubnet" } ], "LaunchConfigurationName": { "Ref": "WebServerLaunchConfig" }, "LoadBalancerNames": [ { "Ref": "PublicElasticLoadBalancer" } ]

      YAML

      MinSize: '1' MaxSize: '10' DesiredCapacity: !Ref WebServerCount VPCZoneIdentifier: - !Ref PublicSubnet LaunchConfigurationName: !Ref WebServerLaunchConfig LoadBalancerNames: - !Ref PublicElasticLoadBalancer
      PublicLoadBalancerSecurityGroup

      添加以下入站和出站规则,用以确定可到达和离开负载均衡器的流量。这些规则允许所有 HTTP 流量到达和离开负载均衡器。

      JSON

      "GroupDescription": "Public Elastic Load Balancing security group with HTTP access on port 80 from the Internet", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "CidrIp": "0.0.0.0/0" } ], "SecurityGroupEgress": [ { "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "CidrIp": "0.0.0.0/0" } ], "VpcId": { "Ref": "VPC" }

      YAML

      GroupDescription: >- Public Elastic Load Balancing security group with HTTP access on port 80 from the Internet SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 VpcId: !Ref VPC
      WebServerSecurityGroup

      修改 HTTP 入站规则,仅允许来自负载均衡器的流量。

      JSON

      "GroupDescription": "Allow access from load balancer and SSH traffic", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "SourceSecurityGroupId": { "Ref": "PublicLoadBalancerSecurityGroup" } }, { "IpProtocol": "tcp", "FromPort": 22, "ToPort": 22, "CidrIp": { "Ref": "SSHLocation" } } ], "VpcId": { "Ref": "VPC" }

      YAML

      VpcId: !Ref VPC GroupDescription: Allow access from load balancer and SSH traffic SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: !Ref PublicLoadBalancerSecurityGroup - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref SSHLocation
      WebServerLaunchConfig

      启动配置有很多需要指定的不同属性,我们只重点介绍其中几个属性。InstanceTypeImageId 属性使用已在模板中指定的参数和映射值。创建堆栈时,需要以参数值的形式指定实例类型。ImageId 值是基于堆栈区域和指定的实例类型的映射。

      UserData 属性中,我们指定在实例启动并运行后运行的配置脚本。配置信息均在实例的元数据中定义 (我们将在下一步中添加)。

      JSON

      "InstanceType": { "Ref": "InstanceType" }, "ImageId": { "Fn::FindInMap": [ "AWSRegionArch2AMI", { "Ref": "AWS::Region" }, { "Fn::FindInMap": [ "AWSInstanceType2Arch", { "Ref": "InstanceType" }, "Arch" ] } ] }, "KeyName": { "Ref": "KeyName" }, "AssociatePublicIpAddress": "true", "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "#!/bin/bash -xe\n", "yum install -y aws-cfn-bootstrap\n", "# Install the files and packages from the metadata\n", "/opt/aws/bin/cfn-init -v ", " --stack ", { "Ref": "AWS::StackName" }, " --resource WebServerLaunchConfig ", " --configsets All ", " --region ", { "Ref": "AWS::Region" }, "\n", "# Signal the status from cfn-init\n", "/opt/aws/bin/cfn-signal -e $? ", " --stack ", { "Ref": "AWS::StackName" }, " --resource WebServerFleet ", " --region ", { "Ref": "AWS::Region" }, "\n" ] ] } }, "SecurityGroups": [ { "Ref": "WebServerSecurityGroup" } ]

      YAML

      InstanceType: !Ref InstanceType ImageId: !FindInMap - AWSRegionArch2AMI - !Ref 'AWS::Region' - !FindInMap - AWSInstanceType2Arch - !Ref InstanceType - Arch KeyName: !Ref KeyName AssociatePublicIpAddress: 'true' UserData: !Base64 'Fn::Join': - '' - - | #!/bin/bash -xe - | yum install -y aws-cfn-bootstrap - | # Install the files and packages from the metadata - '/opt/aws/bin/cfn-init -v ' - ' --stack ' - !Ref 'AWS::StackName' - ' --resource WebServerLaunchConfig ' - ' --configsets All ' - ' --region ' - !Ref 'AWS::Region' - |+ - | # Signal the status from cfn-init - '/opt/aws/bin/cfn-signal -e $? ' - ' --stack ' - !Ref 'AWS::StackName' - ' --resource WebServerFleet ' - ' --region ' - !Ref 'AWS::Region' - |+ SecurityGroups: - !Ref WebServerSecurityGroup
  7. 将启动配置元数据添加到 WebServerLaunchConfig 资源,指示 cfn-init 帮助程序脚本启动 Web 服务器并创建基本网页。

    1. 选择 WebServerLaunchConfig 资源,然后在集成编辑器中选择元数据选项卡。

    2. 如果以 JSON 格式编写模板:在 Metadata 括号 ({}) 内、AWS::CloudFormation::Designer 右括号后面添加一个逗号 (,)。

    3. AWS::CloudFormation::Designer 属性后添加下面的代码段,指示 cfn-init 帮助程序脚本启动 Web 服务器并创建基本网页。

      JSON

      "AWS::CloudFormation::Init" : { "configSets" : { "All" : [ "ConfigureSampleApp" ] }, "ConfigureSampleApp" : { "packages" : { "yum" : { "httpd" : [] } }, "files" : { "/var/www/html/index.html" : { "content" : { "Fn::Join" : ["\n", [ "<h1>Congratulations, you have successfully launched the AWS CloudFormation sample.</h1>" ]]}, "mode" : "000644", "owner" : "root", "group" : "root" } }, "services" : { "sysvinit" : { "httpd" : { "enabled" : "true", "ensureRunning" : "true" } } } } }

      YAML

      'AWS::CloudFormation::Init': configSets: All: - ConfigureSampleApp ConfigureSampleApp: packages: yum: httpd: [] files: /var/www/html/index.html: content: !Join - |+ - - >- <h1>Congratulations, you have successfully launched the AWS CloudFormation sample.</h1> mode: '000644' owner: root group: root services: sysvinit: httpd: enabled: 'true' ensureRunning: 'true'
  8. 添加 WebServerCount 参数。该参数指定在 CloudFormation 创建自动扩缩组时要创建多少个实例。

    1. 选择 AWS CloudFormation Designer 画布上的空白区域。

    2. 在集成编辑器窗格中,选择参数选项卡。

    3. 在 集成编辑器 中添加以下参数。如果以 JSON 格式编写模板,请根据需要添加逗号。

      JSON

      "WebServerCount": { "Description": "Number of Amazon EC2 instances to launch for the WebServer server", "Type": "Number", "Default": "1" }

      YAML

      WebServerCount: Description: Number of Amazon EC2 instances to launch for the WebServer server Type: Number Default: '1'
  9. 修改模板输出以显示负载均衡器的 DNS 名称。

    1. 在集成编辑器窗格中,选择输出选项卡。

    2. 修改 JSON 以使用负载均衡器 DNS 名称,如下面的代码段所示。

      JSON

      { "Outputs": { "URL": { "Value": { "Fn::GetAtt": [ "PublicElasticLoadBalancer", "DNSName" ] }, "Description": "Newly created application URL" } } }

      如果以 YAML 格式编写模板,请使用下面的代码段。

      Outputs: URL: Value: !GetAtt - PublicElasticLoadBalancer - DNSName Description: Newly created application URL
  10. 在 AWS CloudFormation Designer 工具栏上,选择 Validate template(验证模板)( )以检查模板中的语法错误。

    查看并修复 Messages 窗格中的错误,然后再次验证模板。如果未看到错误,则说明您的模板语法上是有效的。

  11. 从 AWS CloudFormation Designer 工具栏中,选择 File(文件)( ),然后选择 Save(保存)以在本地保存模板。

现在,您已获得一个可用于更新基本 Web 服务器堆栈的修改的 CloudFormation 模板。在下一步中,我们将使用此模板更新基本 Web 服务器堆栈。

步骤 3:更新堆栈

要实施模板更改,我们需要更新基本 Web 服务器堆栈。您可以从 AWS CloudFormation Designer 中直接启动 CloudFormation 更新堆栈向导。

更新堆栈
  1. 在 AWS CloudFormation Designer 工具栏上,选择 Create Stack(创建堆栈)( )。

    AWS CloudFormation Designer 将打开的模板保存到 S3 桶中,然后启动 CloudFormation 更新堆栈向导。由于我们修改了 BasicWebServerStack 堆栈的模板,因此,CloudFormation 会为此堆栈启动更新堆栈向导。

  2. CloudFormation 会自动填充模板 URL;选择 Next

  3. Stack 部分的 Name 字段中,确认堆栈名称为 BasicWebServerStack

  4. Parameters 部分中,使用现有的值;选择 Next

  5. 在本演练中,您无需添加标记或指定高级设置,因此请选择 Next

  6. 确保堆栈名称正确,然后选择 Update

CloudFormation 可能需要几分钟时间更新堆栈。要监控进度,可查看堆栈事件。有关更多信息,请参阅在 AWS Management Console上查看 AWS CloudFormation 堆栈数据和资源。堆栈更新后,查看堆栈输出并前往网站 URL,确认网站正在运行。有关更多信息,请参阅在 AWS Management Console上查看 AWS CloudFormation 堆栈数据和资源。您使用 AWS CloudFormation Designer 成功地更新了模板和堆栈。

要确保不因任何不必要的服务而产生费用,您可以删除此堆栈。

步骤 4:清理资源

要确保不因不必要的服务而产生费用,请删除您的堆栈及其资源。

删除堆栈
  1. 从 CloudFormation 控制台,选择 BasicWebServerStack 堆栈。

  2. 选择 Delete Stack

  3. 在确认消息中,选择 Yes, Delete

CloudFormation 可能需要几分钟时间删除堆栈。要监控进度,可查看堆栈事件。堆栈删除后,您创建的所有资源都被删除。现在,您已明白如何使用 AWS CloudFormation Designer,您可以使用它构建和修改自己的模板了。