掌握Kubernetes Pod故障排除:高級策略和方案
Kubernetes(K8s)部署通常會帶來各種角度的挑戰(zhàn),包括 pod、服務、ingress、無響應集群、控制平面和高可用性設置。Kubernetes pod 是 Kubernetes 生態(tài)系統(tǒng)中最小的可部署單元,封裝了一個或多個共享資源和網(wǎng)絡的容器。Pod 旨在運行應用程序或進程的單個實例,并根據(jù)需要創(chuàng)建和處置。Pod 對于在 K8s 環(huán)境中擴展、更新和維護應用程序至關重要。
譯自 Master Kubernetes Pods: Advanced Troubleshooting Strategies,作者 None。
本文探討了 Kubernetes pod 面臨的挑戰(zhàn)以及要采取的故障排除步驟。運行 Kubernetes pod 時遇到的部分錯誤消息包括:
- ImagePullBackoff
- ErrImagePull
- InvalidImageName
- CrashLoopBackOff
有時,您甚至不會遇到列出的錯誤,但仍會發(fā)現(xiàn)您的 pod 失敗。首先,需要注意的是,在調(diào)試任何 Kubernetes 資源時,您都應該了解 API 參考。它解釋了如何定義各種 Kubernetes API 以及 pod/部署中的多個對象如何工作。文檔在 Kubernetes 網(wǎng)站上的 API 參考中定義得很明確。在這種情況下,在調(diào)試 pod 時,從 API 參考中選擇 pod 對象以詳細了解 pod 的工作原理。它定義了進入 pod 的字段,即版本、類型、元數(shù)據(jù)、規(guī)范和狀態(tài)。Kubernetes 還提供了一個作弊小炒,其中包含所需命令的指南。
先決條件
本文假設讀者具備以下條件:
- 已安裝 Kind 以進行場景演示
- 對 Kubernetes 架構有中級了解
- Kubectl 命令行工具
Kubernetes Pod 錯誤 - ImagePullBackoff
該錯誤顯示有三個不同的原因:
- 無效鏡像
- 無效標簽
- 無效權限
當您沒有有關鏡像的正確信息時,就會出現(xiàn)這些情況。您可能也沒有從其存儲庫(私有存儲庫)中提取鏡像的權限。為了在下面的示例中演示這一點,我們創(chuàng)建了一個 nginx 部署:
? ~ kubectl create deploy nginx --image=nginxdeployment.apps/nginx
created
Pod 正在運行后,獲取 pod 名稱:
? ~ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-8f458dc5b-hcrsh 1/1 Running 0 100s
復制正在運行的 pod 的名稱并獲取有關它的更多信息:
? ~ kubectl describe pod nginx-8f458dc5b-hcrsh
Name: nginx-8f458dc5b-hcrsh
hable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m43s default-scheduler Successfully assigned default/nginx-8f458dc5b-hcrsh to k8s-troubleshooting-control-plane
Normal Pulling 2m43s kubelet Pulling image "nginx"
Normal Pulled 100s kubelet Successfully pulled image "nginx" in 1m2.220189835s
Normal Created 100s kubelet Created container nginx
Normal Started 100s kubelet Started container nginx
鏡像已成功拉取。您的 Kubernetes pod 正在運行,沒有錯誤。
要演示 ImagePullBackoff,請編輯部署 YAML 文件并指定一個不存在的鏡像:
? kubectl edit deploy nginx
containers:
-image: nginxdoestexist
imagePullPolicy: Always
name: nginx
新 pod 未成功部署
? ~ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-5b847fdb95-mx4pq 0/1 ErrImagePull 0 3m40s
nginx-8f458dc5b-hcrsh 1/1 Running 0 38m
顯示 ImagePullBackoff 錯誤
? ~ kubectl describe pod nginx-6f46cbfbcb-c92bl
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 88s default-scheduler Successfully assigned default/nginx-6f46cbfbcb-c92bl to k8s-troubleshooting-control-plane
Normal Pulling 40s (x3 over 88s) kubelet Pulling image "nginxdoesntexist"
Warning Failed 37s (x3 over 85s) kubelet Failed to pull image "nginxdoesntexist": rpc error: code = Unknown desc = failed to pull and unpack image "docker.io/library/nginxdoesntexist:latest": failed to resolve reference "docker.io/library/nginxdoesntexist:latest": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
Warning Failed 37s (x3 over 85s) kubelet Error: ErrImagePull
Normal BackOff 11s (x4 over 85s) kubelet Back-off pulling image "nginxdoesntexist"
Warning Failed 11s (x4 over 85s) kubelet Error: ImagePullBackOff
Kubernetes Pod 錯誤 - 已拉取鏡像但 Pod 處于 pending 狀態(tài)。
每當你在生產(chǎn)環(huán)境中運行 K8s 時,K8s 管理員會根據(jù)集群內(nèi)運行的命名空間的要求為每個命名空間分配資源配額。命名空間用于在集群內(nèi)進行邏輯分離。
當資源配額中的規(guī)范不滿足 Pod 中應用程序的最低要求時,就會拋出“Image pulled, but the pod is still pending”錯誤。在以下示例中,創(chuàng)建一個名為 payments 的命名空間:
? ~ kubectl create ns payments
namespace/payments created
使用相關規(guī)范創(chuàng)建資源配額
? ~ cat resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 4Gi
將資源配額分配給命名空間 payments
? ~ kubectl apply -f resourcequota.yaml -n paymentsresourcequota/compute-resources created
在具有資源配額限制的命名空間內(nèi)創(chuàng)建新部署:
kubectl create deploy nginx --image=nginx -n paymentsdeployment.apps/nginx created
盡管已成功創(chuàng)建部署,但沒有 Pod 存在:
? ~ kubectl get pods -n payments
No resources found in payments namespace
已創(chuàng)建部署,但是沒有處于準備狀態(tài)的 Pod,沒有更新的 Pod,也沒有可用的 Pod:
? ~ kubectl get deploy -n payments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 0/1 0 0 7m4s
要進一步調(diào)試,請描述 nginx 部署。Pod 創(chuàng)建失?。?/p>
? ~ kubectl describe deploy nginx -n payments
Name: nginx
Namespace: payments
CreationTimestamp: Wed, 24 May 2023 21:37:55 +0300
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=nginx
Replicas: 1 desired | 0 updated | 0 total | 0 available | 1 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available False MinimumReplicasUnavailable
ReplicaFailure True FailedCreate
Progressing False ProgressDeadlineExceeded
OldReplicaSets: <none>
NewReplicaSet: nginx-8f458dc5b (0/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 10m deployment-controller Scaled up replica set nginx-8f458dc5b to 1
從 Kubernetes 事件進行的進一步分析顯示 Pod 創(chuàng)建所需的內(nèi)存不足。
? ~ kubectl get events --sort-by=/metadata.creationTimestamp
當你的鏡像已成功拉取,并且你的容器已創(chuàng)建,但你的運行時配置失敗時,就會發(fā)生此錯誤。例如,如果你有一個正在嘗試寫入不存在的文件夾或沒有寫入該文件夾的權限的正在工作的 Python 應用程序。最初,應用程序會執(zhí)行,然后遇到錯誤。如果你的應用程序邏輯中出現(xiàn) panic ,則容器將停止。容器將進入 CrashLoopBackOff。最終,你觀察到部署沒有 Pod,即存在一個 Pod,但它沒有運行并拋出 CrashLoopbackoff 錯誤。
存活和就緒探測失敗
存活(Liveness)探測檢測 Pod 是否已進入損壞狀態(tài)且無法再提供流量。Kubernetes 將為您重新啟動 Pod。就緒(readiness )探測檢查您的應用程序是否已準備好處理流量。就緒探測確保您的應用程序從配置映射中提取所有必需的配置并啟動其線程。只有完成此過程后,您的應用程序才準備好接收流量。如果您的應用程序在此過程中遇到錯誤,它也會進入 CrashLoopBackoff。
開始故障排除!
本文概述了 Kubernetes Pod 的故障排除技術。它解決了在部署 Pod 時遇到的常見錯誤,并提供了解決這些錯誤的實用解決方案。它還深入了解了在理解 Kubernetes 工作原理和有效識別和解決問題時至關重要的參考頁面和備忘單。通過遵循本文中提供的指導,讀者可以提高他們的故障排除技能,并簡化其 Kubernetes Pod 的部署和管理。