Azure國際帳號服務 AKS容器部署失敗解決方法
前言:失敗不止一次,原因也不止一種
把容器部署到 AKS,本質上是把「一個應用」在正確的時機、正確的身份、正確的網路與正確的資源上啟動。部署失敗看似只有一條錯誤訊息,但背後常常是多個環節同時出了問題:映像沒有被拉取、權限不對、DNS 解析失敗、Pod 沒地方被排程、探針把容器一直重啟……你越快跳過猜測,越快回到資料本身,就越容易在短時間內修好。
下面我用一套「由外到內」的排查流程來講:先看事件與狀態鎖定失敗階段,再逐段驗證映像、身份、權限、網路與 Pod 啟動行為。每個步驟都會附上你可以直接用來判斷的依據與常見修復方向。
第一章:先判斷失敗屬於哪一層
你需要把問題分到正確的桶裡。AKS 的部署失敗通常出現在以下階段:
- YAML/資源建立階段:ConfigMap/Secret 不存在、欄位格式錯誤、命名空間或資源引用錯。
- 排程階段:Pod Pending,原因多半是節點資源不足、節點選擇器/容忍策略不匹配、PVC 尚未綁定。
- 映像拉取階段:Pod 事件顯示 ImagePullBackOff、ErrImagePull。
- 啟動階段:容器啟動後馬上崩潰,事件顯示 CrashLoopBackOff。
- 可用性階段:容器在跑,但 Readiness/Liveness 探針失敗,服務一直不可用。
Azure國際帳號服務 你不必一次看完所有指標,但要至少抓住「失敗類型」。下面用最常用的命令與現象來教你怎麼定位。
第一步:看 Pod 與事件(事件是最可靠的敘事者)
部署完成後,第一件事不是翻 log,而是先看狀態和事件。
典型流程:
kubectl get pods -n <ns>kubectl describe pod <pod-name> -n <ns>(重點找 Events)kubectl logs <pod-name> -n <ns> --all-containers(只在排到「啟動階段」時才重要)
Azure國際帳號服務 在 kubectl describe 的 Events 裡,你往往會直接看到例如:
Failed to pull image、401 Unauthorized、403 ForbiddenBack-off pulling imageFailedScheduling、0/xx nodes are availableReadiness probe failed或Liveness probe failedCrashLoopBackOff前面通常也會有 exit code 訊息或 mount 失敗
你要做的是:把錯誤字串對應到上面那五層之一,接著只針對那層深入。
第二步:確認資源引用是否一致(命名空間與 Secret 最常坑)
很多「部署失敗」其實只是宣告寫得看似合理,運行時卻引用錯地方。最常見的坑有三類:
- 命名空間不一致:Deployment 在 ns-a,Secret 卻在 ns-b。
- Azure國際帳號服務 Secret 名稱/欄位錯:Secret 內 key 名稱不是你在容器環境變數裡引用的那個。
- ImagePullSecrets 設定在錯的層級:你設定在某個 ServiceAccount 或 Deployment template 位置,但實際 Pod 沒拿到。
建議做法:檢查 Deployment(或 StatefulSet)的 spec.template.spec 內實際使用的是哪個 serviceAccountName,以及 imagePullSecrets 是否存在。
第二章:映像拉取失敗(ImagePullBackOff / ErrImagePull)
這類錯誤最常見也最好解。你看到 ImagePullBackOff,本質上就是節點上的 kubelet 拉不到映像。
常見原因分成四大類:映像名稱錯、Registry 權限不對、網路/憑證問題、或是宣告了錯誤的 imagePullSecrets。
原因一:鏡像標籤錯或命名規則錯
有些團隊會把版本策略混用:有的推的是 :1.2.3,有的用 :latest,還有的用 git SHA。Deployment 寫死某個 tag,結果那個 tag 根本不存在,就會直接拉取失敗。
排查:
- 在 ACR(或你使用的 Registry)確認該 tag 是否存在。
- 確認完整映像路徑:
<registry>/<repository>:<tag> - 檢查大小寫(某些 repository 在平台上大小寫不同會導致找不到)。
修復:更新 Deployment 的 image tag,或把 CI/CD 推送規則調整到與部署一致。
原因二:ACR 權限或身份(Managed Identity / Service Principal)不對
如果你用 ACR,最常見的方式是:
- 用
imagePullSecrets提供憑證(docker config json) - Azure國際帳號服務 或用 AKS 的 Managed Identity + RBAC 讓節點/Pod 有權拉映像
你要先確認自己用哪種。
如果你用 imagePullSecrets:
- Secret 是否真的存在於該命名空間
- Secret 的
.dockerconfigjson是否包含正確 registry 權限 - Deployment template 內是否指定了
imagePullSecrets
修復通常是重新建立 Secret,或修正 Deployment 對 Secret 的引用。
如果你用 Managed Identity / ACR pull 權限:
- 確認 ACR 中給予正確的身份角色(例如 AcrPull)
- 確認 AKS cluster 的 identity 設定是否生效(有些情境需要重新部署或確保設定連動)
- 確認你不是只把權限給了節點 identity,卻在 Pod 端使用了不同的身份路徑
修復方向:補齊 ACR 權限角色,或用對應方式授權正確的 identity。
原因三:Registry 被限制在私網 / 網路連線不足
當 ACR 開啟了私有 endpoint、或你部署在限制 egress 的網路環境,節點到 Registry 的連線就可能失敗。
典型現象:
- Events 內可能出現 time out、connection refused、或解析失敗
- 同樣的 cluster 在不同網段可能表現不同
修復方向通常包括:
- 檢查 DNS 解析是否能把 registry hostname 解析到正確的私網 IP
- 檢查 Network Security Group(NSG)與防火牆規則是否允許到 Registry 的連線
- 若用私有 endpoint,確認是否有對應的 VNet integration 與 routing 設定
你可以先用簡單測試驗證解析與連線(例如在同一 VNet 環境的測試 Pod 或節點環境做 nslookup/curl 類行為),再回到 Kubernetes 層修。
原因四:TLS / CA 憑證問題
如果你使用自簽憑證 registry 或內部 TLS 終止方式不同,節點可能因憑證信任鏈缺失導致無法完成 HTTPS 連線。
Events 可能出現 x509 相關錯誤。修復通常是把對應的 CA 憑證配置到節點信任或在容器映像中安裝憑證,具體做法視你的網路與安全策略而定。
第三章:Pod 無法排程(Pending / FailedScheduling)
如果 Pod 卡在 Pending,先不要急著去看 log,因為容器根本可能還沒啟動。你需要看的第一個地方是 kubectl describe pod 的 FailedScheduling。
原因一:節點資源不足(CPU/Memory requests 過高)
最常見的狀況是 requests 設得過高,導致叢集沒有任何節點能滿足。
排查:
kubectl describe pod ...中是否顯示 insufficient cpu/memory- 用
kubectl top nodes觀察節點是否長期接近滿載
修復方向:
- Azure國際帳號服務 調整 Deployment 的
resources.requests與limits - 檢查 HPA/VPA 是否影響到 requests(有些自動化會在運行期改變策略)
- 啟用或調整 cluster autoscaler:讓叢集在需求上來時擴容
原因二:nodeSelector / affinity / tolerations 不匹配
你可能在 YAML 中加入 nodeSelector、或使用 affinity 把 Pod 綁到特定節點池;同時你可能還設了容忍(tolerations),結果導致只有很少甚至沒有節點符合條件。
排查:
- 看 FailedScheduling 的訊息裡是否包含 nodeSelector/taint-related 字樣
- 確認節點池的 labels 是否匹配
- 確認 taint key/value 與 toleration 設定一致
修復:調整 node pool labels 或放寬 affinity/toleration,至少在測試環境先讓排程恢復。
原因三:PVC 尚未綁定(尤其是 StatefulSet)
如果你用 PersistentVolumeClaim,Pod 可能因為 PVC 未綁定或等待 provision 而 Pending。
排查:
kubectl get pvc -n <ns>kubectl describe pvc <pvc> -n <ns>看 events
修復方向取決於存儲類型與 CSI 設定:storageclass 是否存在、是否能動態 provision、以及是否有配額限制。
第四章:容器啟動失敗(CrashLoopBackOff)
當你看到 CrashLoopBackOff,代表容器已被嘗試啟動,但很快退出。這通常比 Pending 更好處理,但也更需要你看 log。
第一步:看前一次崩潰 log(--previous)
容器重啟時,當前 log 可能只顯示啟動片段。用:
kubectl logs <pod> -n <ns> -c <container> --previous
Azure國際帳號服務 找出程式退出原因,例如:
- 找不到環境變數或設定檔
- DB 連線失敗(DNS/憑證/網路策略)
- 權限問題(無法寫入目錄、檔案系統權限)
- 缺少依賴(例如動態載入的證書或字型)
原因一:ConfigMap/Secret 沒掛載成功或 key 名稱錯
這類錯常常被忽略,因為容器啟動到一半才讀設定,然後因為設定缺失而退出。
排查方式:
kubectl describe pod看是否有 Volume mount 失敗- 進一步確認檔案/環境變數是否存在:如果你能臨時加一個 sleep 進入容器或用 debug image,就能快速確認
修復:對齊 key 名稱與路徑,並確認 Secret 在正確命名空間。
原因二:容器無法連線到外部服務(DNS/網路/憑證)
你會看到應用 log 顯示連線 timeout、憑證錯誤、或連線被拒絕。
常見根因:
- 外部 endpoint 解析錯誤(DNS 指向錯誤 IP)
- NSG/防火牆阻擋出站流量
- 應用使用的 CA 憑證不存在(TLS 握手失敗)
修復方向:
- 在同一命名空間用簡易測試 Pod 驗證 DNS 與連線
- 調整出站規則或 Private Endpoint 連線策略
- 補齊憑證或調整應用信任設定
原因三:應用啟動慢,但探針太快(導致重啟)
有時不是程式真的掛了,而是探針過於激進,導致 Liveness 把容器殺掉。
你需要檢查 Deployment 的:
livenessProbe、readinessProbeinitialDelaySeconds、timeoutSeconds、failureThreshold
修復:把初始延遲與容忍次數調大,並確保 readiness 的條件對應「服務已準備好接流量」,而不是只要進程啟動就算。
原因四:檔案系統權限(非 root 使用者無法寫入)
越來越多鏡像以非 root 方式運行。若你的應用需要寫入 /tmp 或某個掛載資料夾,但安全設定沒放行,就會在啟動時退出。
Azure國際帳號服務 排查:
- log 裡是否出現 permission denied
- 檢查 securityContext:
runAsUser、fsGroup、以及 volume 的權限策略
修復:調整 securityContext,或在映像中準備好目錄權限,或對需要的掛載點設定適當 fsGroup。
第五章:探針失敗(Readiness/Liveness)與服務不可用
這類問題最折磨,因為 Pod 可能是 Running,但服務一直不通。你會看到:
- Pod 為
Running,但 Ready=false - Events 顯示 readiness probe failed
- Ingress 或 Service 的流量沒有真正打到容器
探針設計的兩個原則
第一,Readiness 是「能接流量」。你要確保 readinessProbe 代表的是依賴資源都已就緒,例如連到 DB 成功、必要緩存載入完成等。若 readiness 只做了簡單的端點回傳 200,但 DB 其實不可用,你會在上線後才發現服務假活。
第二,Liveness 是「判斷要不要重啟」。livenessProbe 不能過於敏感,否則瞬間的網路抖動就會讓 Pod 不斷重啟。
常見修復:調整探針路徑、端口與協定
很多探針失敗其實是設定錯誤:
- probe 指到錯的 port
- path 寫錯(例如從
/health變成/healthz) - 協定不一致(HTTP 換成 HTTPS)
- Azure國際帳號服務 容器還沒啟動就被探測
你可以直接從容器內部驗證探測端點:若你有 shell 訪問,確認回應內容與狀態碼。
超時與閾值:把「短暫慢」變成「可容忍」
若你的服務啟動需要載入模型、初始化連線或跑迁移,初始階段可能會超過 probe timeout。
修復策略:
- 增大
initialDelaySeconds - 增大
timeoutSeconds - 增大
failureThreshold - 必要時把 readiness 和 liveness 分別設計(readiness 允許啟動期較寬鬆,liveness 更保守)
Azure國際帳號服務 第六章:ServiceAccount 與權限(RBAC / Workload Identity / Pull 權限)
當你看到的是權限相關錯誤,或應用 log 出現 403/Access denied,多數情況是 Kubernetes RBAC 或 Azure 資源層權限不對。
在 AKS 裡,影響權限的常見元素有:
- Deployment template 中的
serviceAccountName - ServiceAccount 對應的 ClusterRole/RoleBinding
- 若使用 Workload Identity:Federated credential 與 Azure RBAC 是否正確綁定
- 若需要拉取 ACR:節點/Pod 的拉取權限是否有給到
排查順序:先看 Kubernetes 層,再看 Azure 層
你可以用以下順序思考:
- Pod 是否能成功啟動到容器?若連映像都拉不到,先處理 registry 權限。
- 容器啟動後操作的是 Kubernetes API 還是 Azure 服務?如果是 Kubernetes API,查 RBAC。
- 如果是 Azure 服務(例如 Key Vault、Storage、Event Hub),查 Workload Identity 或 MI 的 RBAC。
修復方式對應也不同:RBAC 缺少就補角色綁定;Workload Identity 缺少就補綁定與對應 Azure RBAC。
Azure國際帳號服務 第七章:一份可直接照做的部署失敗修復清單
當你站在事故現場,最需要的是「不要漏步驟」。下面我把前面章節的精華整理成可操作清單。你每次遇到部署失敗,照順序跑一遍,通常很快就能收斂原因。
Azure國際帳號服務 清單 1:快速確認症狀
- Pod 狀態是 Pending / ImagePullBackOff / CrashLoopBackOff / Running 但 Ready=false?
kubectl describe pod讀 Events:記下第一個致命錯誤句。- 若是 CrashLoop:用
kubectl logs --previous找退出原因。
清單 2:若是 ImagePullBackOff
- 確認 image 完整路徑與 tag 是否存在。
- 確認 imagePullSecrets 或 serviceAccount 對應的 pull 權限是否在正確命名空間。
- 若用 ACR:檢查 ACR 授權(AcrPull)給到的是正確 identity。
- 檢查網路:DNS、出站規則、私有 endpoint 連通性。
- 如有 TLS 問題:補憑證或調整 trust store。
清單 3:若是 Pending / FailedScheduling
- 檢查 FailedScheduling 的不足資源原因(cpu/memory)。
- 檢查 nodeSelector/affinity/tolerations 是否導致無節點可用。
- 若有 PVC:檢查 PVC events 與 storageclass。
- 視情況調整 requests 或開啟/調整 autoscaler。
清單 4:若是 CrashLoopBackOff
- 看
kubectl logs --previous:找程式退出訊息與 exit code 對應原因。 - 檢查 ConfigMap/Secret key、volume mount 是否正確。
- 檢查外部連線:DB、API、Redis 是否能解析與連線。
- 檢查檔案權限與 securityContext。
- 檢查探針是否過敏(啟動慢被重啟)。
清單 5:若是 Ready=false 或探針失敗
- 確認 probe port/path/協定正確。
- 調整 initialDelaySeconds/timeoutSeconds/failureThreshold。
- readiness 對應「可接流量」,liveness 對應「要不要重啟」。
- 檢查服務依賴是否在 readiness 階段已就緒。
第八章:如何讓部署更穩定,少遇到同一類錯
修好不代表長期穩。真正省時間的是建立能提前暴露問題的機制。
把「健康檢查」當成產品的一部分
很多團隊只在上線後才補 health endpoint。建議做法是把 readiness/liveness 端點與依賴檢查明確定義:例如 readiness 只在 DB 連線成功且必要資料已載入後回應 200;liveness 只關注程式是否進入不可恢復狀態。
CI/CD 做鏡像存在性與基本運行測試
部署前做兩件事很划算:
- 確保 ACR 中該 tag 已存在(避免人為輸入錯 tag)。
- 用最小化的方式跑容器啟動測試(例如啟動後檢查 health endpoint 回應)。
這能把一大半的 ImagePull 與啟動錯誤提前擋掉。
用一致的資源命名與環境變數介面
ConfigMap/Secret 的 key 改了但部署沒改,很常見。建議用嚴格的介面契約:例如環境變數名稱固定、Secret key 名固定,並在 PR 規範中檢查變更。
Azure國際帳號服務 資源 requests/limits 用資料而不是感覺
requests 過高會導致排程失敗,limits 過低會造成 OOM 重啟。你可以從過去版本的觀測指標(CPU/memory)推估 requests,然後用少量 buffer 方式調整。
結語:把排查變成流程,你就不會被錯誤牽著走
AKS 容器部署失敗並不可怕,可怕的是把有限時間拿去猜測。正確做法是用狀態與事件把問題分層,再進入對應層級驗證:映像與權限、網路連通、排程條件、容器啟動行為、以及探針與依賴就緒。當你把每次事故都歸檔成「症狀—原因—修復」,下一次同類問題就會變成快速套用的經驗,而不是重來一次的痛。

