本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
EC2/本地部署问题排查
主题
- CodeDeploy代理无法在 Windows 2016 上启动
- CodeDeploy 插件 CommandPoller缺少凭据错误
- 部署失败,显示消息“PKCS7 签名的消息验证失败”
- 将相同的文件部署或重新部署到相同的实例位置失败,出现错误“The deployment failed because a specified file already exists at this location”
- 长文件路径会导致 “没有这样的文件或目录” 错误
- 长时间运行的进程可能会导致部署失败
- 在部署日志中未报告错误的情况下对失败的 AllowTraffic 生命周期事件进行故障排除
- 对失败 ApplicationStop或 AfterBlockTraffic 部署生命周期事件进行故障排除 BeforeBlockTraffic
- 使用 UnknownError:未打开以供阅读,对失败的 DownloadBundle 部署生命周期事件进行故障排除
- 排查所有生命周期事件跳过错误
- 默认情况下,Windows PowerShell 脚本无法使用 64 位版本 PowerShell 的 Windows
通过查看部署过程中创建的日志文件可以确定很多部署失败的原因。为简单起见,我们建议使用 Amazon Log CloudWatch s 集中监控日志文件,而不是逐个实例查看它们。有关信息,请参阅在 CodeDeploy 日志控制台中查看 CloudWatch 日志
CodeDeploy代理无法在 Windows 2016 上启动
在 Windows 2016 上运行 CodeDeploy 代理安装程序文件 (CodeDeploy-agent.msi
) 时,.msi 文件无法启动,您会在中看到以下错误C:\Windows\TEMP\CodeDeploy-agent.msi_installer.log
:
Error 1920 Service 'CodeDeploy Host Agent Service' (CodeDeployagent) failed to start. Verify
that you have sufficient privileges to start system services.
出现此错误是因为 Windows Defender 防病毒软件阻止了CodeDeploy-agent.msi
文件运行。
要解决此问题,您必须在运行代理安装程序之前添加 Windows Defender 排除项。
添加 Windows 防御器排除项
-
使用以下 Powershell 语句添加排除项。确保以管理员身份运行它们。
Write-Host ("Adding Windows Defender exclude for CodeDeploy...") Add-MpPreference -ExclusionPath ("C:\ProgramData\Amazon\CodeDeploy","$env:windir\Temp")
-
在代理安装之前、作为自定义 AMI 的一部分或使用 Systems Manager 添加排除项。如果您将代理作为用户数据的一部分进行安装,请在代理安装脚本之前一个步骤添加排除项。
有关更多信息,请参阅安装适用于 Windows 服务器的 CodeDeploy 代理使用Systems Manager 运行命令运行命令和启动时在 Windows 实例上运行命令。
CodeDeploy 插件 CommandPoller缺少凭据错误
如果您收到类似于 InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Missing credentials - please
check if this instance was started with an IAM instance profile
的错误,可能是由于下列原因之一导致:
-
您要部署到的实例没有与之关联的 IAM 实例配置文件。
-
您的 IAM 实例配置文件未配置正确的权限。
IAM 实例配置文件授予 CodeDeploy 代理与 Amazon S3 通信 CodeDeploy和从 Amazon S3 下载修订版的权限。对于 EC2 实例,请参阅 适用于 Amazon CodeDeploy 的 Identity and Access Management。对于本地实例,请参阅Working with On-Premises Instances。
部署失败,显示消息“PKCS7 签名的消息验证失败”
此错误消息表示该实例正在运行的 CodeDeploy 代理版本仅支持 SHA-1 哈希算法。2015 年 11 月发布的 CodeDeploy 代理版本 1.0.1.854 中引入了对 SHA-2 哈希算法的Support。自 2016 年 10 月 17 日起,如果安装了低于 1.0.1.854 的 CodeDeploy 代理版本,则部署将失败。有关更多信息,请参阅 SSL 证书切换Amazon到 SHA256 哈希算法
将相同的文件部署或重新部署到相同的实例位置失败,出现错误“The deployment failed because a specified file already exists at this location”
当 CodeDeploy 尝试将文件部署到实例,但指定目标位置已存在同名文件时,部署到该实例可能会失败。您可能会收到错误消息“The deployment failed because a specified file already exists at this location: location-name
.” 这是因为,在每个部署期间, CodeDeploy 会先删除上一部署中的所有文件 (清除日志文件中列出了这些文件)。如果目标安装文件夹中有未在此清理文件中列出的文件,则默认情况下, CodeDeploy 代理会将其解释为错误并使部署失败。
在亚马逊 Linux、RHEL 和 Ubuntu Server 实例上,清理文件位于/opt/codedeploy-agent/deployment-root/deployment-instructions/
。在 Windows 服务器实例上,位置是C:\ProgramData\Amazon\CodeDeploy\deployment-instructions\
。
避免此错误的最简单方式是,指定默认行为之外的选项以使部署失败。对于每个部署,您可以选择是使部署失败、覆盖清除文件中未列出的文件,还是保留实例上已有的文件。
覆盖选项在以下情况下很有用:您在上一个部署后手动将文件放置在实例上,然后将一个同名文件添加到下一个应用程序修订。
您可以为您在要成为下一部署的一部分的实例上放置的文件选择保留选项,而无需将这些文件添加到应用程序修订包。如果您的应用程序文件已经在生产环境中并且您想首次使用进行 CodeDeploy 部署,则保留选项也很有用。有关更多信息,请参阅 创建 EC2/本地计算平台部署(控制台) 和 对现有内容的回滚行为。
排查 The deployment failed because a specified file already exists at
this location
部署错误
如果您选择不指定选项来覆盖或保留 CodeDeploy 在目标部署位置检测到的内容(或者,如果您不指定任何部署选项来处理编程命令中的现有内容),则可以选择纠正错误。
以下信息仅在您选择不保留或覆盖内容的情况下适用。
如果您尝试重新部署具有相同名称和位置的文件,则使用之前使用的相同基础部署组 ID 指定应用程序名称和部署组,则重新部署更有可能成功。 CodeDeploy 在重新部署之前,使用底层部署组 ID 来识别要删除的文件。
将新文件部署到实例上的相同位置或将相同的文件重新部署到实例上的相同位置可能会因以下原因而失败:
-
您为将相同修订重新部署到同一实例的操作指定不同的应用程序名称。重新部署失败,因为即使部署组名称相同,使用其他应用程序名称意味着将使用不同的基础部署组 ID。
-
您已删除并重新创建应用程序的部署组,然后尝试将同一修订重新部署到该部署组。重新部署失败,因为即使部署组名称相同,也会 CodeDeploy 引用不同的底层部署组 ID。
-
您在中删除了应用程序和部署组 CodeDeploy,然后创建了一个与您删除的应用程序和部署组同名的新应用程序和部署组。之后,您尝试重新将已部署到上一个部署组的修订部署到同名的新部署组。重新部署失败,因为即使应用程序和部署组名称相同, CodeDeploy 仍引用您删除的部署组的 ID。
-
您已将一个修订部署到一个部署组,然后将对另一个部署组的同一修订部署到相同的实例。第二次部署将失败,因为 CodeDeploy 引用不同的基础部署组 ID。
-
您已将一个修订部署到一个部署组,然后将对另一个部署组的其他修订部署到相同的实例。至少有一个文件具有相同名称且位于第二个部署组尝试部署的相同位置。第二次部署失败,因为在第二次部署开始之前 CodeDeploy 未删除现有文件。两个部署都将引用不同的部署组 ID。
-
您在中部署了修订版 CodeDeploy,但至少有一个文件名称相同且位于相同位置。部署失败,因为默认情况下,部署开始之前 CodeDeploy 不会删除现有文件。
要处理这些情况,请执行下列操作之一:
-
从文件之前部署到的位置和实例中删除文件,然后尝试重新部署。
-
在您的修订 AppSpec 文件中,在 ApplicationStop 或 BeforeInstall部署生命周期事件中,指定自定义脚本以删除与您的版本即将安装的文件相匹配的任何位置的文件。
-
将文件部署或重新部署到不属于之前的部署的位置或实例。
-
在删除应用程序或部署组之前,部署一个 AppSpec 包含指定不向实例复制任何文件的文件的修订版。对于该部署,指定使用您即将删除的基础应用程序和部署组的 ID 的应用程序名称和部署组名称。(您可以使用get-deployment-group命令检索部署组 ID。) CodeDeploy使用底层部署组 ID 和 AppSpec 文件删除其在先前成功部署中安装的所有文件。
长文件路径会导致 “没有这样的文件或目录” 错误
对于向 Windows 实例的部署,如果您的 appspec.yml 文件部分的文件路径大于 260 个字符,则可能会看到部署失败并出现类似于以下内容的错误:
No such file or directory @ dir_s_mkdir -
C:\
your-long-file-path
之所以出现此错误,是因为默认情况下,Windows 不允许文件路径大于 260 个字符,如微软文档
对于 CodeDeploy 代理版本 1.4.0 或更高版本,您可以通过两种方式启用长文件路径,具体取决于代理安装过程:
如果尚未安装 CodeDeploy 代理:
-
在计划安装 CodeDeploy 代理的计算机上,使用以下命令启用
LongPathsEnabled
Windows 注册表项:New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
-
安装代 CodeDeploy 理。有关更多信息,请参阅安装代 CodeDeploy 理:
如果已经安装了 CodeDeploy 代理:
-
在 CodeDeploy 代理计算机上,使用以下命令启用
LongPathsEnabled
Windows 注册表项:New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
-
重新启动 CodeDeploy 代理以使注册表项更改生效。要重新启动代理,请使用以下命令:
powershell.exe -Command Restart-Service -Name codedeployagent
长时间运行的进程可能会导致部署失败
对于部署到 Amazon Linux、Ubuntu Server 和 RHEL 实例,如果您的部署脚本启动了长时间运行的进程,则 CodeDeploy 可能会花很长时间等待部署生命周期事件,然后部署失败。这是因为,在该进程运行的时间比该事件中的前台和后台进程预期的所需时间长的情况下, CodeDeploy 将停止部署并使其失败,即使该进程仍按预期运行也是如此。
例如,应用程序修订在其根目录下包含两个文件:after-install.sh
和 sleep.sh
。其 AppSpec 文件包含以下说明:
version: 0.0 os: linux files: - source: ./sleep.sh destination: /tmp hooks: AfterInstall: - location: after-install.sh timeout: 60
该after-install.sh
文件在 AfterInstall 应用程序生命周期事件期间运行。以下是其内容:
#!/bin/bash /tmp/sleep.sh
sleep.sh
文件包含以下内容,它会使程序执行暂停 3 分钟(180 秒),并模拟某个长时间运行的进程:
#!/bin/bash sleep 180
当after-install.sh
呼叫sleep.sh
sleep.sh
开始并运行三分钟(180 秒)时,也就是说,比 CodeDeploy 预期的时间(以及从关系上讲)停止运行的时间过了两分钟sleep.sh
(120 秒after-install.sh
)。超时一分钟(60 秒)后,即使sleep.sh
继续按预期运行,在 AfterInstall 应用程序生命周期事件发生时也会 CodeDeploy 停止部署并失败。将显示以下错误:
Script at specified location: after-install.sh failed to complete in 60
seconds
.
仅在 &
中添加 after-install.sh
符号无法在后台运行 sleep.sh
。
#!/bin/bash # Do not do this. /tmp/sleep.sh &
这样做可以在默认的一小时部署生命周期事件超时期内使部署处于待处理状态,之后会像以前一样在 AfterInstall 应用程序生命周期事件中 CodeDeploy 停止部署并失败。
在中after-install.sh
,按sleep.sh
如下方式调用 CodeDeploy ,这样可以在进程开始运行后继续:
#!/bin/bash /tmp/sleep.sh > /dev/null 2> /dev/null < /dev/null &
在之前的调用中,sleep.sh
是要在后台开始运行的进程的名称,该进程将 stdout、stderr 和 stdin 重定向到 /dev/null
。
在部署日志中未报告错误的情况下对失败的 AllowTraffic 生命周期事件进行故障排除
在某些情况下,蓝/绿部署在 AllowTraffic 生命周期事件期间失败,但部署日志并未指出失败的原因。
此失败通常是由于在用于管理部署组流量的传统负载均衡器、Application Load Balancer 或Network Load Balancer 的 Elastic Load Balancing 中错误配置的运行状况检查所致。
要解决这一问题,请检查并更正负载均衡器的运行状况检查配置中的错误。
对于经典负载均衡器,请参阅经典负载均衡器的用户指南和Elastic Load Bal ancing API 参考版本 2012-06-0 1 ConfigureHealthCheck中的配置运行H ealth 检查。
对于应用程序负载均衡器,请参阅应用程序负载均衡器用户指南中的目标组运行H eal th 检查。
对于Network Load Bal ancer,请参阅网络负载均衡器用户指南中的目标组运行Health 检查。
对失败 ApplicationStop或 AfterBlockTraffic 部署生命周期事件进行故障排除 BeforeBlockTraffic
在部署期间, CodeDeploy 代理运行前一次成功部署 AppSpec 文件 AfterBlockTraffic 中为 ApplicationStop BeforeBlockTraffic、和指定的脚本。(所有其他脚本均在当前部署中的 AppSpec 文件中运行。) 如果这些脚本之一包含错误且未成功运行,则部署可能失败。
这些失败的可能原因包括:
-
CodeDeploy 代理在正确的位置找到了
文件,但deployment-group-id
_last_successful_install
文件中列出的位置不存在。deployment-group-id
_last_successful_install在 Amazon Linux、Ubuntu 服务器和 RHEL 实例中,此文件必须存在于
/opt/codedeploy-agent/deployment-root/deployment-instructions
。在 Windows 服务器实例上,此文件必须存储在
C:\ProgramData\Amazon\CodeDeploy\deployment-instructions
文件夹中。 -
在
文件中列出的位置中,要么 AppSpec 文件无效,要么脚本未成功运行。deployment-group-id
_last_successful_install -
这一脚本中包含无法更正的错误,所以永远无法成功运行。
使用 CodeDeploy 控制台调查部署在任何此类事件期间可能失败的原因。在部署的详细信息页上,选择查看事件。在实例的详细信息页面的ApplicationStopBeforeBlockTraffic、或AfterBlockTraffic行中,选择查看日志。或者使用 Amazon CLI 调用 get-deployment-instance 命令。
如果失败的原因是上次成功部署的脚本从未成功运行,请创建部署并指定忽略 ApplicationStop BeforeBlockTraffic、和 AfterBlockTraffic 失败。有两种方式可执行此操作:
-
使用控制 CodeDeploy 台创建部署。在创建部署页面的ApplicationStop 生命周期事件失败下,选择在实例上的此生命周期事件失败时不要使部署到该实例失败。
-
使用 Amazon CLI 调用 create-deployment 命令并包含
--ignore-application-stop-failures
选项。
当您重新部署应用程序修订时,部署将继续,即使这三个生命周期事件中的任一事件失败也是如此。如果新的修订已包含针对这些生命周期事件的修复脚本,未来的部署无需应用此修复就能成功。
使用 UnknownError:未打开以供阅读,对失败的 DownloadBundle 部署生命周期事件进行故障排除
如果您尝试从 Amazon S3 部署应用程序修订版,但在部署生命周期事件期间 DownloadBundle 部署失败并出现UnknownError: not opened
for reading
错误:
-
Amazon S3 服务出现内部错误。请重新部署应用程序修订。
-
您的 EC2 实例上的 IAM 实例配置文件无权访问 Amazon S3 中的应用程序版本。有关 Amazon S3 存储桶策略的信息,请参阅将每个Amazon S3 每个 CodeDeploy 每个每个每个每个每个每个每个每个每个每个每个每个每个每个每个每个每个每个每个每个和部署先决条件。
-
您部署到的实例与一个Amazon区域(例如,美国西部(俄勒冈))相关联,但包含应用程序修订的 Amazon S3 存储桶与另一个Amazon区域(例如,美国东部(弗吉尼亚北部))相关联。确保应用程序修订位于与实例相同Amazon区域关联的 Amazon S3 存储桶中。
在部署的事件详细信息页的下载服务包行中,选择查看日志。或者使用 Amazon CLI 调用 get-deployment-instance 命令。如果出现此错误,则输出中应有一个错误代码为 UnknownError
且错误消息为 not opened for reading
的错误。
要确定此错误的原因,请执行以下步骤:
-
对至少一个实例启用线路日志记录,然后重新部署应用程序修订。
-
查看线路日志记录文件以找到错误。此问题的常见错误消息包括短语“access denied”。
-
在查看日志文件后,建议您禁用线路日志记录以减小日志文件的大小并减少将来可能会在实例上的输出中以纯文本格式出现的敏感信息量。
有关如何查找线路日志文件以及启用和禁用线路记录的信息,请参阅:log_aws_wire:
CodeDeploy 代理配置参考中的。
排查所有生命周期事件跳过错误
如果跳过 EC2 或本地部署的所有生命周期事件,您可能会收到类似于的错误The overall deployment failed because too many
individual instances failed deployment, too few healthy instances are available for
deployment, or some instances in your deployment group are experiencing problems. (Error
code: HEALTH_CONSTRAINTS)
。这里介绍了一些可能的原因和解决方案:
-
CodeDeploy 代理可能未在实例上安装或运行。要确定 CodeDeploy 代理是否正在运行,请执行以下操作:
-
对于 Amazon Linux RHEL 或 Ubuntu 服务器,请运行以下命令:
sudo service codedeploy-agent status
-
对于 Windows,请运行以下命令:
powershell.exe -Command Get-Service -Name CodeDeployagent
如果 CodeDeploy 代理未安装或未运行,请参见确认 CodeDeploy 代理是否正在运行。
您的实例可能无法使用端口 443 访问 CodeDeploy 或 Amazon S3 公共终端节点。请尝试以下任一操作:
-
将公有 IP 地址分配到实例并使用其路由表来允许 Internet 访问。确保与实例关联的安全组允许端口 443 (HTTPS) 上的出站访问。有关更多信息,请参阅 CodeDeploy 代理的通信协议和端口:
-
如果是在私有子网中预配置了实例,请在路由表中使用 NAT 网关而不是 Internet 网关。有关更多信息,请参阅 NAT 网关。
-
-
的服务角色 CodeDeploy 可能没有所需的权限。要配置 CodeDeploy 服务角色,请参阅步骤 2:为创建服务角色 CodeDeploy。
-
如果您使用 HTTP 代理,请确保在 CodeDeploy 代理配置文件的
:proxy_uri:
设置中指定了该代理。有关更多信息,请参阅CodeDeploy 代理配置参考: -
您部署实例的日期和时间签名可能与部署请求的日期和时间签名不匹配。在 CodeDeploy 代理日志文件
Cannot reach InstanceService: Aws::CodeDeployCommand::Errors::InvalidSignatureException - Signature expired
中查找与之类似的错误。如果您看到此错误,请按照排除 “InvalidSignatureException — 签名已过期:[时间] 现在早于 [时间]” 部署错误中的步骤进行操作。有关更多信息,请参阅查看 CodeDeploy EC2/本地部署部署的日志数据: -
CodeDeploy 代理可能会因为实例的内存或硬盘空间不足而停止运行。尝试通过更新 CodeDeploy 代理配置中的
max_revisions
设置来减少实例上的存档部署数量。如果您对 EC2 实例执行此操作但问题仍然存在,请考虑使用更大的实例。例如,如果您的实例类型为t2.small
,请尝试使用t2.medium
。有关更多信息,请参阅 CodeDeploy 代理安装的文件 CodeDeploy 代理配置参考、和实例类型。 -
您要部署到的实例可能没有附加 IAM 实例配置文件,或者它可能附加了没有所需权限的 IAM 实例配置文件。
-
如果未将 IAM 实例配置文件附加到您的实例,请创建一个具有所需权限的配置文件,然后将其附加。
-
如果 IAM 实例配置文件已经附加到您的实例,请确保它具有所需的权限。
在您确认附加的实例配置文件配置有所需权限之后,重新启动实例。有关更多信息,请参阅步骤 4:为 AmazAmazon EC2 实例创建 IAmazon EC2 实例配置文件 Amazon EC2 用户指南中的适用于 Amazon EC2 的 IAmazon EC2 的 IAM 角色。
-
默认情况下,Windows PowerShell 脚本无法使用 64 位版本 PowerShell 的 Windows
如果作为部署一部分运行的 Windows PowerShell 脚本依赖于 64 位功能(例如,因为它消耗的内存超过 32 位应用程序允许的内存或调用仅在 64 位版本中提供的库),则该脚本可能会崩溃或无法按预期运行。这是因为默认情况下, CodeDeploy 使用 32 位版本的 Windows PowerShell 来运行作为应用程序修订版一部分的 Windows PowerShell 脚本。
将如下所示的代码添加到必须在 64 位版本的 Windows 上运行的任何脚本的开头 PowerShell:
# Are you running in 32-bit mode? # (\SysWOW64\ = 32-bit mode) if ($PSHOME -like "*SysWOW64*") { Write-Warning "Restarting this script under 64-bit Windows PowerShell." # Restart this script under 64-bit Windows PowerShell. # (\SysNative\ redirects to \System32\ for 64-bit mode) & (Join-Path ($PSHOME -replace "SysWOW64", "SysNative") powershell.exe) -File ` (Join-Path $PSScriptRoot $MyInvocation.MyCommand) @args # Exit 32-bit script. Exit $LastExitCode } # Was restart successful? Write-Warning "Hello from $PSHOME" Write-Warning " (\SysWOW64\ = 32-bit mode, \System32\ = 64-bit mode)" Write-Warning "Original arguments (if any): $args" # Your 64-bit script code follows here... # ...
尽管此代码中的文件路径信息可能看起来违反直觉,但 32 位 Windows PowerShell 使用的路径如下:
c:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
64 位 Windows PowerShell 使用如下路径:
c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe