GCP帳號充值代辦 Google Cloud GKE容器部署失敗排查
前言:先別急著改,先把失敗「定性」
在 GKE 上部署容器失敗,最大問題不是你不會修,而是你一開始就把精力平均灑在所有可能性上:鏡像是不是壞的、ServiceAccount 權限夠不夠、網路能不能通、資源是否不夠、掛載卷是否正確、就緒探針是不是判斷錯了……最後常見的結局是「改了很多,但不知道改到哪裡有用」。
更務實的做法是:先把失敗定性成幾類,再對應到合理的排查路徑。GKE 的錯誤訊息雖然複雜,但其實具有規律。你只要抓住其中幾個關鍵字,就能快速縮小範圍。
本文以「部署失敗排查」為主線,提供一套從現象到根因的通用流程。你不一定每一次都遇到全部情況,但這套流程能讓你在 30 分鐘內看出大方向。
第一章:快速判斷失敗類型(先看 Pod 狀態)
大多數問題最後都會落在 Pod 上。先用最直接的方式看狀態,而不是急著看部署 YAML。
1. Pod 一直 Pending:多半是排程或資源、網路或卷問題
如果 Pod 長時間是 Pending,常見原因包括:
- 節點資源不足(CPU/Memory 不夠)
- 節點選擇器與容忍(nodeSelector、nodeAffinity、taints/tolerations)不匹配
- PV/StorageClass 無法供應
- 事件顯示拉不下鏡像前就卡住(偶爾也會先呈現 Pending)
- 叢集網路/子網路配置導致節點無法正確加入或 Pod 網路未就緒
下一步不是猜,而是看事件。
GCP帳號充值代辦 2. Pod 出現 ImagePullBackOff 或 ErrImagePull:優先懷疑鏡像路徑與憑證
這類錯誤非常典型。你會看到類似 ImagePullBackOff、ErrImagePull、unauthorized、manifest unknown、denied。
常見根因:
- 鏡像名稱/Tag 寫錯(尤其是版本號或路徑)
- 鏡像私有,需要正確的 ImagePullSecret 或 Workload Identity 配置
- 雲端端點或權限未授權(例如 Artifact Registry/Container Registry 權限不足)
- 節點無法連到鏡像服務(網路 egress、DNS、代理、VPC Service Controls 等)
3. Pod 是 CrashLoopBackOff:大多是啟動參數、程式啟動失敗或探針設定
當你看到 CrashLoopBackOff,要先確認是容器真的崩潰,還是被探針重啟。
常見原因:
- GCP帳號充值代辦 程式需要環境變數/設定檔,但 ConfigMap/Secret 掛載失敗或 key 名稱不正確
- 應用啟動命令錯誤、工作目錄錯、依賴檔缺失
- 探針(liveness/readiness/startup)設定不合理,導致還沒就緒就被殺掉
- 資源不足導致 OOMKilled
4. Pod Running 但 Service 不通:通常是 Service/Ingress/防火牆或容器監聽錯誤
不少人會以為部署成功就結束了,但對外服務不通通常是下一層問題。這時候你要回頭看:
- Service selector 是否匹配 Pod labels
- 容器監聽的 port 是否和 Service targetPort 對得上
- Ingress path/host 規則是否正確
- NetworkPolicy 是否阻擋
- GCP帳號充值代辦 防火牆/負載平衡器健康檢查是否失敗
第二章:用事件與日誌把線索「串起來」
GKE 不是只有 Pod 狀態,事件(Events)與日誌是你最好的推理工具。你要做的不是看一堆輸出,而是找「第一個明確錯誤」。
1. 先看事件:kubectl describe pod
對單一 Pod 跑 kubectl describe pod,你通常會看到事件區塊列出類似:
- Failed to pull image:原因通常非常明確
- FailedScheduling:事件會指出不可行的原因,例如 node selector/Insufficient cpu
- FailedMount:指向卷與權限/路徑
- Readiness probe failed:指向探針 URL/端口/逾時
重要的是:事件是時間序列。不要只看最後一行,把「最早出錯」的那條當作主線。
2. 再看容器日誌:kubectl logs
日誌能揭露程式啟動階段發生的真正錯誤。常見做法是先看最後一次失敗:
kubectl logs <pod>- 如果有重啟,查上一個容器:
kubectl logs --previous
另外,如果你使用了多容器 Pod,記得指定 -c。很多人只看主容器日誌,卻忽略 sidecar 才是失敗點。
3. Pod 沒起來就看不到日誌:改看 initContainer 或事件
如果 Pod 在 initContainer 階段失敗,你的主容器日誌可能根本不存在。這時候要查:
- 事件:Failed to pull image、FailedMount、Back-off restarting failed container 等
- 描述:initContainers 區塊的狀態
這能把排查範圍從「應用本身」縮到「啟動前步驟」。
第三章:鏡像與憑證失敗(最常見的第一類)
很多部署失敗不是雲端複雜,而是鏡像拉不下來。你應該把鏡像排查放在最前面,因為它能快速結束一半問題。
1. 檢查鏡像 reference:Tag、digest、路徑
請確認 Deployment/PodSpec 裡的 image 字串完全正確。常見踩雷:
- 容器映像登記在 Artifact Registry,但你寫成了 Container Registry 格式
- Tag 拼寫錯,或使用了尚未 push 的版本
- 大小寫錯誤(某些系統會在特定情況下敏感)
- 工作流程用 digest,但你改回了 tag(tag 可能被覆蓋或回收)
GCP帳號充值代辦 建議做法是:確認你推上去的鏡像「完整名稱」與部署中的一致。
2. 如果是私有鏡像:ImagePullSecret / Workload Identity
私有鏡像常見是權限不足。GKE 現代化常用 Workload Identity,而不是一直塞 ImagePullSecret。兩者都要確認:
- 若用 ImagePullSecret:Secret 是否存在於同一個 namespace?是否正確?
- 若用 Workload Identity:KSA(Kubernetes Service Account)是否映射到 GCP Service Account?角色是否授予(例如讀取 Artifact Registry)?
你可以透過事件中的 unauthorized、denied 字樣判斷方向。遇到此類錯誤,優先處理憑證與權限,而不是去動應用程式。
3. 網路導致「看似權限問題」的鏡像拉取失敗
有些環境使用 Private Cluster、限制 egress、或有 VPC Service Controls,導致節點其實無法連到鏡像服務。這時候你可能看到類似超時、解析失敗或不可達。
排查可從:
- 節點子網與路由是否允許出站
- DNS 解析是否正常
- 是否需要 Cloud NAT
- 是否有 firewall 規則阻擋
先把基礎網路跑通,後續才談權限與配置。
第四章:資源與排程(Pending 最容易被低估)
Pending 常常不只是「資源不夠」。你需要看排程被卡在哪一步。
1. FailedScheduling:nodeSelector / affinity / tolerations
如果 Deployment 使用 nodeSelector 或 affinity,請檢查它與集群節點標籤是否一致。同時如果節點上有 taint,你的 Pod 必須有 toleration 才能調度到該節點。
事件中的 0/... 以及理由能直接告訴你哪個條件不滿足。例如:
- didn't match Pod's node affinity/selector
- had taint ... that the pod didn't tolerate
2. Insufficient cpu/memory:資源請求是否過高
請求(requests)過大是常見原因。尤其是你把 requests 設得接近 limits,結果一旦節點縮容或自動擴縮節奏不同,就容易卡住。
處理方式一般是:
- 調整 requests/limits,讓 requests 反映「實際需要」而不是估算
- 確認 HPA/Cluster Autoscaler 目標設定
- 檢查節點池大小、autoscaling 上限與最小值
3. Storage 供應失敗:PVC/PV 相關事件
若使用 PVC,Pending 有時是因為 StorageClass 供應器或參數錯誤。事件可能提示:
- provisioning failed
- no storage class
- permission denied
這類問題不要只看 Pod,去看 PVC、StorageClass,以及相關的 provisioner 日誌或事件。
第五章:掛載卷、環境變數與 Secret/ConfigMap
很多 CrashLoopBackoff 或啟動失敗,都源自「配置沒有如你想像」。部署成功到容器啟動,配置錯了照樣會炸。
1. ConfigMap/Secret key 不存在:找不到檔案或環境變數
如果你用 envFrom 或 env 取某個 key,key 名稱若不匹配,就會讓應用拿到空值或啟動失敗。這在事件層面未必明顯,通常要看容器日誌。
如果你用 volumeMount 指向檔名,則掛載的檔案也可能不在預期路徑。
2. 檔案權限問題:容器無法讀取掛載目錄
某些應用需要讀取特定路徑,但掛載卷預設權限可能不符合。你會在日誌看到例如 permission denied、read-only file system 等。
處理常見做法包括:
- 調整 Secret/ConfigMap 掛載方式(items、mode)
- 如果使用 CSI,檢查 mount options
- 在應用啟動命令前處理權限(例如 initContainer 改權限)
3. 依賴啟動順序:initContainer 沒做完
如果 initContainer 負責拉取模型、初始化資料庫、或等待外部服務,失敗會直接阻止主容器啟動。你需要看 initContainer 的事件與日誌,因為這通常是最早的錯誤點。
第六章:探針設定錯誤(看似應用問題,其實是調度邏輯)
探針(liveness/readiness/startup)是一個常見「部署後才爆炸」的來源。容器其實能跑,但被探針判定為不健康而一直重啟。
1. Readiness 探針失敗:服務永遠不進流量
Readiness 失敗不一定讓 Pod 重啟,但會導致 Service 對外不可用。你會看到:
- Pod 狀態可能是 Running
- 但 endpoints 可能不包含該 Pod
檢查方向:
- 探針的 port 是否正確
- 路徑是否正確(例如 healthz vs /health)
- 應用是否需要特定 header 或基礎路徑
- time out、period、failureThreshold 是否太短
2. Liveness 探針失敗:一直 CrashLoopBackOff
如果 liveness 間隔太短或容器啟動需時間較長,你會看到反覆重啟。常見做法:
- 加入 startupProbe,先讓應用有緩衝時間
- 調整 liveness initialDelaySeconds、periodSeconds
- 若探針依賴外部服務,外部服務緩慢時要考慮容錯
3. 探針對應的端點在容器內能不能被連到
不要只相信你寫的 URL。容器內端點可能綁到不同介面或不同 port。這在日誌裡可能沒有明顯錯誤,只能通過探針結果與應用實際監聽行為確認。
若你能臨時進入容器(debug),用容器內的方式測試 health endpoint 會最快。
第七章:Service、Ingress 與負載平衡健康檢查
GCP帳號充值代辦 當 Pod 本身看起來是 Running,但外部流量不通,問題通常在服務層。
1. Service 不通:selector 與 labels 不匹配
Service 的 selector 必須與 Pod labels 匹配,否則流量永遠找不到後端。這類問題很常見,尤其是你複製了 YAML,改了 labels 卻忘了改 selector。
排查方向:
- 確認 Deployment/Pod template metadata.labels
- GCP帳號充值代辦 確認 Service selector
- 確認 targetPort 與容器 port 名稱或數字一致
2. Ingress 不通:規則主機名/路徑不匹配或證書問題
Ingress 常見問題包括:
- host 規則與實際請求主機名不同
- pathType 與路徑匹配行為不如預期
- TLS 證書未正確配置或域名不一致
負載平衡器層面通常也會有健康檢查狀態。若後端健康檢查失敗,Ingress 對外也會直接出現 502/503。
3. NetworkPolicy:讓你「看似部署成功」卻永遠互通不了
如果你的環境啟用了 NetworkPolicy,預設可能是拒絕所有入站或出站。這會導致服務之間互相無法訪問。你需要確認:
- 是否有 Ingress policy 限制來源
- 是否有 Egress policy 限制外部呼叫
- 是否需要允許探針流量(有些情況會被誤封)
第八章:權限、IAM 與 GCP 服務整合問題
當應用需要存取其他 GCP 服務(例如存取 Cloud Storage、Secret Manager、BigQuery、Pub/Sub),部署可能表面成功,但應用一啟動就報權限錯誤,最後變成 CrashLoopBackoff。
1. Workload Identity 映射錯誤:請先對齊 Service Account
在 Workload Identity 下,容器內使用的身份來自 KSA 映射到 GCP Service Account。若映射錯了或缺角色,應用就會看到 permission denied。
你要做的是把以下幾個點對齊:
- KSA 名稱與 namespace
- 映射到哪個 GCP Service Account
- GCP Service Account 是否授予正確角色(最低權限)
2. 範圍與環境不一致:同一套 code 在不同環境就失敗
常見情況是 dev/prod 用不同的 project、不同的 Artifact Registry/Storage bucket,結果權限在某個環境缺失。排查時要特別注意環境變數(PROJECT_ID、BUCKET_NAME、TOPIC 等)是不是也一起更新。
3. 使用 Secret Manager 時:secret 名稱或版本錯
若應用從 Secret Manager 拉取密鑰,但 secret id 不存在、版本不對、或沒有讀取權限,就會直接啟動失敗。這類錯誤通常出現在容器日誌的最前幾行。
第九章:一套可重複的排查流程(建議你照著走)
GCP帳號充值代辦 下面是一套「從部署失敗到找到根因」的固定流程。你下次遇到類似問題,只要把輸入替換成你的資源名稱即可。
步驟 1:確定你卡在哪個階段
- kubectl 看 Pod 狀態:Pending / ImagePullBackOff / CrashLoopBackOff / Running 但不通
GCP帳號充值代辦 步驟 2:看同一個 Pod 的 Events,找最早明確錯誤
- kubectl describe pod
- 抓到第一個 Failed 原因當主線
步驟 3:若容器有啟動,先看日誌
- kubectl logs(必要時加 --previous)
- 關注的是應用啟動第一段失敗的訊息,不要只看最後一行
步驟 4:按錯誤類型對應處理
- ImagePull 類:鏡像 reference、憑證、網路出站
- Pending 類:排程條件、資源、PVC 供應
- CrashLoop 類:啟動命令、配置、探針、權限、依賴服務
- 不通類:Service selector/ports、Ingress 規則、健康檢查、NetworkPolicy
GCP帳號充值代辦 步驟 5:每修一次,都用「具體證據」驗證
- 修完 ImagePull:確認 Pod 不再報 unauthorized/manifest unknown
- 修完探針:確認 readiness 變成 True,endpoint 開始出現
- 修完權限:確認應用日誌不再 permission denied
不要靠「我覺得應該好了」來收工。GKE 的驗證最好落在 Pod 狀態與事件、以及對外服務的回應上。
第十章:常見「坑」總結(你可以用來自我檢查)
以下是我在實務中最常見、也最容易浪費時間的坑。你可以把它當成自查清單。
坑 1:tag 寫對了,但 registry 還是錯專案/區域
Artifact Registry 的位置(region)與 project 都會影響可用性。Tag 正確只是必要條件,不是充分條件。
坑 2:Service selector 不是筆誤,而是 labels 結構不同
例如 Pod labels 是 app.kubernetes.io/name,但 Service selector 寫成 app。看起來差不多,但永遠不匹配。
GCP帳號充值代辦 坑 3:資源 requests 設太大,導致 autoscaling 沒跟上
Cluster Autoscaler 不是萬能。requests 過大會讓擴容策略來不及或擴不到合適的節點大小。
GCP帳號充值代辦 坑 4:探針路徑對了,卻忘了容器內 base path 或路由規則
很多框架有固定的路由前綴,例如 /api/health。你只要漏掉一段就會一直 readiness 失敗。
GCP帳號充值代辦 坑 5:Workload Identity 看似設定了,但缺少 Artifact Registry 讀取角色
有些人先解決了容器能啟動(因為部分動作不用權限),但後面拉模型或拉資料時才爆權限錯誤。這就會變成後續服務失敗。
結語:把排查變成「可學習的流程」
GKE 的部署失敗排查,真正難的不是技術點太多,而是資訊散落在狀態、事件、日誌、資源定義和雲端權限裡。你要做的,是讓每次排查都有固定路徑:先定性,再看第一個錯誤,再用日誌驗證,再對應類型處理。
當你把這套流程內化,你會發現自己不再依賴運氣,而是能用證據一步一步把根因挖出來。下一次容器部署失敗時,不用再盲目改 YAML,你只要回到「先看 Pod 狀態與事件」這個起點,就能更快到達正確答案。
如果你願意把你遇到的具體錯誤訊息(例如事件中的 Failed 原因、ImagePullBackOff 的細節、或 CrashLoopBackOff 的日誌片段)貼出來,我也可以幫你把排查路徑縮到最短。

