iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0

昨天設定了 NetworkPolicy,限制 Pod 之間的網路流量。今天會整理 K8s 除錯的流程,以及常見錯誤的排查方式。


除錯流程

遇到問題,從上往下逐層縮小範圍:

第一步:確認整體狀態
kubectl get pods

        │
        ▼

第二步:找到異常的 Pod,看詳細事件
kubectl describe pod <pod-name>
→ 看 Events 區塊,通常錯誤原因就在這裡

        │
        ▼

第三步:看 Container Log
kubectl logs <pod-name> --previous

        │
        ▼

第四步:進到 Pod 裡面確認環境
kubectl exec -it <pod-name> -- bash
→ 確認環境變數、網路連線、相依服務

        │
        ▼

第五步:確認相關資源是否正常
kubectl describe service <service-name>
kubectl get endpoints

問題通常在某一層就能找到答案,不需要每次都走到最底層。


常見錯誤

1. CrashLoopBackOff

Container 啟動後馬上崩潰,K8s 不斷重啟它,重啟間隔越來越長(10s → 20s → 40s...),這就是 CrashLoopBackOff。

為什麼會發生

Container 崩潰通常是程式在啟動階段就遇到致命錯誤,最常見的有三種:

  • 環境變數缺少或寫錯,程式一啟動就拋錯退出
  • 相依服務還沒準備好,例如 todo-api 啟動時 MySQL 還在初始化,連線失敗直接退出
  • 程式本身有 bug,啟動流程中觸發了未處理的 exception

怎麼判斷是哪個原因

Pod 崩潰之後 log 會消失,要用 --previous 看上一個容器的輸出:

kubectl logs <pod-name> --previous

看 log 最後幾行,通常就是崩潰原因。如果是環境變數問題,會看到類似:

KeyError: 'DATABASE_URL'
sqlalchemy.exc.OperationalError: Can't connect to MySQL server on 'wrong-host'

如果是相依服務的問題,可以進 Pod 確認連線:

kubectl exec -it <pod-name> -- bash -c "nc -zv mysql-service 3306"

修完怎麼確認

修正之後等 Pod 重建,確認 RESTARTS 不再增加、STATUS 變成 Running:

kubectl get pods -w

2. ImagePullBackOff

K8s 拉不到指定的 image,Pod 無法啟動。

為什麼會發生

K8s 在建立 Pod 的時候會去 Registry 拉 image,失敗的原因通常是:

  • image 名稱或 tag 寫錯,Registry 上根本不存在這個 image
  • 私有 Registry 沒有設定認證,K8s 沒有權限拉取

怎麼判斷是哪個原因

describe pod 的 Events 會直接說明失敗原因:

kubectl describe pod <pod-name>

如果看到 manifest unknown,是 image 名稱或 tag 不存在。如果看到 pull access denied,是認證問題,需要設定 imagePullSecrets。

修完怎麼確認

確認 image 名稱之後更新 Deployment,等新的 Pod 建立,Events 不再出現 pull 錯誤:

kubectl describe pod <new-pod-name>

3. Pending

Pod 一直停在 Pending,表示 K8s 的調度器找不到合適的 Node 來運行它。

為什麼會發生

調度器在決定 Pod 要跑在哪個 Node 之前,會檢查每個 Node 是否滿足條件。常見的失敗原因:

  • Node 的剩餘 CPU 或記憶體不足以滿足 Pod 的 Resource Request
  • Pod 設定了 nodeSelector 或 affinity,但沒有 Node 符合條件
  • PVC 沒有綁上對應的 PersistentVolume,Pod 在等 storage 準備好

怎麼判斷是哪個原因

describe pod 的 Events 會說明調度失敗的原因:

kubectl describe pod <pod-name>

常見的 Events 訊息:

# 資源不足
0/1 nodes are available: 1 Insufficient cpu

# PVC 沒綁上
0/1 nodes are available: 1 pod has unbound immediate PersistentVolumeClaims

如果是資源不足,可以看 Node 目前的使用狀況:

kubectl describe node minikube | grep -A5 "Allocated resources"

修完怎麼確認

資源問題解決後,調度器會自動重新嘗試,Pod 狀態會從 Pending 變成 ContainerCreating 再變成 Running。


4. Running 但功能異常

這是最難排查的狀況,Pod 看起來正常,但服務沒有回應或回錯誤。難在問題可能出在好幾個地方:Pod 本身、Service、網路、或是應用程式邏輯。

怎麼逐步縮小範圍

先確認流量有沒有到 Pod

kubectl describe service <service-name>

看 Endpoints 這行。如果是 <none>,流量根本沒有進到任何 Pod,問題出在 Service 設定,最常見是 selector 跟 Pod 的 labels 對不上:

# 比對兩者
kubectl get pod <pod-name> --show-labels
kubectl get service <service-name> -o jsonpath='{.spec.selector}'

流量有到 Pod,但 API 回錯誤

看 runtime log,搭配實際打一個請求,觀察 log 裡出現什麼:

kubectl logs -f <pod-name>

log 看不出原因

直接進 Pod 裡面確認環境變數和連線:

kubectl exec -it <pod-name> -- bash
env | grep DATABASE_URL
nc -zv mysql-service 3306

修完怎麼確認

打一個實際的 API 請求,確認回應正常,同時看 log 沒有新的錯誤出現。


小結

狀態 先查什麼 最常見原因
CrashLoopBackOff logs --previous 環境變數錯、相依服務連不到
ImagePullBackOff describe pod Events image 名稱或 tag 錯誤、沒有認證
Pending describe pod Events 資源不足、PVC 沒綁上
Running 但異常 describe service Endpoints selector 跟 labels 對不上、runtime 錯誤

明天會學 Helm,K8s 的套件管理工具,解決目前手動管理大量 YAML 的問題。


上一篇
Day 20|NetworkPolicy
下一篇
Day 22|Helm (1)
系列文
從零學 K8s|30 天核心概念 × 實作,新手也能真正掌握 Kubernetes 共 25 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言