一般來說,無論 Pod 處於什麼異常狀態,都可以執行以下命令來查看 Pod 的狀態
- kubectl get pod <pod-name> -o yaml 查看 Pod 的配置是否正確
- kubectl describe pod <pod-name> 查看 Pod 的事件
- kubectl logs <pod-name> [-c <container-name>] 查看容器日誌
Pod --Pending狀態
Pending 說明 Pod 還沒有調度到某個 Node 上面。可以通過
kubectl describe pod <pod-name> 命令查看到當前 Pod 的事件,進而判斷爲什麼沒有調度。可能的原因包括
- 資源不足,集羣內所有的 Node 都不滿足該 Pod 請求的 CPU、內存、GPU 等資源
- HostPort 已被佔用,通常推薦使用 Service 對外開放服務端口
Pod --Waiting 或 ContainerCreating狀態
首先還是通過 kubectl describe pod <pod-name> 命令查看到當前 Pod 的事件。可能的原因包括
- 鏡像拉取失敗,比如配置了鏡像錯誤、Kubelet 無法訪問鏡像、私有鏡像的密鑰配置錯誤、鏡像太大,拉取超時等
- CNI 網絡錯誤,一般需要檢查 CNI 網絡插件的配置,比如無法配置 Pod 、無法分配 IP 地址
- 容器無法啓動,需要檢查是否打包了正確的鏡像或者是否配置了正確的容器參數
Pod -- ImagePullBackOff狀態
這也是我們測試環境常見的,通常是鏡像拉取失敗。這種情況可以使用 docker pull <image> 來驗證鏡像是否可以正常拉取。
或者docker images | grep <images>查看鏡像是否存在(系統有時會因爲資源問題自動刪除一部分鏡像),
Pod -- CrashLoopBackOff狀態
CrashLoopBackOff 狀態說明容器曾經啓動了,但可能又異常退出了。此時可以先查看一下容器的日誌
kubectl logs <pod-name> kubectl logs --previous <pod-name>
這裏可以發現一些容器退出的原因,比如
- 容器進程退出
- 健康檢查失敗退出
Pod --Error 狀態
通常處於 Error 狀態說明 Pod 啓動過程中發生了錯誤。常見的原因包括
- 依賴的 ConfigMap、Secret 或者 PV 等不存在
- 請求的資源超過了管理員設置的限制,比如超過了 LimitRange 等
- 違反集羣的安全策略,比如違反了 PodSecurityPolicy 等
- 容器無權操作集羣內的資源,比如開啓 RBAC 後,需要爲 ServiceAccount 配置角色綁定
Pod --Terminating 或 Unknown 狀態
從 v1.5 開始,Kubernetes 不會因爲 Node 失聯而刪除其上正在運行的 Pod,而是將其標記爲 Terminating 或 Unknown 狀態。想要刪除這些狀態的 Pod 有三種方法:
- 從集羣中刪除該 Node。使用公有云時,kube-controller-manager 會在 VM 刪除後自動刪除對應的 Node。而在物理機部署的集羣中,需要管理員手動刪除 Node(如 kubectl delete node <node-name>。
- Node 恢復正常。Kubelet 會重新跟 kube-apiserver 通信確認這些 Pod 的期待狀態,進而再決定刪除或者繼續運行這些 Pod。
- 用戶強制刪除。用戶可以執行 kubectl delete pods <pod> --grace-period=0 --force 強制刪除 Pod。除非明確知道 Pod 的確處於停止狀態(比如 Node 所在 VM 或物理機已經關機),否則不建議使用該方法。
特別是 StatefulSet 管理的 Pod,強制刪除容易導致腦裂或者數據丟失等問題。
Pod -- Evicted狀態
出現這種情況,多見於系統內存或硬盤資源不足,可df-h查看docker存儲所在目錄的資源使用情況,如果百分比大於85%,就要及時清理下資源,尤其是一些大文件、docker鏡像。
清除狀態爲Evicted的pod:
kubectl get pods | grep Evicted | awk '{print $1}' | xargs kubectl delete pod
刪除所有狀態異常的pod:
kubectl delete pods $(kubectl get pods | grep -v Running | cut -d ' ' -f 1)
刪除集羣中沒有在使用的docker鏡像(慎用):
docker system prune -a
查看pod對應的服務(鏡像)版本:
kubectl --server=127.0.0.1:8888 get rc -o yaml | grep image: |uniq | sort | grep ecs-core
附:
刪除某類歷史鏡像(僅保留當前使用的)
docker images | grep ecs-core | grep -v `docker images | grep ecs-core -m 1 | awk '{print $2}'` | awk '{print $3}' | xargs docker rmi -f