

# CloudFormation 的工作原理
<a name="cloudformation-overview"></a>

本主题说明了 CloudFormation 的工作原理，并介绍了在使用此服务时需要了解的关键概念。

**Topics**
+ [重要概念](#cfn-whatis-concepts)
+ [CloudFormation 的工作原理](#cfn-whatis-howdoesitwork)
+ [CloudFormation 入门方式](#ways-to-get-started)

## 重要概念
<a name="cfn-whatis-concepts"></a>

在使用 CloudFormation 时，您将使用*模板*和*堆栈*。您创建模板来描述 AWS 资源及其属性。当您创建堆栈时，CloudFormation 会配置模板中描述的资源。

**Topics**
+ [模板](#cfn-concepts-templates)
+ [堆栈](#cfn-concepts-stacks)
+ [更改集](#cfn-concepts-change-sets)

### 模板
<a name="cfn-concepts-templates"></a>

CloudFormation 模板是一个 JSON 或 YAML 格式的文本文件。您可使用任何扩展名（如 `.yaml`、`.json`、`.template` 或 `.txt`）保存这些文件。CloudFormation 使用这些模板作为构建 AWS 资源的蓝图。例如，在模板中，您可描述 Amazon EC2 实例，如实例类型、AMI ID、块储存设备映射和其 Amazon EC2 密钥对名称。当您创建堆栈时，还可以指定 CloudFormation 用来创建模板中描述的任何项的模板。

例如，如果您使用以下模板创建堆栈，则 CloudFormation 将使用 `ami-0ff8a91507f77f867` AMI ID、`t2.micro` 实例类型、`testkey` 密钥对名称和 Amazon EBS 卷来配置实例。

#### YAML
<a name="t2-micro-example.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: A sample template
Resources:
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0ff8a91507f77f867
      InstanceType: t2.micro
      KeyName: testkey
      BlockDeviceMappings:
        - DeviceName: /dev/sdm
          Ebs:
            VolumeType: io1
            Iops: 200
            DeleteOnTermination: false
            VolumeSize: 20
```

#### JSON
<a name="t2-micro-example.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "A sample template",
    "Resources": {
        "MyEC2Instance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "ImageId": "ami-0ff8a91507f77f867",
                "InstanceType": "t2.micro",
                "KeyName": "testkey",
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sdm",
                        "Ebs": {
                            "VolumeType": "io1",
                            "Iops": 200,
                            "DeleteOnTermination": false,
                            "VolumeSize": 20
                        }
                    }
                ]
            }
        }
    }
}
```

您还可以在单个模板中指定多种资源并将这些资源配置为结合使用。例如，您可以修改上一个模板来包含一个弹性 IP 地址（EIP）并将其与 Amazon EC2 实例相关联，如以下示例所示：

#### YAML
<a name="multiple-resources-single-template.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: A sample template
Resources:
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0ff8a91507f77f867
      InstanceType: t2.micro
      KeyName: testkey
      BlockDeviceMappings:
        - DeviceName: /dev/sdm
          Ebs:
            VolumeType: io1
            Iops: 200
            DeleteOnTermination: false
            VolumeSize: 20
  MyEIP:
    Type: AWS::EC2::EIP
    Properties:
      InstanceId: !Ref MyEC2Instance
```

#### JSON
<a name="multiple-resources-single-template.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "A sample template",
    "Resources": {
        "MyEC2Instance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "ImageId": "ami-0ff8a91507f77f867",
                "InstanceType": "t2.micro",
                "KeyName": "testkey",
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sdm",
                        "Ebs": {
                            "VolumeType": "io1",
                            "Iops": 200,
                            "DeleteOnTermination": false,
                            "VolumeSize": 20
                        }
                    }
                ]
            }
        },
        "MyEIP": {
            "Type": "AWS::EC2::EIP",
            "Properties": {
                "InstanceId": {
                    "Ref": "MyEC2Instance"
                }
            }
        }
    }
}
```

之前的模板以 Amazon EC2 实例为中心；但 CloudFormation 模板还具有其他功能，可利用这些功能来构建复杂的资源集并在许多环境中重新使用这些模板。例如，您可添加输入参数，其值是在创建 CloudFormation 堆栈时指定的。换句话说，您可在创建堆栈而不是创建模板时指定一个值 (如实例类型)，以便在不同的情况下更轻松地重新使用模板。

### 堆栈
<a name="cfn-concepts-stacks"></a>

在您使用 CloudFormation 时，可将相关资源作为一个称为堆栈的单元进行管理。您可通过创建、更新和删除堆栈来创建、更新和删除一组资源。堆栈中的所有资源均由堆栈的 CloudFormation 模板定义。假设您创建了一个模板，它包括自动扩缩组、Elastic Load Balancing 负载均衡器和 Amazon Relational Database Service (Amazon RDS) 数据库实例。要创建这些资源，您可通过提交已创建的模板来创建堆栈，CloudFormation 将会为您配置所有这些资源。

### 更改集
<a name="cfn-concepts-change-sets"></a>

如果您需要更改堆栈中运行的资源，则可更新堆栈。在更改资源之前，您可以生成一个更改集，这是建议进行的更改的摘要。利用更改集，您可以在实施更改之前，了解更改可能会对运行的资源 (特别是关键资源) 造成的影响。

例如，如果您更改 Amazon RDS 数据库实例的名称，则 CloudFormation 将创建新数据库并删除旧数据库。除非您已经对旧数据库中的数据进行备份，否则您将丢失该数据。如果您生成了更改集，则将了解更改会导致数据库被替换，而您可以先做出相应的计划，然后再更新堆栈。

## CloudFormation 的工作原理
<a name="cfn-whatis-howdoesitwork"></a>

使用 CloudFormation 创建堆栈时，CloudFormation 会向 AWS 发出基础服务调用以预置和配置模板中描述的资源。您需要有创建这些资源的权限。例如，要使用 CloudFormation 创建 EC2 实例，您需要具有创建实例的权限。您可以使用 [AWS Identity and Access Management](https://docs.aws.amazon.com/IAM/latest/UserGuide/)（IAM）来管理这些权限。

CloudFormation 进行的调用全部由您的模板声明。例如，假设您有一个描述带 `t2.micro` 实例类型的 EC2 实例的模板。当您使用该模板创建堆栈时，CloudFormation 将调用 Amazon EC2 创建实例 API 并将该实例类型指定为 `t2.micro`。以下示意图归纳了用于创建堆栈的 CloudFormation 工作流程。

![\[保存在本地或存储桶中的已创建或现有模板，用于创建堆栈。\]](http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/images/create-stack-diagram.png)


**创建堆栈**

1. 使用文本编辑器创建 JSON 或 YAML 格式的 CloudFormation 模板。CloudFormation 模板描述了您所需的资源及其设置。使用 [基础架构编辑器](infrastructure-composer-for-cloudformation.md) 可视化显示和验证模板。这有助您确保模板结构正确，没有语法错误。有关更多信息，请参阅 [使用 CloudFormation 模板](template-guide.md)。

1. 您可将模板保存在本地或 Amazon S3 存储桶中。

1. 通过指定模板文件的位置（例如，本地计算机上的路径或 Amazon S3 URL）来创建 CloudFormation 堆栈。如果模板包含参数，则可在创建堆栈时指定输入值。利用参数，您可以将值传入模板，以便能在创建堆栈时自定义资源。
**注意**  
如果您指定本地存储的模板文件，CloudFormation 会将其上传到您 AWS 账户中的 S3 桶。CloudFormation 为您上传模板文件的每个区域创建一个桶。具有您 AWS 账户中 Amazon Simple Storage Service（Amazon S3）权限的任何人均可访问桶。如果 CloudFormation 创建的存储桶已存在，则将模板添加到该存储桶。  
您可通过手动将模板上传到 Amazon S3 来使用您自己的存储桶并管理其权限。之后，当您创建或更新堆栈时，请指定模板文件的 Amazon S3 URL。

所有资源创建完毕后，CloudFormation 会报告已创建您的堆栈。然后，您可以开始使用堆栈中的资源。如果堆栈创建失败，则 CloudFormation 会通过删除已创建的资源来回滚您的更改。

### 使用更改集更新堆栈
<a name="updating-stack-with-change-sets"></a>

在需要更新堆栈的资源时，您可以修改堆栈的模板。您不需要创建新堆栈和删除旧堆栈。要更新堆栈，请提交修改的原始堆栈模板版本和/或不同的输入参数值以创建一个更改集。CloudFormation 将修改的模板与原始模板进行比较并生成一个更改集。更改集列出了建议的更改。在审核更改后，您可以启动更改集以更新堆栈，也可以创建新的更改集。以下示意图概述了用于更新堆栈的工作流程。

![\[在执行更改集以更新堆栈之前，使用更改集来查看修改后的值的模板。\]](http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/images/update-stack-diagram.png)


**使用更改集更新堆栈**

1. 您可以使用[基础架构编辑器](infrastructure-composer-for-cloudformation.md)或文本编辑器来修改 CloudFormation 堆栈模板。有关更多信息，请参阅 [更新堆栈模板](using-cfn-updating-stacks-get-template.md)。

   更新模板时，应注意更新可能会导致中断。根据您所更新的资源和属性，更新可能会中断或者甚至替换现有资源。有关更多信息，请参阅 [理解堆栈资源的更新行为](using-cfn-updating-stacks-update-behaviors.md)。

1. 您可在本地或在 S3 存储桶中保存 CloudFormation 模板。

1. 通过指定要更新的堆栈和修改后模板的位置 (例如本地计算机上的路径或 Amazon S3 URL) 来创建更改集。有关创建更改集的更多信息，请参阅[使用更改集更新 CloudFormation 堆栈](using-cfn-updating-stacks-changesets.md)。
**注意**  
如果您指定存储在本地计算机上的模板，则 CloudFormation 自动将模板上传到 AWS 账户 中的 S3 桶。

1. 查看更改集以检查 CloudFormation 是否将执行预期更改。例如，检查 CloudFormation 是否将替换任何关键堆栈资源。您可以创建所需数量的更改集，直到您包含所需的更改。
**重要**  
更改集并不指示您的堆栈更新是否将成功。例如，更改集不会检查是否将超出账户[配额](cloudformation-limits.md)、是否在更新不支持更新的资源或者是否[权限](control-access-with-iam.md)不足而无法修改资源，这些都可能导致堆栈更新失败。

1. 启动要应用于堆栈的更改集。CloudFormation 仅更新您修改的资源以更新堆栈，并发出已成功更新堆栈的信号。如果堆栈更新失败，则 CloudFormation 将回滚更改以将堆栈还原到上一个已知工作状态。

## CloudFormation 入门方式
<a name="ways-to-get-started"></a>

要使用控制台创建 hello world CloudFormation 堆栈，请参阅[创建第一个堆栈](gettingstarted.walkthrough.md)。

如需指导学习，请尝试 [CloudFormation 入门](https://catalog.us-east-1.prod.workshops.aws/workshops/df7f72cf-4f10-4664-acb6-b30dc8d4bcf0/en-US)讲习会，其提供模板开发的实践经验。