疑難排解 EC2/內部部署問題 - AWS CodeDeploy

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

疑難排解 EC2/內部部署問題

注意

您可以藉由檢閱在部署程序期間建立的日誌檔,識別許多部署故障的原因。為了簡單起見,我們建議您使用 Amazon CloudWatch Logs 集中監控日誌檔案,而不是逐個檢視日誌檔案。如需詳細資訊,請參閱在 CodeDeploy 記 CloudWatch 錄主控台中檢視記錄

提示

如需自動執行許多與 EC2 /內部部署相關的故障排解任務的 Runbook,請參閱 AWS Systems Manager 自動化手冊參考資料TroubleshootCodeDeploy中的 AWSSupport-

CodeDeploy 插件 CommandPoller缺少憑據錯誤

如果您收到與 InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Missing credentials - please check if this instance was started with an IAM instance profile 類似的錯誤,可能是由以下其中一項造成:

  • 您要部署的執行個體沒有與其相關聯的 IAM 執行個體設定檔。

  • 您的 IAM 執行個體設定檔未設定正確的許可。

IAM 執行個體設定檔授與 CodeDeploy 代理程式通訊 CodeDeploy和從 Amazon S3 下載修訂版的權限。若為 EC2 執行個體,請參閱適用於 AWS CodeDeploy的 Identity and Access Management。如需現場部署執行個體的詳細資訊,請參閱 Working with On-Premises Instances

部署失敗訊息:「PKCS7 簽章訊息驗證失敗」

此錯誤訊息指出執行個體正在執行僅支援 SHA-1 雜湊演算法的 CodeDeploy 代理程式版本。SHA-2 雜湊演算法的 Support 已於 2015 年 11 月發行的 CodeDeploy 代理程式版本 1.0.1.854 中引入。自 2016 年 10 月 17 日起,如果安裝的 CodeDeploy 代理程式版本早於 1.0.1.854,則部署會失敗。如需詳細資訊,請參閱AWS 若要切換至 SSL 憑證的 SHA256 雜湊演算法,請注意:淘汰舊版本 1.0.1.85 的 CodeDeploy 主機代理程式和。更新 CodeDeploy 代理程式

部署或重新部署相同的檔案到同一個執行個體裡時,發生錯誤訊息「部署失敗,因為指定的檔案已存在於此位置」

當 CodeDeploy 嘗試將檔案部署到執行個體,但指定的目標位置中已存在相同名稱的檔案時,該執行個體的部署可能會失敗。您可能會收到「部署失敗,因為指定的檔案已存在於此位置:location-name」的錯誤訊息。這是因為,在每次部署期間, CodeDeploy 首先會刪除先前部署中列示在清理記錄檔中的所有檔案。如果目標安裝資料夾中有未列在此清除檔案中的檔案,則 CodeDeploy 代理程式預設會將此解譯為錯誤,且部署失敗。

注意

在 Amazon Linux、RHEL 和 Ubuntu 伺服器執行個體上,清理檔案位於/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偵測到的內容的選項 (或未指定任何部署選項來處理程式化命令中的現有內容),則可以選擇對錯誤進行疑難排解。

以下資訊僅適用於當您選擇不保留或覆寫內容。

如果您嘗試重新部署具有相同名稱和位置的檔案,則如果您使用之前使用的相同基礎部署群組識別碼指定應用程式名稱和部署群組,則重新部署的可能性較高。 CodeDeploy 使用基礎部署群組 ID 識別要在重新部署之前移除的檔案。

部署新的檔案或重新部署相同的檔案到執行個體上,其失敗的可能原因:

  • 重新部署同個修訂時,您指定不同的應用程式名稱到同一個執行個體上。重新部署失敗,因為即使部署群組名稱是相同的,但使用不同的應用程式名稱表示使用不同的基礎部署群組 ID。

  • 您刪除了應用程式的部署群組後並為其重建,接著嘗試將相同修訂重新部署至該部署群組。重新部署會失敗,因為即使部署群組名稱相同,也會 CodeDeploy 參考不同的基礎部署群組識別碼。

  • 您在中刪除了應用程式和部署群組 CodeDeploy,然後使用與刪除的名稱相同的新應用程式和部署群組建立。然後,您嘗試重新部署之前部署到部署群組的修訂到新建立且有相同名稱的部署群組裡。重新部署會失敗,因為即使應用程式和部署群組名稱相同, CodeDeploy 仍會參考您刪除之部署群組的識別碼。

  • 您部署修訂到部署群組裡,然後部署相同的修訂至同一個執行個體裡的另一個部署群組。第二個部署失敗,因為 CodeDeploy 參考了不同的基礎部署群組識別碼。

  • 您部署修訂到一個部署群組裡,然後部署另一個的修訂至同一個執行個體裡的另一個部署群組。在相同位置中,至少有一個相同名稱的檔案,在此位置中,第二部署群組會嘗試部署。第二個部署失敗,因為 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 代理程式:

  1. 在您計劃安裝 CodeDeploy 代理程式的電腦上,使用此命令啟用 LongPathsEnabled Windows 登錄機碼:

    New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
  2. 安裝代 CodeDeploy 理程式。如需詳細資訊,請參閱 安裝 CodeDeploy 代理程式

如果已安裝 CodeDeploy 代理程式:

  1. 在 CodeDeploy 代理程式電腦上,使用此命令啟用 LongPathsEnabled Windows 登錄機碼:

    New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
  2. 重新啟動 CodeDeploy 代理程式,讓登錄機碼變更生效。如果要重新啟動代理程式,請使用此命令:

    powershell.exe -Command Restart-Service -Name codedeployagent

長時間執行的程序可能導致部署失敗

對於 Amazon Linux、Ubuntu 伺服器和 RHEL 執行個體的部署,如果您有啟動長時間執行程序的部署指令碼, CodeDeploy 可能會在部署生命週期事件中花費很長時間等待,然後部署失敗。這是因為如果處理序執行的時間長於前景處理序,而在該事件中預期的背景處理序需要執行、 CodeDeploy 停止和失敗部署,即使處理序仍如預期般執行也是如此。

例如,應用程式修訂在其根目錄下包含兩個檔案:after-install.shsleep.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 檔案包含下列內容,會使程式暫停執行三分鐘 (180 秒),模擬某些長時間執行的程序:

#!/bin/bash sleep 180

當通after-install.sh話時sleep.shsleep.sh開始並執行三分鐘 (180 秒),這是兩分鐘 (120 秒) 過去 CodeDeploy 預期的時間 sleep.sh (並且,根據關係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 &

這樣做可能會讓部署保持擱置狀態,最長可達預設的 1 小時部署生命週期事件逾時期間,之後會像以前一樣在 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 生命週期事件期間失敗,但部署記錄檔不會指出失敗的原因。

此失敗通常是因為 Classic Load Balancer、應用程式負載平衡器或 Network Load Balancer 用於管理部署群組流量的 Elastic Load Balancing 中設定健康狀態檢查錯誤所致。

若要解決該問題,請檢閱和修正負載平衡器的運作狀況檢查裡任何的錯誤。

對於傳統負載平衡器,請參閱傳統負載平衡器使用者指南和 Elastic Load Balancing API 參考版本 2012-06-01 ConfigureHealthCheck中的設定 Health 狀態檢查。

對於應用程式負載平衡器,請參閱應用程式負載平衡器使用者指南中的目標群組 Health 狀態檢查

對於 Network Load Balancer,請參閱網路負載平衡器使用者指南中的目標群組的 Health 全狀況檢查。

疑難排解失敗 ApplicationStop BeforeBlockTraffic、或 AfterBlockTraffic 部署生命週期事件

在部署期間, CodeDeploy 代理程式會執行先前成功部署的 ApplicationStop BeforeBlockTraffic、和 AppSpec 檔案 AfterBlockTraffic 中指定的指令碼。(所有其他指令碼均從目前部署中的 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料夾中。

  • 在檔案中列出的位置中,deployment-group-id_last_successful_install AppSpec 檔案無效或指令碼未成功執行。

  • 此指令碼內含無法更正的錯誤,所以永遠不會順利執行。

使用主 CodeDeploy 控台來調查為什麼在任何這些事件期間部署可能會失敗。在部署的詳細資訊頁面上,選擇 View events (檢閱事件)。在執行個體的詳細資訊頁面上,在ApplicationStop、或資AfterBlockTraffic料列中 BeforeBlockTraffic,選擇 [檢視記錄檔]。或者使用 AWS CLI 來呼叫指get-deployment-instance令。

如果失敗的原因是上次成功部署中永遠不會成功執行的指令碼,請建立部署並指定應忽略 ApplicationStop BeforeBlockTraffic、和 AfterBlockTraffic 失敗。有兩種方式可以進行:

  • 使用 CodeDeploy 主控台建立部署。在 [建立部署] 頁面的 [ApplicationStop 生命週期事件失敗] 下,選擇 [如果執行個體上的這個生命週期事件失敗,則不要讓部署失敗至執行個體]。

  • 使 AWS CLI 用呼叫指create-deployment令並包含選--ignore-application-stop-failures項。

當您再次部署應用程式修訂,此部署會持續,即使這三個生命週期事件中的任何一個故障。如果新的修訂版包含這些生命週期事件的修正指令碼,則未來部署可在不套用此修正而成功執行。

疑難排解失敗的 DownloadBundle 部署生命週期事件 UnknownError:未開啟以供讀取

如果您嘗試從 Amazon S3 部署應用程式修訂版,且部署在部 DownloadBundle 署生命週期事件期間失敗,並顯示UnknownError: not opened for reading錯誤:

  • 有內部 Amazon S3 服務錯誤。請再次部署應用程式修訂。

  • EC2 執行個體上的 IAM 執行個體設定檔沒有存取 Amazon S3 中應用程式修訂版的許可。如需 Amazon S3 儲存貯體政策的相關資訊,請參閱將修訂推送 CodeDeploy 至 Amazon S3 (僅適用於 EC2 /內部部署)部署先決條

  • 您部署到的執行個體與一個 AWS 區域 (例如美國西部 (奧勒岡)) 相關聯,但包含應用程式修訂版的 Amazon S3 儲存貯體與另一個 AWS 區域 (例如美國東部 (維吉尼亞北部)) 相關聯。確保應用程式修訂版位於與執行個體相關聯的相同 AWS 區域的 Amazon S3 儲存貯體中。

在部署的事件詳細資訊頁面,於 Download bundle (下載套用) 列,選取 View logs (檢視日誌)。或者使用 AWS CLI 來呼叫指get-deployment-instance令。如果發生此錯誤,輸出中應出現錯誤碼為 UnknownError 和錯誤訊息為 not opened for reading 的錯誤。

判斷此錯誤的原因:

  1. 在至少一個執行個體上啟用有線登入,然後再部署應用程式修訂一次。

  2. 檢查有線日誌檔尋找錯誤。此問題的常見錯誤訊息包含「拒絕存取」。

  3. 檢查完日誌檔案後,我們建議您停用線路日誌記錄,以減少日誌檔案大小以及未來在執行個體上以純文字形式顯示在輸出中的敏感資訊量。

若要取得有關如何尋找配線記錄檔案以及啟用和停用電線記錄的資訊,請參閱CodeDeploy 代理程式組態參考:log_aws_wire:中的。

對所有生命週期事件略過錯誤進行故障診斷

如果跳過 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 伺服器,請執行下列動作:

      systemctl status codedeploy-agent
    • 對於 Windows,請執行下列動作:

      powershell.exe -Command Get-Service -Name CodeDeployagent

    如果未安裝或執行 CodeDeploy 代理程式,請參閱確認 CodeDeploy 代理程式正在執行

    您的執行個體可能無法使用連接埠 443 到達 CodeDeploy 或 Amazon S3 公有端點。請嘗試執行下列其中一項操作:

    • 將公有 IP 地址指派給執行個體,並使用其路由表允許網際網路存取。請確定與執行個體關聯的安全群組允許透過連接埠 443 (HTTPS) 進行對外存取。如需詳細資訊,請參閱 CodeDeploy 代理程式的通訊協定和連接埠

    • 如果執行個體是在私有子網路中佈建的,則使用 NAT 閘道,而非路由表中的網際網路閘道。如需更多詳細資訊,請參閱 NAT 閘道

  • 的服務角色 CodeDeploy 可能沒有必要的權限。如要設定 CodeDeploy 的服務角色,請參閱 步驟 2:建立服務角色 CodeDeploy

  • 如果您使用 HTTP Proxy,請確定已在代 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:為您的 Amazon EC2 執行個體建立 IAM 執行個體設定檔 Amazon EC2 使用者指南中的適用於 Amazon EC2 的 IAM 角色

視窗 PowerShell 指令碼預設無法使用 64 位元版本 PowerShell 的視窗

如果做為部署一部分執行的 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 位元視窗 PowerShell 使用如下路徑:

c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe