

# 演练：为测试和生产堆栈构建管道
<a name="continuous-delivery-codepipeline-basic-walkthrough"></a>

设想一个发布流程：您提交一个 CloudFormation 模板，然后 CloudFormation 使用该模板自动构建测试堆栈。在您审查测试堆栈后，可预览您的更改将如何修改生产堆栈，然后选择是否实施更改。要完成此工作流程，您可使用 CloudFormation 构建测试堆栈、删除测试堆栈、创建更改集，然后执行更改集。但是，在每个操作中，您都需要手动与 CloudFormation 进行交互。在此演练中，我们将构建一个 CodePipeline 管道来实现上述多个操作的自动化，从而帮助您使用 CloudFormation 堆栈实现持续交付工作流。

## 先决条件
<a name="w2aac21c11b5"></a>

该演练假定您使用过 CodePipeline 和 CloudFormation，并且知道管道以及 AWS CloudFormation 模板和堆栈的工作方式。有关 CodePipeline 的更多信息，请参阅[《AWS CodePipeline 用户指南》](https://docs.aws.amazon.com/codepipeline/latest/userguide/)。您创建管道的同一 AWS 区域中还需要有一个 Amazon S3 存储桶。

**重要**  
示例 WordPress 模板将创建需要 Internet 连接的 EC2 实例。检查您是否有允许 Internet 流量的默认 VPC 和子网。

## 演练概述
<a name="w2aac21c11b7"></a>

此演练在堆栈中为示例 WordPress 站点构建一个管道。此管道分为三个阶段。每个阶段均必须包含至少一个操作，此操作是管道将在您的构件 (您的输入) 上执行的任务。阶段在管道中组织操作。CodePipeline 必须完成阶段中的所有操作，然后阶段才会处理新构件，例如，您提交新输入以重新运行管道。

在此演练结束时，您将获得执行以下工作流程的管道：

1. 管道的第一个阶段从存储库中检索源构件 (CloudFormation 模板及其配置文件)。

   您将准备一个包含示例 WordPress 模板的构件并将该构件上传到 S3 存储桶。

1. 在第二个阶段，管道将创建测试堆栈，然后等待您审批。

   在您审查测试堆栈后，可选择继续使用原来的管道或创建并提交另一个构件以进行更改。如果您批准，该阶段将删除测试堆栈，然后管道将继续下一阶段。

1. 在第三个阶段，管道将针对生产堆栈创建更改集，然后等待您审批。

   在初始运行中，您将没有生产堆栈。更改集显示 CloudFormation 将创建的所有资源。如果您批准，该阶段将执行更改集并构建您的生产堆栈。

**注意**  
CloudFormation 是一项免费服务。但是，将按各种资源当前的费率向您收取您在堆栈中包含的 AWS 资源 (如 EC2 实例) 的费用。有关 AWS 定价的详细信息，请参阅 [http://aws.amazon.com](https://aws.amazon.com/) 上每种产品的详细信息页。

## 步骤 1：编辑构件并将构件上传到 S3 存储桶
<a name="w2aac21c11b9"></a>

在构建管道之前，您必须设置源存储库和文件。CodePipeline 将这些源文件复制到管道的[构件存储](https://docs.aws.amazon.com/codepipeline/latest/userguide/concepts.html#concepts-artifacts)中，然后使用它们在管道中执行操作，例如，创建 CloudFormation 堆栈。

在将 Amazon Simple Storage Service (Amazon S3) 作为源存储库时，CodePipeline 要求您压缩源文件，然后再将它们上传到 S3 存储桶中。压缩的文件是可包含 CloudFormation 模板和/或模板配置文件的 CodePipeline 构件。我们提供了一个包含一个示例 WordPress 模板和两个模板配置文件的构件。两个配置文件指定 WordPress 模板的参数值。CodePipeline 在创建 WordPress 堆栈时使用这些值。一个文件包含测试堆栈的参数值，另一个文件包含生产堆栈的参数值。您将需要编辑配置文件来指定您拥有的现有 EC2 密钥对名称。有关构件的更多信息，请参阅[CloudFormation 构件](continuous-delivery-codepipeline-cfn-artifacts.md)。

在构建构件后，将构件上传到 S3 存储桶。

**编辑和上传项目**

1. 下载并打开示例构件：[https://s3.amazonaws.com/cloudformation-examples/user-guide/continuous-deployment/wordpress-single-instance.zip](https://s3.amazonaws.com/cloudformation-examples/user-guide/continuous-deployment/wordpress-single-instance.zip)。

   此构件包含三个文件：
   + 示例 WordPress 模板：`wordpress-single-instance.yaml`
   + 测试堆栈的模板配置文件：`test-stack-configuration.json`
   + 生产堆栈的模板配置文件：`prod-stack-configuration.json`

1. 提取所有文件，然后使用任意文本编辑器修改模板配置文件。

   打开配置文件以查看这些文件是否包含映射到 WordPress 模板参数的键值对。配置文件指定您的管道在创建测试堆栈和生产堆栈时使用的参数值。

   编辑 `test-stack-configuration.json` 文件以为测试堆栈指定参数值并为生产堆栈指定 `prod-stack-configuration.json` 文件。
   + 将 `DBPassword` 和 `DBRootPassword` 密钥的值更改为您可用于登录 WordPress 数据库的密码。如 WordPress 模板中所定义，参数值必须仅包含字母数字字符。
   + 将 `KeyName` 密钥的值更改为您将在其中创建管道的区域中的现有 EC2 密钥对名称。

1. 将修改的配置文件添加到原始构件 (`.zip`) 文件，并替换重复文件。

   您现在已拥有可上传到 S3 存储桶的自定义构件。

1. [将构件上传到您拥有的 S3 存储桶。](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html)

   记下文件的位置。您将在构建管道时指定此文件的位置。

   有关构件和 S3 存储桶的备注：
   + 使用位于您将在其中创建管道的同一 AWS 区域中的桶。
   + CodePipeline 要求存储桶[已启用版本控制](https://docs.aws.amazon.com/AmazonS3/latest/userguide/versioning-workflows.html)。
   + 您还可将不要求您在上传文件之前压缩文件的服务 (如 GitHub 或 CodeCommit) 用于源存储库。
   + 构件可包含密码等敏感信息。限制访问以便仅允许的用户可查看文件。当您这样做时，确保 CodePipeline 仍可访问文件。例如，如果您将构件上传到 S3 存储桶，可使用 [S3 存储桶策略或用户策略](https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-management.html)来限制访问。

您现已具有一个构件，CodePipeline 可将此构件拉入您的管道中。在下一步中，您将指定构件的位置并构建 WordPress 管道。

## 步骤 2：创建管道堆栈
<a name="w2aac21c11c11"></a>

为了创建 WordPress 管道，您将使用示例 CloudFormation 模板。除了构建管道以外，该模板还为 CodePipeline 和 CloudFormation 设置 AWS Identity and Access Management（IAM）服务角色，为 CodePipeline 构件存储设置 S3 存储桶，以及设置管道将通知（如有关审核的通知）发送到的 Amazon Simple Notification Service（Amazon SNS）主题。示例模板使您能够在单一 CloudFormation 堆栈中轻松预置和配置这些资源。

有关管道配置的更多详细信息，请参阅[管道的用途](#codepipeline-basic-walkthrough-template-details)。

**重要**  
示例 WordPress 模板将创建需要 Internet 连接的 EC2 实例。检查您的默认 VPC 和子网是否允许到 Internet 的流量。

**创建管道堆栈**

1. 从 [https://s3.amazonaws.com/cloudformation-examples/user-guide/continuous-deployment/basic-pipeline.yml](https://s3.amazonaws.com/cloudformation-examples/user-guide/continuous-deployment/basic-pipeline.yml) 下载示例模板。将该模板保存到您的计算机上。

1. 通过以下网址打开 CloudFormation 控制台：[https://console.aws.amazon.com/cloudformation/](https://console.aws.amazon.com/cloudformation/)。

1. 选择一个支持 CodePipeline 和 CloudFormation 的 AWS 区域。

   有关更多信息，请参阅 *AWS 一般参考* 中的 [CodePipeline 端点和限额](https://docs.aws.amazon.com/general/latest/gr/codepipeline.html)和 [CloudFormation 端点和限额](https://docs.aws.amazon.com/general/latest/gr/cfn.html)。

1. 选择**创建堆栈**。

1. 在 **Specify template (指定模板)** 下，选择 **Upload a template file (上传模板文件)**，然后选择您刚下载的模板 `basic-pipeline.yml`。

1. 选择**下一步**。

1. 对于 **Stack name**，键入 `sample-WordPress-pipeline`。

1. 在 **Parameters** 部分中，指定下列参数值，然后选择 **Next**。设置堆栈参数时，如果您保留 WordPress 模板及其配置文件的相同名称，则可使用默认值。否则，请指定您使用的文件名。  
**PipelineName**  
管道的名称，如 `WordPress-test-pipeline`。  
**S3Bucket**  
您将构件 (`.zip` 文件) 保存到的 S3 存储桶的名称。  
**SourceS3Key**  
构件的文件名。如果您已将构件保存到文件夹中，则可将其作为文件名的一部分包含，如 `folder/subfolder/wordpress-single-instance.zip`。  
**电子邮件**  
CodePipeline 将管道通知发送到的电子邮件地址，如 `myemail@example.com`。

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

1. 确保堆栈名称和模板 URL 正确，然后选择 **Create stack (创建堆栈)**。

1. 要确认您知道 CloudFormation 可能会创建 IAM 资源，请选中该复选框。

AWS CloudFormation 可能需要几分钟的时间以创建堆栈。要监控进度，可查看堆栈事件。有关更多信息，请参阅 [监控堆栈进度](monitor-stack-progress.md)。

在创建您的堆栈后，CodePipeline 将启动您的新管道。要查看其状态，请参阅 [CodePipeline 控制台](https://console.aws.amazon.com/codepipeline/)。从管道列表中，选择 **WordPress-test-pipeline**。

### 管道的用途
<a name="codepipeline-basic-walkthrough-template-details"></a>

此部分使用示例 WordPress 管道模板中的代码段介绍管道的三个阶段。

#### 第 1 阶段：源
<a name="w2aac21c11c11c15b5"></a>

管道的第 1 阶段是您指定源代码位置的源阶段。每当您将修订推送到此位置时，CodePipeline 都将重新运行您的管道。

源代码位于 S3 桶中，并由其文件名标识。您在创建管道堆栈时已将这些值指定为输入参数值。为了允许在后续阶段使用源构件，代码段将指定 `OutputArtifacts` 属性以及名称为 `TemplateSource`。要在后面的阶段中使用此构件，可将 `TemplateSource` 指定为输入构件。

```
- Name: S3Source
  Actions:
    - Name: TemplateSource
      ActionTypeId:
        Category: Source
        Owner: AWS
        Provider: S3
        Version: '1'
      Configuration:
        S3Bucket: !Ref 'S3Bucket'
        S3ObjectKey: !Ref 'SourceS3Key'
      OutputArtifacts:
        - Name: TemplateSource
```

#### 第 2 阶段：TestStage
<a name="w2aac21c11c11c15b7"></a>

在 `TestStage` 阶段，管道将创建测试堆栈，等待审批，然后删除测试堆栈。

对于 `CreateStack` 操作，管道将使用测试配置文件和 WordPress 模板创建测试堆栈。这两个文件都包含在通过源阶段引入的 `TemplateSource` 输入构件中。代码段将使用 `REPLACE_ON_FAILURE` 操作模式。如果堆栈创建失败，管道将替换堆栈，这样一来，您无需清除堆栈或对堆栈进行故障排除，即可重新运行管道。操作模式对于快速迭代测试堆栈很有用。对于 `RoleArn` 属性，该值是在模板中的其他位置声明的 AWS CloudFormation 服务角色。

`ApproveTestStack` 操作将暂停管道并向您在创建管道堆栈时指定的电子邮件地址发送通知。在管道暂停时，您可检查 WordPress 测试堆栈及其资源。可以使用 CodePipeline [批准或拒绝](https://docs.aws.amazon.com/codepipeline/latest/userguide/approvals-approve-or-reject.html)该操作。`CustomData` 属性包含对您正审批的操作的描述，它是由管道添加到通知电子邮件的。

在批准该操作后，CodePipeline 将移到 `DeleteTestStack` 操作并删除测试 WordPress 堆栈及其资源。

```
- Name: TestStage
  Actions:
    - Name: CreateStack
      ActionTypeId:
        Category: Deploy
        Owner: AWS
        Provider: CloudFormation
        Version: '1'
      InputArtifacts:
        - Name: TemplateSource
      Configuration:
        ActionMode: REPLACE_ON_FAILURE
        RoleArn: !GetAtt [CFNRole, Arn]
        StackName: !Ref TestStackName
        TemplateConfiguration: !Sub "TemplateSource::${TestStackConfig}"
        TemplatePath: !Sub "TemplateSource::${TemplateFileName}"
      RunOrder: '1'
    - Name: ApproveTestStack
      ActionTypeId:
        Category: Approval
        Owner: AWS
        Provider: Manual
        Version: '1'
      Configuration:
        NotificationArn: !Ref CodePipelineSNSTopic
        CustomData: !Sub 'Do you want to create a change set against the production stack and delete the ${TestStackName} stack?'
      RunOrder: '2'
    - Name: DeleteTestStack
      ActionTypeId:
        Category: Deploy
        Owner: AWS
        Provider: CloudFormation
        Version: '1'
      Configuration:
        ActionMode: DELETE_ONLY
        RoleArn: !GetAtt [CFNRole, Arn]
        StackName: !Ref TestStackName
      RunOrder: '3'
```

#### 第 3 阶段：ProdStage
<a name="w2aac21c11c11c15b9"></a>

管道的 `ProdStage` 阶段将针对现有生产堆栈创建更改集，等待审批，然后执行更改集。

更改集在实施 AWS CloudFormation 将对生产堆栈进行的所有修改之前提供这些修改的预览。在您首次运行管道时，您将没有正在运行的生产堆栈。更改集显示 AWS CloudFormation 在创建测试堆栈时执行的操作。要创建更改集，`CreateChangeSet` 操作将使用 WordPress 示例模板和 `TemplateSource` 输入构件中的生产模板配置。

与上一阶段类似，`ApproveChangeSet` 操作将暂停管道并发送电子邮件通知。在管道暂停后，您可查看更改集以检查针对生产 WordPress 堆栈的所有建议的修改。可以使用 CodePipeline [批准或拒绝](https://docs.aws.amazon.com/codepipeline/latest/userguide/approvals-approve-or-reject.html)该操作以相应地继续运行或停止管道。

在您批准该操作后，`ExecuteChangeSet` 操作执行更改集，以便 AWS CloudFormation 执行更改集中描述的所有操作。在初始运行中，AWS CloudFormation 将创建 WordPress 生产堆栈。在后续运行中，AWS CloudFormation 将更新堆栈。

```
- Name: ProdStage
  Actions:
    - Name: CreateChangeSet
      ActionTypeId:
        Category: Deploy
        Owner: AWS
        Provider: CloudFormation
        Version: '1'
      InputArtifacts:
        - Name: TemplateSource
      Configuration:
        ActionMode: CHANGE_SET_REPLACE
        RoleArn: !GetAtt [CFNRole, Arn]
        StackName: !Ref ProdStackName
        ChangeSetName: !Ref ChangeSetName
        TemplateConfiguration: !Sub "TemplateSource::${ProdStackConfig}"
        TemplatePath: !Sub "TemplateSource::${TemplateFileName}"
      RunOrder: '1'
    - Name: ApproveChangeSet
      ActionTypeId:
        Category: Approval
        Owner: AWS
        Provider: Manual
        Version: '1'
      Configuration:
        NotificationArn: !Ref CodePipelineSNSTopic
        CustomData: !Sub 'A new change set was created for the ${ProdStackName} stack. Do you want to implement the changes?'
      RunOrder: '2'
    - Name: ExecuteChangeSet
      ActionTypeId:
        Category: Deploy
        Owner: AWS
        Provider: CloudFormation
        Version: '1'
      Configuration:
        ActionMode: CHANGE_SET_EXECUTE
        ChangeSetName: !Ref ChangeSetName
        RoleArn: !GetAtt [CFNRole, Arn]
        StackName: !Ref ProdStackName
      RunOrder: '3'
```

## 步骤 3：查看 WordPress 堆栈
<a name="w2aac21c11c13"></a>

由于 CodePipeline 在整个管道中运行，因此，它使用 CloudFormation 创建测试和生产堆栈。要查看这些堆栈的状态及其输出，可使用 CloudFormation 控制台。

**查看堆栈**

1. 通过以下网址打开 CloudFormation 控制台：[https://console.aws.amazon.com/cloudformation/](https://console.aws.amazon.com/cloudformation/)。

1. 根据您的管道是处于测试阶段还是生产阶段，选择 `Test-MyWordPressSite` 或 `Prod-MyWordPressSite` 堆栈。

1. 要查看堆栈状态，可查看堆栈[事件](cfn-console-view-stack-data-resources.md)。

如果堆栈处于故障状态，可查看状态描述以找出堆栈错误。修复错误，然后重新运行管道。如果堆栈处于 `CREATE_COMPLETE` 状态，请查看其输出以获取您的 WordPress 站点的 URL。

您已成功使用 CodePipeline 为示例 WordPress 站点构建持续交付工作流程。如果您将更改提交到 S3 存储桶，CodePipeline 将自动检测新版本，然后重新运行您的管道。利用此工作流程，可以在更改生产站点之前更轻松地提交和测试更改。

## 步骤 4：清理资源
<a name="w2aac21c11c15"></a>

要确保不因任何不必要的服务而产生费用，请删除您的资源。

**重要**  
在删除管道堆栈前，删除测试和生产 WordPress 堆栈。管道堆栈包含删除 WordPress 堆栈所需的服务角色。如果您已先删除管道堆栈，则可关联另一个服务角色 Amazon 资源名称（ARN） 与 WordPress 堆栈，然后删除它们。

**删除构件存储中的对象**

1. 通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 选择 CodePipeline 用作管道构件存储的 S3 存储桶。

   此存储桶的名称遵循以下格式：`stackname-artifactstorebucket-id`。如果您已按照此演练操作，此存储桶的名称可能看上去与以下示例类似：`sample-WordPress-pipeline-artifactstorebucket-12345abcd12345`。

1. 删除构件存储 S3 存储桶中的所有对象。

   当您在下一步中删除管道堆栈时，此存储桶必须为空。否则，CloudFormation 将无法删除此存储桶。

**删除堆栈**

1. 从 CloudFormation 控制台中，选择要删除的堆栈。

   如果管道创建的 WordPress 堆栈仍在运行，请先选择它们。默认情况下，堆栈名称为 `Test-MyWordPressSite` 和 `Prod-MyWordPressSite`。

   如果您已删除 WordPress 堆栈，请选择 `sample-WordPress-pipeline` 堆栈。

1. 选择 **Actions**)（操作），然后选择 **Delete Stack**（删除堆栈）。

1. 在确认消息中，选择 **Yes, Delete**。

CloudFormation 将删除堆栈的所有堆栈资源，如 EC2 实例、通知主题、服务角色和管道。

现在您已了解如何使用 CodePipeline 构建基本 CloudFormation 工作流程，您可以将示例模板和构件作为起点以构建自己的工作流程。

## 另请参阅
<a name="w2aac21c11c17"></a>

下列相关资源可帮助您处理这些参数。
+ 有关 CodePipeline 中 CloudFormation 操作参数的更多信息， 请参阅*《AWS CodePipeline 用户指南》*中的 [CloudFormation 部署操作配置引用](https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CloudFormation.html)。
+ 有关操作提供方的示例模板值，例如 `Owner` 字段或 `configuration` 字段的值，请参阅*《AWS CodePipeline 用户指南》*中的[操作结构参考](https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference.html)。
+ 要下载 YAML 或 JSON 格式的示例管道堆栈模板，请参阅*《AWS CodePipeline 用户指南》*中[教程：使用 CloudFormation 创建管道](https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-cloudformation.html)。