

# 更新 CloudFormation 堆栈
<a name="updating.stacks.walkthrough"></a>

**注意**  
本教程基于 [在 Amazon EC2 上部署应用程序](deploying.applications.md) 教程中的概念生成。如果您尚未完成该教程，我们建议您先完成该教程，以了解使用 CloudFormation 进行的 EC2 引导的过程。

本主题演示了正在运行的堆栈的简单更新进展。我们将带您逐步了解以下步骤：

1. **创建起始堆栈**：使用基础 Amazon Linux 2 AMI 创建堆栈，从而使用 CloudFormation 帮助程序脚本安装 Apache Web Server 和简单的 PHP 应用程序。

1. **更新应用程序**：使用 CloudFormation 更新应用程序中的一个文件并部署软件。

1. **添加密钥对**：向实例中添加 Amazon EC2 密钥对，然后更新安全组以允许 SSH 访问实例。

1. **更新实例类型**：更改底层 Amazon EC2 实例的实例类型。

1. **更新 AMI**：在您的堆栈中更改 Amazon EC2 实例的亚马逊机器映像（AMI）。

**注意**  
CloudFormation 使用免费，但您需要为自己创建的 Amazon EC2 资源付费。如果您不熟悉 AWS，可以利用[免费套餐](https://aws.amazon.com/free/)来最大限度地降低或避免在学习过程产生费用。

**Topics**
+ [

## 第 1 步：创建起始堆栈
](#update-stack-initial-stack)
+ [

## 第 2 步：更新应用程序
](#update-stack-update-application)
+ [

## 第 3 步：添加使用密钥对的 SSH 访问权限
](#update-stack-add-key-pair)
+ [

## 第 4 步：更新实例类型
](#update-stack-update-instance-type)
+ [

## 第 5 步：更新 AMI
](#update-stack-update-ami)
+ [

## 可用性和影响注意事项
](#update.walkthrough.impact)
+ [

## 相关资源
](#update.walkthrough.related)

## 第 1 步：创建起始堆栈
<a name="update-stack-initial-stack"></a>

我们将从创建可在本主题剩下的所有内容中使用的堆栈开始。我们已提供了一个简单的模板来启动在 Apache Web Server 中托管并在 Amazon Linux 2 AMI 上运行的简单实例 PHP Web 应用程序。

Apache Web Server、PHP 和简单的 PHP 应用程序全部都由默认安装在 Amazon Linux 2 AMI 上的 CloudFormation 帮助程序脚本进行安装。以下模板代码段显示描述待安装软件包和文件的元数据，此情况下为 Amazon Linux 2 AMI 的 Yum 存储库中的 Apache Web Server 和 PHP 基础设施。代码段还显示 `Services` 部分，以确保 Apache Web Server 处于运行状态。

```
WebServerInstance:
  Type: AWS::EC2::Instance
  Metadata:
    AWS::CloudFormation::Init:
      config:
        packages:
          yum:
            httpd: []
            php: []
        files:
          /var/www/html/index.php:
            content: |
              <?php
              echo '<h1>Hello World!</h1>';
              ?>
            mode: '000644'
            owner: apache
            group: apache
        services:
          systemd:
            httpd:
              enabled: true
              ensureRunning: true
```

应用程序本身是“Hello World”示例，在模板中进行了完整定义。对于现实工作中的应用程序，文件可存储在 Amazon S3、GitHub 或另一个存储库中，并通过模板进行参考。CloudFormation 可下载软件包（如 RPM 或 RubyGem），并能引用单个的文件以及展开 `.zip` 和 `.tar` 文件，以在 Amazon EC2 实例上创建应用程序项目。

模板用于启用和配置 `cfn-hup` 进程守护程序以侦听 Amazon EC2 实例元数据中所定义配置的更改。您可以使用 `cfn-hup` 进程守护程序更新应用程序软件，如 Apache 或 PHP 的版本，也可通过 CloudFormation 更新 PHP 应用程序文件。来自该模板中同一 Amazon EC2 资源的以下代码片段展示了配置 `cfn-hup` 所需的必要部分，即每两分钟调用 `cfn-init` 一次以通知并应用元数据的更新。否则，`cfn-init` 只能在启动时运行一次。

```
files:
  /etc/cfn/cfn-hup.conf:
    content: !Sub |
      [main]
      stack=${AWS::StackId}
      region=${AWS::Region}
      # The interval used to check for changes to the resource metadata in minutes. Default is 15
      interval=2
    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 -s ${AWS::StackId} -r WebServerInstance --region ${AWS::Region}
      runas=root
services:
  systemd:
    cfn-hup:
      enabled: true
      ensureRunning: true
      files:
        - /etc/cfn/cfn-hup.conf
        - /etc/cfn/hooks.d/cfn-auto-reloader.conf
```

为了完成堆栈，在 Amazon EC2 实例定义中的 `Properties` 部分，`UserData` 属性包含调用 `cfn-init` 以安装软件包和文件的 `cloud-init` 脚本。有关更多信息，请参阅《CloudFormation 模板参考指南**》中的 [CloudFormation 帮助程序脚本参考](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/cfn-helper-scripts-reference.html)。该模板还创建了一个 Amazon EC2 安全组。

```
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  LatestAmiId:
    Description: The latest Amazon Linux 2 AMI from the Parameter Store
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'

  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: t3.micro
    AllowedValues:
      - t3.nano
      - t3.micro
      - t3.small
      - t3.medium
      - t3a.nano
      - t3a.micro
      - t3a.small
      - t3a.medium
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5a.large
      - m5a.xlarge
      - m5a.2xlarge
      - c5.large
      - c5.xlarge
      - c5.2xlarge
      - r5.large
      - r5.xlarge
      - r5.2xlarge
      - r5a.large
      - r5a.xlarge
      - r5a.2xlarge
    ConstraintDescription: must be a valid EC2 instance type.
    
Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: !Ref InstanceType
      SecurityGroupIds:
        - !Ref WebServerSecurityGroup
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          # Get the latest CloudFormation package
          yum update -y aws-cfn-bootstrap
          # Run cfn-init
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region} || error_exit 'Failed to run cfn-init'        
          # Start up the cfn-hup daemon to listen for changes to the EC2 instance metadata
          /opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'
          # Signal success or failure
          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
    Metadata:
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              httpd: []
              php: []
          files:
            /var/www/html/index.php:
              content: |
                <?php
                echo "<h1>Hello World!</h1>";
                ?>
              mode: '000644'
              owner: apache
              group: apache
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
                # The interval used to check for changes to the resource metadata in minutes. Default is 15
                interval=2
              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 -s ${AWS::StackId} -r WebServerInstance --region ${AWS::Region}
                runas=root
          services:
            systemd:
              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
    CreationPolicy:
      ResourceSignal:
        Timeout: PT5M

  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

Outputs:
  WebsiteURL:
    Value: !Sub 'http://${WebServerInstance.PublicDnsName}'
    Description: URL of the web application
```

**要使用此模板启动堆栈**

1. 复制该模板并将其作为文本文件本地保存到您的系统中。注意保存位置，因为您需要在后续步骤中使用此文件。

1. 登录到 AWS 管理控制台 并打开 CloudFormation 控制台 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)。

1. 依次选择**创建堆栈、使用新资源（标准）**。

1. 选择**选择现有模板**。

1. 在**指定模板**下，选择**上传模板文件**，浏览到您在第一步中创建的文件，然后选择**下一步**。

1. 在**指定堆栈详细信息**页面上，输入 **UpdateTutorial** 作为堆栈名称。

1. 在**参数**下，保持所有参数不变，然后选择两次**下一步**。

1. 在**审核并创建**屏幕上，选择**提交**。

当您的堆栈状态变成 `CREATE_COMPLETE` 后，**输出**选项卡会显示网站的 URL。如果您选择 `WebsiteURL` 的输出值，您将看到新 PHP 应用程序在工作。

## 第 2 步：更新应用程序
<a name="update-stack-update-application"></a>

现在您已部署好堆栈，接下来更新应用程序吧。我们将对应用程序所打印出的文本进行简单更改。要执行此操作，我们将添加回显命令至 index.php 文件，如此模板代码段所示：

```
files:
  /var/www/html/index.php:
    content: |
      <?php
      echo "<h1>Hello World!</h1>";
      echo "<p>This is an updated version of our application.</p>";
      ?>
    mode: '000644'
    owner: apache
    group: apache
```

使用文本编辑器手动编辑您保存在本地的模板文件。

现在，更新堆栈。

**要使用更新后的模板更新堆栈**

1. 在 CloudFormation 控制台中，选择您的 **UpdateTutorial** 堆栈。

1. 选择**更新、直接更新**。

1. 选择**替换现有模板**。

1. 在**指定模板**下，选择**上传模板文件**，上传修改的模板文件模板，然后选择**下一步**。

1. 在**指定堆栈详细信息**页面上，保持所有参数相同，然后选择两次**下一步**。

1. 在**审核**页面上，审核您的更改。在**更改**下，您应该会看到 CloudFormation 将更新 `WebServerInstance` 资源。

1. 选择**提交**。

当您的堆栈处于 `UPDATE_COMPLETE` 状态时，您可以再次选择 `WebsiteURL` 输出值以验证应用程序的更改已生效。`cfn-hup` 进程守护程序每 2 分钟运行一次，因此最多能花 2 分钟在堆栈更新后更改应用程序。

要查看已更新资源集，请转至 CloudFormation 控制台。在**事件**选项卡上，查看堆栈事件。在此特别示例中，Amazon EC2 实例 `WebServerInstance` 的元数据已更新，这导致 CloudFormation 也会重新评估其他资源（`WebServerSecurityGroup`）以确保没有其他更改。其他堆栈资源都未修改。CloudFormation 将只更新堆栈中受堆栈的任何更改影响的资源。此类更改可直接进行，如属性或元数据更改，也可由依赖项或 `Ref`、`GetAtt` 中的数据流或其他内部模板函数导致。有关更多信息，请参阅[内置函数参考](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html)。

这一简单更新对此过程进行了阐述。但是，您可以对您的 Amazon EC2 实例中所部署文件和软件包进行更复杂的更改。例如，您可能会确定需要将 MySQL 与 MySQL 的 PHP 支持一起添加到实例中。要执行此操作，只需要将附加软件包和文件与任何附加服务一起添加到配置中，然后更新堆栈以部署更改。

```
packages:
  yum:
    httpd: []
    php: []
    mysql: []
    php-mysql: []
    mysql-server: []
    mysql-libs: []

  ...

services:
  systemd:
    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
    mysqld:
      enabled: true
      ensureRunning: true
```

您可以更新 CloudFormation 元数据，将应用程序所使用的软件包更新到新版本。前述示例中，每个软件包的版本属性都为空，这表示 `cfn-init` 应安装最新版的软件包。

```
packages:
  yum:
    httpd: []
    php: []
```

您可以视需要指定软件包的版本字符串。如果您在后续更新堆栈调用中更改版本字符串，则会部署新版软件包。此处显示 RubyGems 软件包版本号的使用示例。支持版本化的任何软件包都可以有特定版本。

```
packages:
  rubygems:
    mysql: []
    rubygems-update:
      - "1.6.2"
    rake:
      - "0.8.7"
    rails:
      - "2.3.11"
```

## 第 3 步：添加使用密钥对的 SSH 访问权限
<a name="update-stack-add-key-pair"></a>

您还可以更新模板中的资源，以添加原先未在模板中指定的属性。为了阐明上述操作，我们将会添加 Amazon EC2 密钥对到现有 EC2 实例中，然后在 Amazon EC2 安全组中打开端口 22，从而使您可以使用 Secure Shell（SSH）访问实例。

**向现有 Amazon EC2 实例添加 SSH 访问权限**

1. 向模板额外添加两个参数，从而以现有 Amazon EC2 密钥对和 SSH 位置的名称进行传递。

   ```
   Parameters:
     KeyName:
       Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
       Type: AWS::EC2::KeyPair::KeyName
       ConstraintDescription: must be the name of an existing EC2 KeyPair.
   
     SSHLocation:
       Description: The IP address that can be used to SSH to the EC2 instances in CIDR format (e.g. 203.0.113.1/32)
       Type: String
       MinLength: 9
       MaxLength: 18
       Default: 0.0.0.0/0
       AllowedPattern: '^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$'
       ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
   ```

1. 将 `KeyName` 属性添加到 Amazon EC2 实例。

   ```
   WebServerInstance:
     Type: AWS::EC2::Instance
     Properties:
       ImageId: !Ref LatestAmiId
       InstanceType: !Ref InstanceType
       KeyName: !Ref KeyName
       SecurityGroupIds:
         - !Ref WebServerSecurityGroup
   ```

1. 将端口 22 和 SSH 位置添加到 Amazon EC2 安全组的入口规则。

   ```
   WebServerSecurityGroup:
     Type: AWS::EC2::SecurityGroup
     Properties:
       GroupDescription: Enable HTTP access via port 80 and SSH access via port 22
       SecurityGroupIngress:
         - IpProtocol: tcp
           FromPort: 80
           ToPort: 80
           CidrIp: 0.0.0.0/0
         - IpProtocol: tcp
           FromPort: 22
           ToPort: 22
           CidrIp: !Ref SSHLocation
   ```

1. 使用与 [第 2 步：更新应用程序](#update-stack-update-application) 中所述的相同步骤更新堆栈。

## 第 4 步：更新实例类型
<a name="update-stack-update-instance-type"></a>

现在，让我们演示一下如何通过更改实例类型来更新底层基础设施。

我们到目前为止所建立的堆栈使用 t3.micro Amazon EC2 实例。假设您新建的网站获取的流量比 t3.micro 实例能处理的流量多，且您现在想移动到 m5.large Amazon EC2 实例类型中。如果实例类型的架构发生变化，则必须使用不同的 AMI 创建实例。但是，t3.micro 和 m5.large 都使用相同的 CPU 架构并运行 Amazon Linux 2（x86\$164）AMI。有关更多信息，请参阅《Amazon EC2 用户指南》**中的[更改实例类型的兼容性](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/resize-limitations.html)。

让我们使用在上一步中进行修改的模板更改实例类型。由于 `InstanceType` 是模板的输入参数，我们不需要修改模板；我们能在**指定堆栈详细信息**页面上更改参数值。

**要使用新的参数值更新堆栈**

1. 在 CloudFormation 控制台中，选择您的 **UpdateTutorial** 堆栈。

1. 选择**更新、直接更新**。

1. 选择**使用当前模板**，然后选择**下一步**。

1. 在**指定堆栈详细信息**页面上，将文本框中 **InstanceType** 的值从 `t3.micro` 更改为 `m5.large`。然后，选择两次**下一步**。

1. 在**审核**页面上，审核您的更改。在**更改**下，您应该会看到 CloudFormation 将更新 `WebServerInstance` 资源。

1. 选择**提交**。

对于 EBS 支持的 Amazon EC2 实例，可以通过启动和停止实例来动态更改实例类型。CloudFormation 会尝试通过更新实例类型并重启实例来优化更改，因此实例 ID 不会更改。但是，实例重启时，实例的公用 IP 地址会更改。为了确保在更改后正确绑定弹性 IP 地址，CloudFormation 还会更新弹性 IP 地址。您可以在**事件**选项卡上的 CloudFormation 控制台中看到更改。

要通过 AWS 管理控制台 检查实例类型，请打开 Amazon EC2 控制台并在其中查找您的实例。

## 第 5 步：更新 AMI
<a name="update-stack-update-ami"></a>

现在，让我们更新堆栈以使用下一代 Amazon Linux，即 Amazon Linux 2023。

更新 AMI 是一项重大更改，需要更换实例。我们不能只通过启动和停止实例来修改 AMI；CloudFormation 会将此视为对资源不可变属性的更改。要更改不可变属性进，CloudFormation 必须启动替代资源，在此例中是运行新 AMI 的新 Amazon EC2 实例。

让我们来看看如何更新堆栈模板以使用 Amazon Linux 2023。关键更改包括更新 AMI 参数和从 `yum` 更改为 `dnf` 程序包管理器。

```
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  LatestAmiId:
    Description: The latest Amazon Linux 2023 AMI from the Parameter Store
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: '/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64'

  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: t3.micro
    AllowedValues:
      - t3.nano
      - t3.micro
      - t3.small
      - t3.medium
      - t3a.nano
      - t3a.micro
      - t3a.small
      - t3a.medium
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5a.large
      - m5a.xlarge
      - m5a.2xlarge
      - c5.large
      - c5.xlarge
      - c5.2xlarge
      - r5.large
      - r5.xlarge
      - r5.2xlarge
      - r5a.large
      - r5a.xlarge
      - r5a.2xlarge
    ConstraintDescription: must be a valid EC2 instance type.

  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: must be the name of an existing EC2 KeyPair.

  SSHLocation:
    Description: The IP address that can be used to SSH to the EC2 instances in CIDR format (e.g. 203.0.113.1/32)
    Type: String
    MinLength: 9
    MaxLength: 18
    Default: 0.0.0.0/0
    AllowedPattern: '^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$'
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
    
Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyName
      SecurityGroupIds:
        - !Ref WebServerSecurityGroup
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          # Get the latest CloudFormation package
          dnf update -y aws-cfn-bootstrap
          # Run cfn-init
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region} || error_exit 'Failed to run cfn-init'        
          # Start up the cfn-hup daemon to listen for changes to the EC2 instance metadata
          /opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'
          # Signal success or failure
          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
    Metadata:
      AWS::CloudFormation::Init:
        config:
          packages:
            dnf:
              httpd: []
              php: []
          files:
            /var/www/html/index.php:
              content: |
                <?php
                echo "<h1>Hello World!</h1>";
                echo "<p>This is an updated version of our application.</p>";
                echo "<p>Running on Amazon Linux 2023!</p>";
                ?>
              mode: '000644'
              owner: apache
              group: apache
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
                # The interval used to check for changes to the resource metadata in minutes. Default is 15
                interval=2
              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 -s ${AWS::StackId} -r WebServerInstance --region ${AWS::Region}
                runas=root
          services:
            systemd:
              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
    CreationPolicy:
      ResourceSignal:
        Timeout: PT5M

  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80 and SSH access via port 22
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SSHLocation

Outputs:
  WebsiteURL:
    Value: !Sub 'http://${WebServerInstance.PublicDnsName}'
    Description: URL of the web application
```

使用与 [第 2 步：更新应用程序](#update-stack-update-application) 中所述的相同步骤更新堆栈。

在新实例运行之后，CloudFormation 将更新堆栈中的其他资源以指向新资源。创建所有新资源并删除旧资源的过程称为 `UPDATE_CLEANUP`。此时，您将注意到堆栈中实例的实例 ID 和应用程序 URL 已随着更新而更改。**事件**表中的事件包含描述“Requested update has a change to an immutable property and hence creating a new physical resource”，以指示资源已被替代。

或者：如果您已将应用程序代码写入您想更新的 AMI 中，您可以使用同一堆栈更新机制更新 AMI 以加载您的新应用程序。

**要使用自定义应用程序代码更新 AMI**

1. 创建含有应用程序或操作系统更改的新 AMI。有关更多信息，请参阅《Amazon EC2 用户指南》**中的[创建 Amazon EBS-backed AMI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami-ebs.html)。

1. 更新您的模板以合并新 AMI ID。

1. 使用与 [第 2 步：更新应用程序](#update-stack-update-application) 中所述的相同步骤更新堆栈。

在您更新堆栈时，CloudFormation 检测到 AMI ID 已更改，然后用我们启动前一个更新所使用的方法触发堆栈更新。

## 可用性和影响注意事项
<a name="update.walkthrough.impact"></a>

不同的属性会对堆栈中的资源造成不同的影响。您可以使用 CloudFormation 更新任何属性，但是您应该在进行任何更改之前考虑以下问题：

1. 更新会如何影响资源本身？ 例如，更新警报阈值会使警报在更新期间处于非活动状态。正如我们所见，更改实例类型时需要停止并重启实例。CloudFormation 使用底层资源的更新或修改操作来对资源进行更改。要了解更改的影响，您应该查看特定资源的文档。

1. 更改可变还是不可变？ 对资源属性的某些更改，如更改 Amazon EC2 实例上的 AMI，不受基础服务的支持。如果更改可变，CloudFormation 将使用适用于基础资源的“Update”或“Modify”类型 API。对于不可变的属性更改，CloudFormation 将用更新后的属性创建新资源，然后再删除旧资源之前将此资源链接至堆栈。虽然 CloudFormation 尝试减少堆栈资源的停机时间，但替代资源是一个多步骤过程，需要时间。重新配置堆栈期间，您的应用程序不能全面运行。例如，它可能不能为请求提供服务或访问数据库。

## 相关资源
<a name="update.walkthrough.related"></a>

有关使用 CloudFormation 启动应用程序的更多信息以及集成其他配置与 Puppet 和 Opscode Chef 等部署服务的更多信息，请参阅以下白皮书：
+ [通过 CloudFormation 启动应用程序](https://s3.amazonaws.com/cloudformation-examples/BoostrappingApplicationsWithAWSCloudFormation.pdf)
+ [将 CloudFormation 与 Opscode Chef 集成](https://s3.amazonaws.com/cloudformation-examples/IntegratingAWSCloudFormationWithOpscodeChef.pdf)
+ [将 CloudFormation 与 Puppet 集成](https://s3.amazonaws.com/cloudformation-examples/IntegratingAWSCloudFormationWithPuppet.pdf)