AWS代理帳號充值 AWS ECS Service 部署新版本卡在 Primary 狀態不切換:健康檢查失敗診斷
一、先理解:為什麼會卡在 PRIMARY
AWS ECS 的部署流程裡,PRIMARY 不是「已經完成」的意思,而是「目前被系統視為主要承載流量的 task set」。當你推出新版本時,ECS 或 CodeDeploy 會先建立新的 task set,等它通過一連串健康檢查,再把流量逐步切過去。只要健康檢查沒有穩定通過,系統就不會放心把舊版本換掉,畫面上就會像是卡在 PRIMARY,遲遲不切換。
很多人第一次遇到時,直覺會以為是部署工具壞了,或是 ECS 沒有真的在跑新版本。其實多數情況不是。真正的問題通常很單純:容器有啟動,但健康檢查打不到;服務有起來,但回應碼不對;ALB 已經註冊目標,卻因為網路或設定錯誤而一直判定 unhealthy。換句話說,部署卡住的表面現象,背後常常是應用程式沒有在「對的時間、用對的方式、回應對的檢查」。
二、先看三個地方,最快找到方向
要診斷這類問題,不要一開始就亂改參數。先把資訊收齊,通常三個地方就足夠判斷八成原因:ECS Service 事件、Target Group 健康狀態、容器應用日誌。這三個地方剛好對應「排程有沒有成功」、「流量入口有沒有成功註冊」、「程式本身有沒有活著」。
1. ECS Service 事件
AWS代理帳號充值 Service 事件是最容易被忽略、卻最有用的線索。你會看到像是健康檢查失敗、目標群組沒有健康目標、任務反覆重啟、容器無法保持穩定等訊息。這些字眼不只是提醒,它其實已經在告訴你失敗位置在哪一層。
如果事件一直重複提到 target group unhealthy,通常代表容器已經跑起來,但對外服務端點不符合預期。若事件顯示 task stopped,則要往容器啟動失敗、OOM、設定檔錯誤或權限問題去查。若連 task 都放不進去,問題可能在 CPU、Memory、執行角色或子網配置,而不是健康檢查本身。
2. Target Group 健康狀態
Target Group 是部署成敗的核心判斷點。只要新的 task 沒被判定為 healthy,流量就不會真正切過去。你要看的不只是「不健康」,而是「為什麼不健康」。常見原因包含回應逾時、狀態碼不符合、連線失敗、端口不通、TLS 設定錯誤等。
特別注意,健康檢查路徑不應該綁登入流程,也不要依賴外部資料庫才能回 200。很多系統平常對外提供功能沒問題,但 health endpoint 卻會去查 Redis、連資料庫、讀第三方服務,一旦那條依賴鏈稍微慢一點,健康檢查就直接失敗。健康檢查的目的不是驗證全系統功能,而是確認容器已經能穩定接收流量。
3. 容器應用日誌
如果 Target Group 看起來一直不通,請直接看容器日誌。很多時候答案就寫在那裡,例如啟動時讀不到環境變數、連不上資料庫、憑證錯誤、port 綁錯、migration 卡住、應用程式啟動後立刻退出。這些都會導致容器看似已啟動,實際上根本沒有在正確的 port 上提供服務。
特別是新版本上線時,若你同時改了設定檔、映像檔版本、任務定義與安全群組,日誌幾乎是唯一能幫你把問題拆開的地方。不要只看最後一行錯誤,要往前找完整啟動過程,通常第一個異常才是真正的根因。
三、最常見的九種根因
實務上,ECS 新版本卡在 PRIMARY 不切換,通常可以歸成以下幾類。只要有系統地排查,就不會在參數上瞎試。
- 健康檢查路徑錯誤:ALB 設成
/health,但應用其實回的是/status,或路由前面還有反向代理前綴。 - 回應碼不符合:檢查路徑回 301、302、401、403、500,Target Group 就會判定失敗。
- 啟動時間太長:應用需要初始化快取、載入模型、做 migration,還沒 ready 就被健康檢查打掉。
- 容器埠與目標埠不一致:task definition 裡的 containerPort、Target Group 的 port、應用實際監聽埠不一致。
- 安全群組阻擋:ALB 到 task 的 inbound 沒放行,或 task 的 egress 被封住。
- 健康檢查設定太嚴:interval 太短、timeout 太小、healthy threshold 太高,剛起來就被判失敗。
- 應用依賴外部資源:資料庫、Redis、第三方 API 慢或不通,導致健康檢查一直失敗。
- 容器本身不穩:記憶體不足、CPU 飽和、OOM kill、程式異常退出。
- 部署流程設定不合理:blue/green 的流量切換條件太保守,或 deployment config 與健康檢查未協調。
這些原因常常不是單獨出現,而是互相疊加。比如應用本來就慢,再加上健康檢查 timeout 設太短,就會讓問題看起來像是部署卡住;其實只是系統沒有給新版本足夠時間完成啟動。
四、照這個順序排查,效率最高
遇到 PRIMARY 不切換,建議按照下面順序做,先定位層級,再決定要不要調參數。這樣做的好處是,不會在錯的地方浪費時間。
- 確認任務是否真的進入 RUNNING:如果 task 根本沒跑起來,健康檢查不用看,先查排程、權限、資源不足、映像檔拉取失敗。
- 看 Target Group 的 unhealthy reason:如果顯示 timeout,就優先看網路與啟動速度;如果顯示 response code mismatch,就優先看路由與 health endpoint。
- AWS代理帳號充值 進容器內直接測試:不要只從外部看,直接在容器裡打健康檢查路徑,確認服務是否真的在監聽正確埠位。
- 比對 task definition 與實際設定:檢查 containerPort、環境變數、資源限制、entry point、command 是否和上一版一致。
- 檢查安全群組與網路路由:ALB 到 task、task 到外部服務、private subnet 的 NAT、NACL 等都可能卡住流量。
- 回看部署事件與應用日誌:很多時候第一個錯誤訊息就是根因,後面的失敗只是連鎖反應。
如果你有 ECS Exec,可以直接進容器執行健康檢查,像是:
curl -i localhost:8080/health
這一步很重要。因為外部健康檢查失敗,不一定代表服務完全掛掉;有時只是 ALB 路徑、header、host 設定不對,或是應用在容器內其實正常,但對外反向代理沒轉過去。
五、修正方式,不只是把健康檢查放寬
很多團隊一遇到部署卡住,就先把 timeout 拉長、threshold 調低、grace period 增加。這些做法不是不能用,但它們只是讓系統「晚一點失敗」,不是解決真正問題。真正穩定的做法,是把健康檢查設計成真的能反映服務就緒狀態,而不是拿來碰運氣。
第一,建立專用的 health endpoint。這個 endpoint 要簡單、快、穩,最好只檢查進程是否活著與基本依賴是否可用,不要把所有外部系統都綁進去。第二,把應用啟動流程拆清楚,讓 server 先起來,再慢慢完成耗時初始化。這樣 health check 才有機會在合理時間內通過。
第三,正確使用 health check grace period。它可以避免應用剛起來時被過早判死,但它不能掩蓋真正的故障。如果應用每次都要一分鐘以上才 ready,與其無限放寬健康檢查,不如把啟動流程優化掉。第四,確認 ALB 的 listener rule、target group、port 與路由一致,尤其是有前綴轉發、HTTPS 強制跳轉、API Gateway 代理時,更容易出錯。
第五,注意資源配額。某些新版本因為加了功能,記憶體需求突然變高,結果容器一啟動就 OOM。這時候健康檢查看到的只是「服務不健康」,但真正的根因是資源規格太小。若你只會調 health check,問題永遠不會好。
AWS代理帳號充值 六、如果是藍綠部署,還要再多看一層
藍綠部署比單純 rolling update 更依賴健康檢查。因為它不是把舊任務直接替掉,而是先讓新版本準備好,再決定何時切流量。這種模式的好處是安全,壞處是任何一個健康門檻沒過,都會讓切換停住。
如果你使用的是 CodeDeploy 搭配 ECS,還要注意 lifecycle hook、traffic shifting policy、termination wait time。當新 task set 已經建立,但一直無法完成切換時,不要只盯著 ECS 頁面,要同時看 CodeDeploy 的部署歷史。很多時候 ECS 看起來像卡住,其實是 CodeDeploy 在等待一個沒有通過的條件。
另外,如果舊版本和新版本共用同一組外部資源,新版本在預熱期間就可能把舊版本拖慢,導致雙方健康狀態一起掉。這種情況下,部署看起來像是 PRIMARY 不切換,實際上是新舊版本互相影響,讓健康檢查變成連鎖故障。
七、把經驗變成制度,之後就不會一直重演
真正成熟的團隊,不是每次都靠人工盯部署,而是把這類失敗變成可預防的制度。你可以從三件事開始:第一,為健康檢查建立一致標準,所有服務都至少有一個獨立、快速、可重複的健康端點。第二,把應用啟動時間納入發布準則,如果某個版本平均需要更久才 ready,就先調整參數或拆分啟動流程。第三,把 ECS Service 事件、Target Group 狀態與應用日誌串在一起看,讓值班的人不用翻三個畫面才能找到根因。
另外,建議把常見失敗模式寫進發布清單。像是:是否改了健康檢查路徑、是否改了監聽埠、是否加了登入保護、是否新增外部依賴、是否調高記憶體需求。這些看似瑣碎的小檢查,往往就是避免部署卡死的關鍵。
AWS ECS 的部署不難,難的是把「服務已起來」和「服務已可安全接流量」區分清楚。PRIMARY 卡住,不代表系統壞掉,而是在提醒你:新版本還沒有被證明足夠穩。只要你能沿著事件、健康檢查、日誌、網路與資源這幾條線往下查,通常都能在最短時間內找到真正原因,讓切換重新恢復正常。


