AppSpec'挂钩'部分 - Amazon CodeDeploy
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

AppSpec'挂钩'部分

AppSpec文件'hooks'部分中的内容会有所不同,具体取决于部署的计算平台。EC2/本地部署'hooks'部分包含将部署生命周期事件挂钩链接到一个或多个脚本的映射。Lambda 或 Amazon ECS 部署'hooks'部分指定了部署生命周期事件期间要运行的 Lambda 验证函数。如果某个事件的挂钩不存在,则不会对该事件执行任何操作。只有在部署过程中运行脚本或 Lambda 验证函数时,才需要此部分。

AppSpec亚马逊 ECS 部署的 “挂钩” 部分

亚马逊 ECS 部署的生命周期事件挂钩列表

AmazonLambda 挂钩是一个 Lambda 函数,在生命周期事件名称后的新行上使用字符串指定。对于每次部署,每个挂钩将执行一次。以下是生命周期事件的描述,您可以在 Amazon ECS 部署期间在这些事件中运行挂钩。

  • BeforeInstall— 用于在创建替换任务集之前运行任务。一个目标组与原始任务集相关联。如果指定了可选的测试侦听器,则它与原始任务集相关联。此时,无法执行回滚。

  • AfterInstall— 用于在创建替换任务集且其中一个目标组与之关联后运行任务。如果指定了可选的测试侦听器,则它与原始任务集相关联。在此生命周期事件时挂钩函数的运行结果可能会触发回滚。

  • AfterAllowTestTraffic— 用于在测试侦听器向替换任务集提供流量后运行任务。此时挂钩函数的运行结果可能会触发回滚。

  • BeforeAllowTraffic— 用于在第二个目标组与替换任务集关联之后但在将流量转移到替换任务集之前运行任务。在此生命周期事件时挂钩函数的运行结果可能会触发回滚。

  • AfterAllowTraffic— 用于在第二个目标组向替换任务集提供流量后运行任务。在此生命周期事件时挂钩函数的运行结果可能会触发回滚。

有关更多信息,请参阅 Amazon ECS 部署期间会发生什么教程:通过验证测试部署 Amazon ECS 服务

在 Amazon ECS 部署中运行挂钩顺序

在 Amazon ECS 部署中,事件挂钩按以下顺序运行:

注意

无法为部署中的 “开始TestTrafficAllowTraffic、“安装” 和 “结束” 事件编写脚本,这就是它们在此图中显示为灰色的原因。

“挂钩” 部分的结构

以下示例说明了 'hooks' 部分的结构。

使用 YAML:

Hooks: - BeforeInstall: "BeforeInstallHookFunctionName" - AfterInstall: "AfterInstallHookFunctionName" - AfterAllowTestTraffic: "AfterAllowTestTrafficHookFunctionName" - BeforeAllowTraffic: "BeforeAllowTrafficHookFunctionName" - AfterAllowTraffic: "AfterAllowTrafficHookFunctionName"

使用 JSON:

"Hooks": [ { "BeforeInstall": "BeforeInstallHookFunctionName" }, { "AfterInstall": "AfterInstallHookFunctionName" }, { "AfterAllowTestTraffic": "AfterAllowTestTrafficHookFunctionName" }, { "BeforeAllowTraffic": "BeforeAllowTrafficHookFunctionName" }, { "AfterAllowTraffic": "AfterAllowTrafficHookFunctionName" } ] }

Lambda “挂钩” 函数示例

使用该'hooks'部分指定CodeDeploy可以调用以验证 Amazon ECS 部署的 Lambda 函数。对于 BeforeInstallAfterInstallAfterAllowTestTrafficBeforeAllowTrafficAfterAllowTraffic 部署生命周期事件,您可以使用相同函数或不同函数。完成验证测试后,Lambda AfterAllowTraffic 函数会回调CodeDeploy并提供SucceededFailed的结果。

重要

如果 Lambda 验证函数未在一小时内通知,CodeDeploy则认为部署已失败。

在调用 Lambda 挂钩函数之前,必须使用命令将部署 ID 和生命周期事件挂钩执行 ID 通知服务器。putLifecycleEventHookExecutionStatus

以下是用 Node.js 编写的 Lambda 挂钩函数示例。

'use strict'; const aws = require('aws-sdk'); const codedeploy = new aws.CodeDeploy({apiVersion: '2014-10-06'}); exports.handler = (event, context, callback) => { //Read the DeploymentId from the event payload. var deploymentId = event.DeploymentId; //Read the LifecycleEventHookExecutionId from the event payload var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId; /* Enter validation tests here. */ // Prepare the validation test results with the deploymentId and // the lifecycleEventHookExecutionId for CodeDeploy. var params = { deploymentId: deploymentId, lifecycleEventHookExecutionId: lifecycleEventHookExecutionId, status: 'Succeeded' // status can be 'Succeeded' or 'Failed' }; // Pass CodeDeploy the prepared validation test results. codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) { if (err) { // Validation failed. callback('Validation test failed'); } else { // Validation succeeded. callback(null, 'Validation test succeeded'); } }); };

AppSpecAmazonLambda 部署的 “挂钩” 部分

AmazonLambda 部署的生命周期事件挂钩列表

AmazonLambda 挂钩是一个 Lambda 函数,在生命周期事件名称后的新行上使用字符串指定。对于每次部署,每个挂钩将执行一次。以下是AppSpec文件中可供使用的挂钩的描述。

  • BeforeAllowTraffic— 用于在流量转移到已部署的 Lambda 函数版本之前运行任务。

  • AfterAllowTraffic— 用于在所有流量转移到已部署的 Lambda 函数版本后运行任务。

在 Lambda 函数版本部署中运行挂钩顺序

在无服务器 Lambda 函数版本部署中,事件挂钩按以下顺序运行:

注意

无法为部署中的 “开始” 和 “结束” 事件编写脚本,这就是它们在此图中显示为灰色的原因。AllowTraffic

“挂钩” 部分的结构

以下示例说明了“hooks”部分的结构。

使用 YAML:

hooks: - BeforeAllowTraffic: BeforeAllowTrafficHookFunctionName - AfterAllowTraffic: AfterAllowTrafficHookFunctionName

使用 JSON:

"hooks": [{ "BeforeAllowTraffic": "BeforeAllowTrafficHookFunctionName" }, { "AfterAllowTraffic": "AfterAllowTrafficHookFunctionName" }]

Lambda “挂钩” 函数示例

使用 “挂钩” 部分指定CodeDeploy可以调用以验证 Lambda 部署的 Lambda 函数。对于 BeforeAllowTrafficAfterAllowTraffic 部署生命周期事件,您可以使用相同函数或不同函数。完成验证测试后,Lambda 验证函数会回调CodeDeploy并提供SucceededFailed的结果。

重要

如果 Lambda 验证函数未在一小时内通知,CodeDeploy则认为部署已失败。

在调用 Lambda 挂钩函数之前,必须使用命令将部署 ID 和生命周期事件挂钩执行 ID 通知服务器。putLifecycleEventHookExecutionStatus

以下是用 Node.js 编写的 Lambda 挂钩函数示例。

'use strict'; const aws = require('aws-sdk'); const codedeploy = new aws.CodeDeploy({apiVersion: '2014-10-06'}); exports.handler = (event, context, callback) => { //Read the DeploymentId from the event payload. var deploymentId = event.DeploymentId; //Read the LifecycleEventHookExecutionId from the event payload var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId; /* Enter validation tests here. */ // Prepare the validation test results with the deploymentId and // the lifecycleEventHookExecutionId for CodeDeploy. var params = { deploymentId: deploymentId, lifecycleEventHookExecutionId: lifecycleEventHookExecutionId, status: 'Succeeded' // status can be 'Succeeded' or 'Failed' }; // Pass CodeDeploy the prepared validation test results. codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) { if (err) { // Validation failed. callback('Validation test failed'); } else { // Validation succeeded. callback(null, 'Validation test succeeded'); } }); };

AppSpecEC2/本地部署的 “挂钩” 部分

生命周期事件挂钩列表

每次部署到一个实例,EC2/本地部署挂接都会执行一次。在一个挂钩中,可以指定运行一个或多个脚本。生命周期事件的每个挂钩在单独的行中使用字符串指定。以下是AppSpec文件中可供使用的挂钩的描述。

有关哪些生命周期事件挂钩对哪些部署和回滚类型有效的信息,请参阅生命周期事件挂钩可用性

  • ApplicationStop— 此部署生命周期事件甚至在下载应用程序修订版之前发生。您可以为此事件指定脚本,以便从容地停止应用程序或在部署准备过程中删除当前已安装的软件包。用于此部署生命周期事件AppSpec的文件和脚本来自先前成功部署的应用程序修订版。

    注意

    在部署到实例之前,AppSpec文件在实例上不存在。因此,ApplicationStop 挂钩在您首次部署到实例时不会运行。您可以在第二次部署到实例时使用 ApplicationStop 挂钩。

    为确定上次成功部署的应用程序修订的位置,CodeDeploy 代理将查看 deployment-group-id_last_successful_install 文件中列出的位置。此文件位于:

    /opt/codedeploy-agent/deployment-root/deployment-instructions亚马逊 Linux、Ubuntu 服务器和 RHEL 亚马逊 EC2 实例上的文件夹。

    C:\ProgramData\Amazon\CodeDeploy\deployment-instructionsWindows 服务器亚马逊 EC2 实例上的文件夹。

    要对在 ApplicationStop 部署生命周期事件期间失败的部署进行故障排除,请参阅 对失败ApplicationStop或AfterBlockTraffic部署生命周期事件进行故障排除 BeforeBlockTraffic

  • DownloadBundle— 在此部署生命周期事件中,CodeDeploy代理将应用程序修订文件复制到临时位置:

    /opt/codedeploy-agent/deployment-root/deployment-group-id/deployment-id/deployment-archive亚马逊 Linux、Ubuntu 服务器和 RHEL 亚马逊 EC2 实例上的文件夹。

    C:\ProgramData\Amazon\CodeDeploy\deployment-group-id\deployment-id\deployment-archiveWindows 服务器亚马逊 EC2 实例上的文件夹。

    此事件是为 CodeDeploy 代理预留的,不能用于运行脚本。

    要对在 DownloadBundle 部署生命周期事件期间失败的部署进行故障排除,请参阅 对DownloadBundle部署生命周期失败事件进行故障排除UnknownError:未打开以供读取

  • BeforeInstall— 您可以将此部署生命周期事件用于预安装任务,例如解密文件和创建当前版本的备份。

  • Install— 在此部署生命周期事件中,CodeDeploy代理将修订文件从临时位置复制到最终目标文件夹。此事件是为 CodeDeploy 代理预留的,不能用于运行脚本。

  • AfterInstall— 您可以将此部署生命周期事件用于配置应用程序或更改文件权限等任务。

  • ApplicationStart— 您通常使用此部署生命周期事件来重启在此期间停止的服务ApplicationStop

  • ValidateService— 这是最后一次部署生命周期事件。它用于验证部署已成功完成。

  • BeforeBlockTraffic— 在从负载均衡器注销实例之前,您可以使用此部署生命周期事件在实例上运行任务。

    要对在 BeforeBlockTraffic 部署生命周期事件期间失败的部署进行故障排除,请参阅 对失败ApplicationStop或AfterBlockTraffic部署生命周期事件进行故障排除 BeforeBlockTraffic

  • BlockTraffic— 在此部署生命周期事件中,互联网流量被阻止访问当前提供流量服务的实例。此事件是为 CodeDeploy 代理预留的,不能用于运行脚本。

  • AfterBlockTraffic— 在实例从负载均衡器注销后,您可以使用此部署生命周期事件在实例上运行任务。

    要对在 AfterBlockTraffic 部署生命周期事件期间失败的部署进行故障排除,请参阅 对失败ApplicationStop或AfterBlockTraffic部署生命周期事件进行故障排除 BeforeBlockTraffic

  • BeforeAllowTraffic— 在实例向负载均衡器注册之前,您可以使用此部署生命周期事件在实例上运行任务。

  • AllowTraffic— 在此部署生命周期事件中,允许互联网流量在部署后访问实例。此事件是为 CodeDeploy 代理预留的,不能用于运行脚本。

  • AfterAllowTraffic— 在实例向负载均衡器注册后,您可以使用此部署生命周期事件在实例上运行任务。

生命周期事件挂钩可用性

下表列出了适用于每个部署和回滚方案的生命周期事件挂钩。

生命周期事件名称 就地部署¹ 蓝/绿部署:原始实例 蓝/绿部署:替换实例 蓝/绿部署回滚:原始实例 蓝/绿部署回滚:替换实例
ApplicationStop
DownloadBundle²
BeforeInstall
安装 ²
AfterInstall
ApplicationStart
ValidateService
BeforeBlockTraffic
BlockTraffic²
AfterBlockTraffic
BeforeAllowTraffic
AllowTraffic²
AfterAllowTraffic

¹也适用于就地部署的回滚。

² 预留用于CodeDeploy运营。不能用于运行脚本。

在部署中运行挂钩顺序

就地部署

在就地部署中 (包括就地部署的回滚),事件挂钩按以下顺序运行:

注意

对于就地部署,只有当您在部署组中指定了 Elastic Load Balancing 中的传统负载均衡器、应用程序负载均衡器或网络负载均衡器时,与阻止和允许流量相关的六个挂钩才适用。

注意

无法为部署中的 “开始”、“安装” 和 “结束” 事件编写脚本,这就是它们在此图中显示为灰色的原因。DownloadBundle但是,您可以编辑AppSpec文件的'files'部分以指定在安装事件期间安装的内容。

蓝/绿部署

在蓝/绿部署中,事件挂钩按以下顺序运行:

注意

无法为部署中的 “开始BlockTrafficAllowTraffic、“安装” 和 “结束” 事件编写脚本,这就是它们在此图中显示为灰色的原因。DownloadBundle但是,您可以编辑文件的 “文件” 部分,AppSpec以指定在安装事件期间安装的内容。

“挂钩” 部分的结构

'hooks' 部分具有以下结构:

hooks: deployment-lifecycle-event-name: - location: script-location timeout: timeout-in-seconds runas: user-name

可以在 hook 条目中的部署生命周期事件名称后包括以下元素:

location

必需。修订的脚本文件包的位置。您hooks在本节中指定的脚本位置相对于应用程序修订包的根目录。有关更多信息,请参阅计划 CodeDeploy 的修订

timeout

可选。在脚本被视为失败之前允许其执行的秒数。默认值为 3600 秒(1 小时)。

注意

3600 秒(1 小时)是允许每个部署生命周期事件脚本执行的最长时间。如果脚本超过此限制,则部署将停止,并且部署到实例将失败。确保在 timeout 中为每个部署生命周期事件的所有脚本指定的总秒数不超过此限制。

runas

可选。运行脚本时要模拟的用户。默认情况下,这是在实例上运行的CodeDeploy代理。CodeDeploy不存储密码,因此如果 run as 用户需要密码,则无法模拟用户。此元素仅适用于亚马逊 Linux 和 Ubuntu 服务器实例。

挂钩的环境变量可用性

在每个部署生命周期事件期间,挂钩脚本可以访问以下环境变量:

APPLICATION_NAME

CodeDeploy 中属于当前部署的应用程序的名称(例如,WordPress_App)。

DEPLOYMENT_ID

CodeDeploy 已分配给当前部署的 ID(例如,d-AB1CDEF23)。

DEPLOYMENT_GROUP_NAME

CodeDeploy 中属于当前部署的部署组的名称(例如,WordPress_DepGroup)。

DEPLOYMENT_GROUP_ID

CodeDeploy 中属于当前部署的部署组的 ID(例如,b1a2189b-dd90-4ef5-8f40-4c1c5EXAMPLE)。

LIFECYCLE_EVENT

当前部署生命周期事件的名称(例如 AfterInstall)。

这些是每个部署生命周期事件的本地环境变量。

根据部署包的来源,还有其他环境变量可用于挂接脚本:

亚马逊 S3 的捆绑包

  • BUNDLE_B

    从中下载部署包的 Amazon S3 存储桶的名称(例如,my-s3-bucket)。

  • 捆绑密钥

    在 Amazon S3 存储桶中下载的包的对象密钥(例如,WordPress_App.zip)。

  • 捆绑版

    包的对象版本(例如3sL4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo)。只有在 Amazon S3 存储桶启用了对象版本控制时,才会设置此变量。

  • BUNDLE_ETAG

    捆绑包的对象 etag(例如b10a8db164e0754105b7a99be72e3fe5-4)。

捆绑来自 GitHub

  • 捆绑提交

    由 Git 生成的捆绑包的 SHA256 提交哈希(例如d2a84f4b8b650937ec8f73cd8be2c74add5a911ba64df27458ed8229da804a26)。

如果 DEPLOYMENT_GROUP_NAME 的值等于 Staging,则以下脚本会将 Apache HTTP 服务器上的侦听端口更改为 9090 而非 80。必须在 BeforeInstall 部署生命周期事件期间调用此脚本:

if [ "$DEPLOYMENT_GROUP_NAME" == "Staging" ] then sed -i -e 's/Listen 80/Listen 9090/g' /etc/httpd/conf/httpd.conf fi

如果 DEPLOYMENT_GROUP_NAME 环境变量的值等于 Staging,则以下脚本示例会将其错误日志中记录的消息的详细级别从警告更改为调试。必须在 BeforeInstall 部署生命周期事件期间调用此脚本:

if [ "$DEPLOYMENT_GROUP_NAME" == "Staging" ] then sed -i -e 's/LogLevel warn/LogLevel debug/g' /etc/httpd/conf/httpd.conf fi

以下脚本示例将指定网页中的文本替换为显示这些环境变量值的文本。必须在 AfterInstall 部署生命周期事件期间调用此脚本:

#!/usr/bin/python import os strToSearch="<h2>This application was deployed using CodeDeploy.</h2>" strToReplace="<h2>This page for "+os.environ['APPLICATION_NAME']+" application and "+os.environ['DEPLOYMENT_GROUP_NAME']+" deployment group with "+os.environ['DEPLOYMENT_GROUP_ID']+" deployment group ID was generated by a "+os.environ['LIFECYCLE_EVENT']+" script during "+os.environ['DEPLOYMENT_ID']+" deployment.</h2>" fp=open("/var/www/html/index.html","r") buffer=fp.read() fp.close() fp=open("/var/www/html/index.html","w") fp.write(buffer.replace(strToSearch,strToReplace)) fp.close()

挂钩示例

以下是 hooks 条目的示例,该条目为 AfterInstall 生命周期事件指定两个挂钩:

hooks: AfterInstall: - location: Scripts/RunResourceTests.sh timeout: 180 - location: Scripts/PostDeploy.sh timeout: 180

Scripts/RunResourceTests.sh 脚本在部署过程的 AfterInstall 阶段运行。如果该脚本的运行时间超过 180 秒(3 分钟),则部署将失败。

您在“hooks”部分中指定的脚本的位置是应用程序修订包根目录的相对路径。在上述示例中,名为 RunResourceTests.sh 的文件位于名为 Scripts 的目录中。该 Scripts 目录位于包的根级别。有关更多信息,请参阅计划 CodeDeploy 的修订