演练:使用 Amazon CloudFormation Designer 修改堆栈的模板 - Amazon CloudFormation
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

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

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

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

  1. 获取堆栈的模板。

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

  2. 修改模板。

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

  3. 更新堆栈。

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

    注意

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

  4. 删除堆栈。

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

先决条件

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

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

步骤 1:获取堆栈模板

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

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

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

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

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

步骤 2:修改模板

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

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

    1. 右键单击 WebServerInstance 资源。

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

    3. 选择 OK 确认。

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

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

    注意

    这些资源不遵守容器模型,因此,Amazon 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. 在 Amazon CloudFormation Designer 画布上,选择 PublicElasticLoadBalancer 资源。

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

      Amazon 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. 选择 Amazon 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. 在 Amazon CloudFormation Designer 工具栏上,选择 Validate template(验证模板)( )以检查模板中的语法错误。

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

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

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

步骤 3:更新堆栈

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

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

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

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

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

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

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

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

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

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

步骤 4:清理资源

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

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

  2. 选择 Delete Stack

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

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