AppSpec “挂钩” 部分 - AWS CodeDeploy

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

AppSpec “挂钩” 部分

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

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

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

网络 ACL 和安全组都允许 (因此可到达您的实例) 的发起 ping 的AWSLambda 钩子是一个 Lambda 函数,在生命周期事件名称后面的换行中使用字符串指定。对于每次部署,每个挂钩将执行一次。以下是在 Amazon ECS 部署期间可以运行挂钩的生命周期事件的描述。

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

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

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

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

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

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

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

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

注意

这些区域有:启动,安装,TestTraffic,AllowTraffic,以及End部署中的事件无法编写脚本,这就是为什么它们在此图中显示为灰色的原因。

“钩子” 部分的结构

以下示例说明了 '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'部分用于指定一个 Lambda 函数 CodeDeploy 可以调用来验证 Amazon ECS 部署。对于 BeforeInstallAfterInstallAfterAllowTestTrafficBeforeAllowTrafficAfterAllowTraffic 部署生命周期事件,您可以使用相同函数或不同函数。验证测试完成后,LambdaAfterAllowTraffic函数回调 CodeDeploy 并得出以下结果Succeeded要么Failed.

重要

如果出现以下情况,则认为部署已失败 CodeDeploy Lambda 验证函数不会在一小时内通知。

在调用 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'); } }); };

AppSpec 一个 “挂钩” 部分AWSLambda 部署

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

网络 ACL 和安全组都允许 (因此可到达您的实例) 的发起 ping 的AWSLambda 钩子是一个 Lambda 函数,在生命周期事件名称后面的换行中使用字符串指定。对于每次部署,每个挂钩将执行一次。以下是可用于您的钩子的描述 AppSpec file.

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

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

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

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

注意

这些区域有:启动,AllowTraffic,以及End部署中的事件无法编写脚本,这就是为什么它们在此图中显示为灰色的原因。

“钩子” 部分的结构

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

使用 YAML:

hooks: - BeforeAllowTraffic: BeforeAllowTrafficHookFunctionName - AfterAllowTraffic: AfterAllowTrafficHookFunctionName

使用 JSON:

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

示例 Lambda “挂钩” 函数

使用 “钩子” 部分指定一个 Lambda 函数 CodeDeploy 可以调用来验证 Lambda 部署。对于 BeforeAllowTrafficAfterAllowTraffic 部署生命周期事件,您可以使用相同函数或不同函数。验证测试完成后,Lambda 验证函数会回调 CodeDeploy 并得出以下结果Succeeded要么Failed.

重要

如果出现以下情况,则认为部署已失败 CodeDeploy Lambda 验证函数不会在一小时内通知。

在调用 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'); } }); };

AppSpec EC2/本地部署的 “挂钩” 部分

生命周期事件挂钩列表

每次向实例部署一次 EC2/本地部署挂钩。在一个挂钩中,可以指定运行一个或多个脚本。生命周期事件的每个挂钩在单独的行中使用字符串指定。以下是可用于您的钩子的描述 AppSpec file.

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

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

    注意

    网络 ACL 和安全组都允许 (因此可到达您的实例) 的发起 ping 的 AppSpec 在您部署到实例之前,文件不存在于该实例上。因此,ApplicationStop 挂钩在您首次部署到实例时不会运行。您可以在第二次部署到实例时使用 ApplicationStop 挂钩。

    要确定上次成功部署的应用程序版本的位置, CodeDeploy 代理查找列在中的位置deployment-group-id_last_successful_install file. 此文件位于:

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

    C:\ProgramData\Amazon\CodeDeploy\deployment-instructionsWindows ServAmazon EC2 文件夹。

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

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

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

    C:\ProgramData\Amazon\CodeDeploy\deployment-group-id\deployment-id\deployment-archiveWindows ServAmazon EC2 文件夹。

    此活动是为 CodeDeploy 代理,不能用于运行脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

生命周期事件钩子可用性

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

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

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

x 为预留 CodeDeploy 操作 不能用于运行脚本。

在部署中运行挂接顺序

就地部署

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

注意

对于就地部署,仅当您在部署组中指定 Elastic Load Balancing 中的Classic Load Balancer、Application Load Balancer 或Network Load Balancer 时,与阻塞和允许流量相关的六个挂钩才适用。

注意

这些区域有:启动,DownloadBundle,安装,以及End部署中的事件无法编写脚本,这就是为什么它们在此图中显示为灰色的原因。但是,您可以编辑'files'部分 AppSpec 文件来指定在运行期间安装了什么安装事件

蓝/绿部署

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

注意

这些区域有:启动,DownloadBundle,安装,BlockTraffic,AllowTraffic,以及End部署中的事件无法编写脚本,这就是为什么它们在此图中显示为灰色的原因。但是,您可以编辑 “文件” 部分 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 不存储密码,因此如果出现以下情况,则无法模拟用户runas用户需要密码。此元素仅适用于亚马逊 Linux 和 Ubuntu 服务器实例。

挂接的环境变量可用性

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

APPLICATION_NAME

中的应用程序的名称 CodeDeploy 这是当前部署的一部分(例如,WordPress_App)。

DEPLOYMENT_ID

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

DEPLOYMENT_GROUP_NAME

中的部署组的名称 CodeDeploy 这是当前部署的一部分(例如,WordPress_DepGroup)。

DEPLOYMENT_GROUP_ID

中部署组的 ID CodeDeploy 这是当前部署的一部分(例如,b1a2189b-dd90-4ef5-8f40-4c1c5EXAMPLE)。

LIFECYCLE_EVENT

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

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

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

Amazon S3

  • BINDLE_BUCKET

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

  • BUNDLE_KEY

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

  • BUNDLE_VERSION

    包的对象版本(例如3sL4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo)。仅在 Amazon S3 存储桶具有以下条件时设置此变量对象版本控制已启用。

  • BUNDLE_ETAG

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

捆绑来 GitHub

  • BUNDLE_COMMIT

    由 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 的修订