Kubernetes 生產(chǎn)環(huán)境常見問題與排查命令總結(jié)
運(yùn)維工程師在日常工作中,Kubernetes 集群的穩(wěn)定性直接決定了業(yè)務(wù)服務(wù)的可用性。生產(chǎn)環(huán)境中,Pod 啟動(dòng)失敗、Node 不可用、Service 訪問異常、存儲掛載報(bào)錯(cuò)等問題幾乎每天都會遇到。本文從一線運(yùn)維視角出發(fā),系統(tǒng)梳理 Kubernetes 生產(chǎn)環(huán)境中最常見的問題現(xiàn)象、排查思路、關(guān)鍵命令和修復(fù)方案,形成可直接照著操作的故障排查手冊。
一、問題背景與適用場景
1.1 背景說明
Kubernetes 作為容器編排平臺,其復(fù)雜度遠(yuǎn)高于傳統(tǒng)虛擬機(jī)或物理機(jī)。一個(gè)看似簡單的 Pod 啟動(dòng)失敗,可能涉及鏡像、網(wǎng)絡(luò)、存儲、調(diào)度、權(quán)限等多個(gè)層面的配置問題。在生產(chǎn)環(huán)境中,往往需要快速定位問題、避免業(yè)務(wù)中斷,同時(shí)不能因?yàn)檎`操作引發(fā)更大的故障。
本文的排查思路適用于以下場景:
開發(fā)、測試、預(yù)發(fā)布、生產(chǎn)各環(huán)境
基于 kubeadm、kops、Rancher、TKE、EKS、ACK 等方式部署的集群
使用 Deployment、StatefulSet、DaemonSet、Job、CronJob 等控制器部署的工作負(fù)載
有狀態(tài)應(yīng)用(MySQL、Redis)與無狀態(tài) Web 服務(wù)混合部署的場景
1.2 閱讀前提
閱讀本文需要具備以下基礎(chǔ)知識:
了解 Kubernetes 基本概念:Pod、Node、Namespace、Deployment、Service、Ingress、PersistentVolumeClaim、ConfigMap、Secret
熟悉 kubectl 基本操作
了解 Linux 基礎(chǔ)命令:ps、top、df、mount、netstat/ss、curl、dig、kubectl
了解 Docker 基礎(chǔ)概念:鏡像、容器、卷
1.3 排查原則
在進(jìn)入具體問題之前,先明確幾個(gè)排查原則:
分層排查,從下往上:先看 Node 狀態(tài),再看 Pod 狀態(tài),最后看應(yīng)用日志。不要一上來就看 Pod 內(nèi)部,這樣容易忽略底層基礎(chǔ)設(shè)施問題。
先看狀態(tài),再看日志:kubectl get pod 的 STATUS 列往往已經(jīng)能給出初步判斷方向,CrashLoopBackOff 和 ImagePullBackOff 的處理路徑完全不同。
不要輕易重啟:重啟 Pod 會丟失現(xiàn)場,日志和事件信息會部分丟失。如果必須重啟,先保存關(guān)鍵信息。
生產(chǎn)操作必須備份配置:修改 Deployment、Service、ConfigMap 等資源前,先將當(dāng)前配置導(dǎo)出備份。
kubectl get deployment-n -o yaml > backup_ .yaml
高風(fēng)險(xiǎn)操作要確認(rèn)影響范圍:刪除 Pod、刪除 Namespace、修改 RBAC 權(quán)限等操作前,必須確認(rèn)影響范圍,最好在非業(yè)務(wù)高峰期執(zhí)行。
二、Pod 常見問題與排查
Pod 是 Kubernetes 最基礎(chǔ)的調(diào)度單元,Pod 啟動(dòng)失敗是最常見的問題類型。Pod 的狀態(tài)(STATUS)字段是判斷問題方向的第一線索。
2.1 CrashLoopBackOff
2.1.1 現(xiàn)象描述
Pod 處于 CrashLoopBackOff 狀態(tài),Pod 內(nèi)容器反復(fù)重啟,每次重啟間隔時(shí)間逐漸增長(通常為 10s、20s、40s、80s)。
kubectl get pod -nNAME READY STATUS RESTARTS AGE my-app-5d8f9c6b4-x7r2k 0/1 CrashLoopBackOff 3 2m15s
2.1.2 初步判斷
CrashLoopBackOff 表示容器進(jìn)程啟動(dòng)后立即退出,退出碼非零。常見原因包括:
應(yīng)用配置文件錯(cuò)誤或缺失
應(yīng)用啟動(dòng)命令或參數(shù)錯(cuò)誤
依賴服務(wù)(數(shù)據(jù)庫、Redis、API)不可達(dá)
健康檢查(livenessProbe)失敗導(dǎo)致 kubelet 殺死容器
權(quán)限不足(文件讀取、端口綁定)
動(dòng)態(tài)鏈接庫缺失
容器內(nèi)OOM(內(nèi)存不足被內(nèi)核殺掉)
2.1.3 排查步驟
第一步:查看 Pod 事件和狀態(tài)詳情
kubectl describe pod-n
重點(diǎn)關(guān)注 Events 段和 Last State 段:
Last State: Terminated Reason: OOMKilled Exit Code: 137
OOMKilled 說明容器內(nèi)存超限,被內(nèi)核殺掉。如果不是 OOMKilled,繼續(xù)往下看。
第二步:查看容器日志
如果 Pod 還在運(yùn)行(雖然 Restarting),用以下命令查看上一次容器的退出日志:
# 查看上一個(gè)終止容器的日志 kubectl logs-n --previous # 如果是多容器 Pod,指定容器名 kubectl logs -n -c --previous
如果日志顯示 "connection refused" 或 "connection timeout",說明應(yīng)用啟動(dòng)依賴的服務(wù)不可達(dá)。如果日志顯示配置文件找不到,檢查 ConfigMap 和 Secret 是否正確掛載。
第三步:檢查資源限制
kubectl get pod-n -o jsonpath='{.spec.containers[*].resources}'
如果 limits.memory 設(shè)置過低,容器啟動(dòng)后很容易被 OOMKill。重點(diǎn)關(guān)注 requests 和 limits 的關(guān)系:
resources: requests: memory:"128Mi" cpu:"100m" limits: memory:"128Mi" cpu:"200m"
requests.memory 和 limits.memory 設(shè)置相同值,意味著沒有內(nèi)存突發(fā)能力。MySQL、Java 應(yīng)用等內(nèi)存敏感型工作負(fù)載,建議 limits.memory 設(shè)為 requests.memory 的 1.5-2 倍。
第四步:檢查 Liveness Probe 配置
如果 describe 輸出中有如下事件:
Warning Unhealthy 2m ago kubelet Liveness probe failed: HTTP probe failed with statuscode: 503
說明應(yīng)用啟動(dòng)后健康檢查持續(xù)失敗,kubelet 強(qiáng)制殺死了容器。這種情況并非應(yīng)用完全崩潰,而是健康檢查配置不當(dāng)或應(yīng)用啟動(dòng)時(shí)間過長。
排查方法:
kubectl get pod-n -o jsonpath='{.spec.containers[*].livenessProbe}'
檢查 initialDelaySeconds 是否設(shè)置過短。對于 Java、Go 等編譯型語言構(gòu)建的應(yīng)用,首次加載時(shí)間較長,建議 initialDelaySeconds 不少于 30 秒,periodSeconds 不少于 10 秒。
第五步:進(jìn)入容器內(nèi)部排查
如果以上步驟還不能定位根因,進(jìn)入容器內(nèi)部進(jìn)一步排查:
kubectlexec-it-n -- /bin/sh # 查看進(jìn)程狀態(tài) ps aux # 查看打開的文件描述符 ls -la /proc/1/fd # 查看網(wǎng)絡(luò)連接狀態(tài) cat /proc/net/tcp cat /proc/net/tcp6 # 查看 DNS 配置 cat /etc/resolv.conf # 測試網(wǎng)絡(luò)連通性 ping -c 3 kubernetes.default.svc curl -v http://localhost: /health # 查看系統(tǒng)日志(如果有權(quán)限) dmesg | tail -50
2.1.4 常見修復(fù)方案
依賴服務(wù)不可達(dá):檢查依賴服務(wù)的 Endpoint 是否存在:
kubectl get endpoints-n
如果 Endpoints 為空,說明 Service 關(guān)聯(lián)的 Pod 不存在或不健康。需要檢查后端 Pod 是否正常運(yùn)行。
OOMKilled:調(diào)整資源限制或優(yōu)化應(yīng)用內(nèi)存使用:
kubectl patch deployment-n -p'{"spec":{"template":{"spec":{"containers":[{"name":" ","resources":{"limits":{"memory":"512Mi"}}}]}}}}'
配置文件錯(cuò)誤:檢查 ConfigMap 和 Secret 是否正確掛載:
kubectl get pod-n -o jsonpath='{.spec.volumes}'
掛載路徑和配置文件名是否與應(yīng)用期望的一致。
健康檢查配置不當(dāng):調(diào)整 livenessProbe 參數(shù):
livenessProbe: httpGet: path:/health port:8080 initialDelaySeconds:30 periodSeconds:10 failureThreshold:3
2.1.5 驗(yàn)證方式
修復(fù)后觀察 Pod 是否進(jìn)入 Running 狀態(tài):
watch kubectl get pod-n
確認(rèn) READY 列為 1/1(或?qū)嶋H容器數(shù)量),STATUS 為 Running,RESTARTS 不再增長。用以下命令確認(rèn)應(yīng)用功能正常:
kubectlexec-it-n -- curl -s http://localhost: /health
2.2 ImagePullBackOff
2.2.1 現(xiàn)象描述
Pod 處于 ImagePullBackOff 或 ErrImagePull 狀態(tài),無法拉取容器鏡像。
kubectl get pod -nNAME READY STATUS RESTARTS AGE my-app-5d8f9c6b4-x7r2k 0/1 ImagePullBackOff 0 5m
2.2.2 初步判斷
ImagePullBackOff 的常見原因:
鏡像名稱拼寫錯(cuò)誤或標(biāo)簽不存在
私有鏡像倉庫未配置 imagePullSecrets
鏡像倉庫認(rèn)證信息過期
鏡像倉庫網(wǎng)絡(luò)不通(防火墻、節(jié)點(diǎn) DNS 異常)
鏡像倉庫證書過期或不受信任
Node 沒有拉取該鏡像的權(quán)限(節(jié)點(diǎn)級別)
2.2.3 排查步驟
第一步:查看 Pod 事件
kubectl describe pod-n
重點(diǎn)關(guān)注 Events:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning Failed 2m ago kubelet Failed to pull image"registry.example.com/myapp:v1.2": rpc error: code = Unknown desc = Error: Not war: ... Warning Failed 2m ago kubelet Error: ErrImagePull Normal BackOff 2m ago kubelet Back-off pulling image"registry.example.com/myapp:v1.2"
錯(cuò)誤信息會直接告訴你原因:是不存在的鏡像、網(wǎng)絡(luò)不通、還是認(rèn)證失敗。
第二步:檢查鏡像名稱和標(biāo)簽
# 直接在 Node 上嘗試?yán)$R像(如果有權(quán)限) docker pull# 或者用 crictl(如果使用 containerd) crictl pull
如果鏡像標(biāo)簽不存在,會返回 "manifest unknown"。如果是網(wǎng)絡(luò)問題,會返回 timeout。
第三步:檢查 imagePullSecrets
kubectl get pod-n -o jsonpath='{.spec.imagePullSecrets}'
如果使用的是私有倉庫,但沒有配置 imagePullSecrets,Pod 無法認(rèn)證拉取鏡像。
查看現(xiàn)有的 Secret:
kubectl get secrets -n| grep -i docker
創(chuàng)建私有倉庫認(rèn)證 Secret:
kubectl create secret docker-registry--docker-server= --docker-username= --docker-password= --docker-email= -n
將 Secret 關(guān)聯(lián)到 Pod 或 ServiceAccount:
# 關(guān)聯(lián)到 Pod(每個(gè) Pod 都要加) kubectl patch deployment-n -p'{"spec":{"template":{"spec":{"imagePullSecrets":[{"name":" "}]}}}}' # 關(guān)聯(lián)到 ServiceAccount(該 SA 下的所有 Pod 都生效) kubectl patch serviceaccount default -n -p'{"imagePullSecrets":[{"name":" "}]}'
第四步:檢查節(jié)點(diǎn)級別鏡像拉取策略
節(jié)點(diǎn)上的 kubelet 日志可能提供更多信息:
# journalctl 查看 kubelet 日志(需要節(jié)點(diǎn)權(quán)限) journalctl -u kubelet --no-pager | grep -A5"ImagePullBackOff" # 如果是 containerd journalctl -u containerd --no-pager | grep -i pull
第五步:檢查鏡像倉庫網(wǎng)絡(luò)連通性
從 Pod 所在節(jié)點(diǎn)測試網(wǎng)絡(luò):
# 解析鏡像倉庫域名 nslookup registry.example.com # 測試 443 端口連通性 nc -zv registry.example.com 443 # 測試 HTTP 響應(yīng) curl -v https://registry.example.com/v2/
2.2.4 常見修復(fù)方案
鏡像不存在:使用正確標(biāo)簽重新部署,或先在本地拉取測試:
docker pulldocker tag
認(rèn)證失?。焊?imagePullSecrets 中的憑證,或重建 Secret:
kubectl delete secret-n kubectl create secret docker-registry --docker-server= --docker-username= --docker-password= -n
網(wǎng)絡(luò)不通:檢查集群網(wǎng)絡(luò)插件、DNS 服務(wù)、節(jié)點(diǎn)安全組規(guī)則。
證書問題:如果使用自簽名證書,需要在所有 Node 的/etc/docker/certs.d/目錄下配置受信任證書。
2.2.5 驗(yàn)證方式
修復(fù)后,刪除 Pod 觸發(fā)重新調(diào)度:
kubectl delete pod-n watch kubectl get pod -n
觀察 Pod 是否正常拉取鏡像并進(jìn)入 Running 狀態(tài)。
2.3 Pending 狀態(tài)
2.3.1 現(xiàn)象描述
Pod 長時(shí)間處于 Pending 狀態(tài),既不運(yùn)行也不報(bào)錯(cuò)。
kubectl get pod -nNAME READY STATUS RESTARTS AGE my-app-5d8f9c6b4-x7r2k 0/1 Pending 0 10m
2.3.2 初步判斷
Pending 狀態(tài)表示 Pod 已經(jīng)被 Kubernetes API 接受,但調(diào)度器無法將其調(diào)度到合適的 Node 上。原因可能包括:
沒有 Node 滿足 Pod 的資源請求(CPU/內(nèi)存)
沒有 Node 滿足 Pod 的調(diào)度約束(親和性、污點(diǎn)容忍)
持久卷(PVC)處于 Pending 狀態(tài),Pod 等待存儲掛載
調(diào)度器故障
節(jié)點(diǎn)存在污點(diǎn)但 Pod 沒有配置對應(yīng)的容忍
2.3.3 排查步驟
第一步:查看 Pod 事件
kubectl describe pod-n
重點(diǎn)看 Events 和 Conditions:
Conditions: Type Status PodScheduled False Reason : Unschedulable Message : 0/3 nodes are available: 1 Insufficient memory, 2 node(s) had taints that the pod didn't tolerate.
從 Message 可以直接看出原因:資源不足(Insufficient memory)或污點(diǎn)不匹配。
第二步:檢查集群資源狀況
# 查看所有節(jié)點(diǎn)狀態(tài)和資源使用 kubectl top nodes # 如果 metrics-server 未安裝,用以下命令查看資源分配情況 kubectl describe nodes | grep -A5"Allocated resources" # 查看每個(gè)節(jié)點(diǎn)的 CPU 和內(nèi)存請求對比 kubectl get pods -n-o wide
第三步:檢查污點(diǎn)(Taints)和容忍(Tolerations)
# 查看節(jié)點(diǎn)污點(diǎn)
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.spec.taints[*].key}{"
"}{end}'
# 查看 Pod 的容忍配置
kubectl get pod -n -o jsonpath='{.spec.tolerations}'
如果節(jié)點(diǎn)有node.kubernetes.io/not-ready:NoExecute污點(diǎn),而 Pod 沒有配置對應(yīng)的容忍,Pod 將無法調(diào)度。
第四步:檢查親和性配置
kubectl get pod-n -o jsonpath='{.spec.affinity}'
檢查 nodeAffinity、podAffinity、podAntiAffinity 配置是否過于嚴(yán)格。
第五步:檢查 PVC 狀態(tài)
如果 Pod 使用了持久存儲:
kubectl get pvc -nkubectl describe pod -n | grep -A10"Volumes"
如果 PVC 處于 Pending,Pod 會等待存儲綁定:
kubectl get pvc -nNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS data-myapp-0 Pending slow-storage
2.3.4 常見修復(fù)方案
資源不足:增加 Node 擴(kuò)容,或調(diào)整 Pod 資源請求:
# 水平擴(kuò)縮容 Deployment(如果使用 HPA) kubectl scale deployment-n --replicas=2 # 調(diào)整 Pod 資源請求 kubectl patch deployment -n -p'{"spec":{"template":{"spec":{"containers":[{"name":" ","resources":{"requests":{"memory":"256Mi","cpu":"200m"}}}]}}}}'
污點(diǎn)問題:給 Pod 添加匹配的容忍,或者移除節(jié)點(diǎn)污點(diǎn)(謹(jǐn)慎操作):
# 添加污點(diǎn)容忍到 Pod kubectl patch deployment-n -p'{"spec":{"template":{"spec":{"tolerations":[{"key":"node.kubernetes.io/not-ready","operator":"Exists","effect":"NoExecute","tolerationSeconds":300}]}}}}}'
PVC Pending:檢查存儲類是否存在,PVC 配置是否正確:
kubectl get storageclass kubectl describe pvc-n
如果是存儲類問題,可能需要?jiǎng)?chuàng)建 StorageClass 或等待存儲管理員提供存儲后端。
2.3.5 驗(yàn)證方式
修復(fù)后觀察 Pod 是否被調(diào)度并進(jìn)入 Running:
watch kubectl get pod-n
2.4 Terminating 狀態(tài)卡死
2.4.1 現(xiàn)象描述
Pod 長時(shí)間(超過幾分鐘)處于 Terminating 或 ContainerCreating 狀態(tài),刪除不掉。
kubectl get pod -nNAME READY STATUS RESTARTS AGE my-app-5d8f9c6b4-x7r2k 1/1 Terminating 0 30m
2.4.2 初步判斷
Pod 卡在 Terminating 通常是因?yàn)椋?/p>
Finalizers 引用了不存在的資源
存儲卷掛載未清理
容器進(jìn)程未正常退出
kubelet 與 API Server 通信異常
網(wǎng)絡(luò)插件問題導(dǎo)致掛載點(diǎn)卡死
2.4.3 排查步驟
第一步:查看 Pod 詳細(xì)狀態(tài)
kubectl get pod-n -o yaml
檢查 spec.finalizers 是否存在,spec.deletionTimestamp 是否有值。
第二步:檢查 kubelet 日志
在 Pod 所在的 Node 上查看 kubelet 日志:
journalctl -u kubelet --no-pager | grep -E"(pod|%s)"| tail -100
第三步:檢查容器進(jìn)程
# 在 Node 上查看容器進(jìn)程 crictl ps -a | grep# 查看是否有僵尸進(jìn)程 ps aux | grep -E"(zombie| )"
第四步:檢查存儲掛載
# 查看該 Pod 使用的卷 kubectl get pod-n -o jsonpath='{.spec.volumes[*].name}' # 在 Node 上查看掛載點(diǎn) mount | grep df -h | grep
2.4.4 強(qiáng)制刪除方案
如果確認(rèn) Pod 確實(shí)無法正常終止,可以強(qiáng)制刪除:
# 方式一:刪除時(shí)跳過 finalizers kubectl patch pod-n -p'{"metadata":{"finalizers":null}}'--type=merge # 方式二:設(shè)置較短的寬限期后強(qiáng)制終止 kubectl delete pod -n --grace-period=5 --force
警告:強(qiáng)制刪除前必須確認(rèn) Pod 上的業(yè)務(wù)數(shù)據(jù)已備份,強(qiáng)制刪除可能導(dǎo)致數(shù)據(jù)不一致。對于有狀態(tài)應(yīng)用,優(yōu)先調(diào)查掛載問題而不是直接強(qiáng)制刪除。
第五步:檢查 CSI 和存儲插件
如果存儲掛載卡死,查看存儲插件 Pod 的日志:
kubectl get pods -n kube-system | grep -E"csi|storage" kubectl logs -n kube-system--tail=100
2.4.5 常見修復(fù)方案
Finalizers 問題:移除 finalizers 后刪除:
kubectl patch pod-n -p'{"metadata":{"finalizers":null}}'--type=merge
掛載卡死:重啟 kubelet 或重置容器運(yùn)行時(shí)(謹(jǐn)慎操作):
# 重啟 kubelet systemctl restart kubelet # 如果是 containerd,重啟 containerd systemctl restart containerd
網(wǎng)絡(luò)插件問題:檢查 CNI 插件狀態(tài):
kubectl get pods -n kube-system | grep -E"calico|flannel|cilium|weave" kubectl logs -n kube-system--tail=50
2.4.6 驗(yàn)證方式
刪除后確認(rèn) Pod 已消失:
kubectl get pod-n
如果需要重建 Pod,確認(rèn)新 Pod 能正常啟動(dòng)。
三、Node 常見問題與排查
Node 是 Pod 運(yùn)行的基礎(chǔ)底層,Node 不可用會直接影響其上所有 Pod。
3.1 NotReady 狀態(tài)
3.1.1 現(xiàn)象描述
Node 狀態(tài)變?yōu)?NotReady,對應(yīng)的所有 Pod 不再被調(diào)度,但已運(yùn)行的 Pod 仍然維持運(yùn)行(除非使用 DaemonSet 或強(qiáng)制驅(qū)逐)。
kubectl get nodes NAME STATUS ROLES AGE VERSION node-1 Ready control-plane 90d v1.28.0 node-2 NotReady60d v1.28.0
3.1.2 初步判斷
Node 進(jìn)入 NotReady 狀態(tài),通常是因?yàn)楣?jié)點(diǎn)上的 kubelet 進(jìn)程無法與 API Server 保持心跳(默認(rèn) 40 秒內(nèi)沒有心跳視為 not ready)。常見原因:
節(jié)點(diǎn)資源耗盡(CPU/內(nèi)存/磁盤)
kubelet 進(jìn)程崩潰或 OOM
節(jié)點(diǎn)網(wǎng)絡(luò)異常
kubelet 配置錯(cuò)誤
容器運(yùn)行時(shí)故障
內(nèi)核問題(文件描述符耗盡、內(nèi)存耗盡)
3.1.3 排查步驟
第一步:在 Master 節(jié)點(diǎn)查看節(jié)點(diǎn)詳情
kubectl describe node
重點(diǎn)關(guān)注 Conditions 和 Events:
Conditions: Type Status MemoryPressure True # 內(nèi)存壓力 DiskPressure True # 磁盤壓力 PIDPressure False # 進(jìn)程數(shù)壓力 NetworkUnavailable False # 網(wǎng)絡(luò)不可用 Ready False # kubelet 未就緒
如果有條件為 True,說明節(jié)點(diǎn)存在對應(yīng)問題。
第二步:SSH 到問題節(jié)點(diǎn)上進(jìn)一步排查
# 查看 kubelet 狀態(tài) systemctl status kubelet # 查看 kubelet 日志 journalctl -u kubelet --no-pager -n 100 # 查看系統(tǒng)資源 top df -h free -h
第三步:檢查磁盤空間
磁盤空間不足是 Node NotReady 的最常見原因之一。
df -h # 檢查 Docker/容器數(shù)據(jù)目錄大小 du -sh /var/lib/docker/* du -sh /var/lib/containers/* # 檢查日志目錄大小 du -sh /var/log/*
Kubernetes 要求 Docker 的存儲驅(qū)動(dòng)分區(qū)至少有 20% 空閑空間。如果磁盤空間低于 20%,kubelet 會標(biāo)記節(jié)點(diǎn)為 DiskPressure,導(dǎo)致 Pod 驅(qū)逐和新 Pod 無法調(diào)度。
第四步:檢查內(nèi)存
free -h vmstat 1 5
內(nèi)存不足時(shí),內(nèi)核會觸發(fā) OOM Killer,可能殺掉了 kubelet 進(jìn)程。
第五步:檢查 kubelet 進(jìn)程
ps aux | grep kubelet systemctl restart kubelet journalctl -u kubelet --no-pager -n 50
3.1.4 常見修復(fù)方案
磁盤空間不足:清理磁盤空間:
# 清理舊的容器鏡像和未使用的卷 docker system prune -af # 或者如果使用 containerd crictl rmi --prune # 清理日志文件(謹(jǐn)慎操作) journalctl --vacuum-time=7d # 清理舊的 kubelet 日志 truncate -s 0 /var/log/kubelet.log
kubelet 故障:重啟 kubelet:
systemctl restart kubelet systemctl status kubelet
資源耗盡:優(yōu)化節(jié)點(diǎn)負(fù)載或擴(kuò)縮容節(jié)點(diǎn):
# 查看各 Pod 的資源使用 kubectl top pod -n--sort-by=memory
對于內(nèi)存壓力節(jié)點(diǎn),檢查是否有單個(gè) Pod 內(nèi)存使用超出 limits。
3.1.5 驗(yàn)證方式
kubectl get node
STATUS 變?yōu)?Ready 后,確認(rèn)節(jié)點(diǎn)狀態(tài)正常。等待幾分鐘后,確認(rèn)不再出現(xiàn) NotReady。
3.2 節(jié)點(diǎn)資源壓力
3.2.1 內(nèi)存壓力(MemoryPressure)
當(dāng)節(jié)點(diǎn)內(nèi)存不足時(shí),kubelet 會設(shè)置 MemoryPressure=true,并開始驅(qū)逐 Pod。驅(qū)逐策略基于 Pod 的 QoS 級別:BestEffort(無資源請求)Pod 最先被驅(qū)逐。
排查方法:
# 在節(jié)點(diǎn)上查看內(nèi)存使用 free -h cat /proc/meminfo | grep -E"MemAvailable|MemFree" # 查看哪些 Pod 內(nèi)存使用最高 kubectl top pod -A --sort-by=memory | head -20
修復(fù)方案:
將內(nèi)存密集型 Pod 分散到多個(gè)節(jié)點(diǎn)
提高內(nèi)存請求(requests.memory)以獲得更高 QoS 保障
增加節(jié)點(diǎn)內(nèi)存或擴(kuò)容
3.2.2 磁盤壓力(DiskPressure)
當(dāng)磁盤空間不足時(shí),kubelet 會拒絕調(diào)度新 Pod 到該節(jié)點(diǎn)。
排查方法:
# 查看磁盤使用
df -h
# 查看 Docker 使用的磁盤
docker system df
# 查看大文件
find /var/log-typef -size +100M -execls -lh {} ;
修復(fù)方案:
# 清理未使用的 Docker 資源
docker system prune -af --volumes
# 清理舊的日志
find /var/log-typef -name"*.log"-mtime +7 -exectruncate -s 0 {} ;
3.2.3 PID 壓力(PIDPressure)
當(dāng)節(jié)點(diǎn)進(jìn)程數(shù)接近上限時(shí),kubelet 會標(biāo)記 PIDPressure。新 Pod 如果有 PID 限制,可能無法調(diào)度。
排查方法:
# 查看 PID 使用 cat /proc/sys/kernel/pid_max ps aux | wc -l
修復(fù)方案:增加 pid_max 或降低 Pod 的 PID 限制。
3.3 節(jié)點(diǎn)網(wǎng)絡(luò)異常
當(dāng)節(jié)點(diǎn)網(wǎng)絡(luò)不可用時(shí),kubelet 無法與 API Server 通信,節(jié)點(diǎn)狀態(tài)變?yōu)?NetworkUnavailable。
排查方法:
# 在節(jié)點(diǎn)上測試網(wǎng)絡(luò) ping -c 3 8.8.8.8 ping -c 3# 查看 DNS 解析 nslookup kubernetes.default.svc # 查看網(wǎng)絡(luò)接口 ip addr ip route
四、Service 與網(wǎng)絡(luò)常見問題
Service 是 Kubernetes 服務(wù)發(fā)現(xiàn)的核心,Service 訪問異常會直接導(dǎo)致業(yè)務(wù)不可用。
4.1 Endpoints 缺失
4.1.1 現(xiàn)象描述
Service 存在但 Endpoints 為空,訪問 Service 時(shí)連接失敗。
kubectl get svc-n NAME TYPE CLUSTER-IP PORT(S) AGE my-service ClusterIP 10.96.45.123 80/TCP 30d kubectl get endpoints -n NAME ENDPOINTS AGE my-service 30d
4.1.2 初步判斷
Endpoints 為空說明沒有 Pod 被 Service 選中。常見原因:
Selector 標(biāo)簽與 Pod 標(biāo)簽不匹配
后端 Pod 不在 Running 狀態(tài)
Pod 與 Service 不在同一個(gè) Namespace
4.1.3 排查步驟
第一步:檢查 Service 的 Selector
kubectl get svc-n -o jsonpath='{.spec.selector}'
第二步:檢查后端 Pod 的標(biāo)簽
kubectl get pods -n--show-labels | grep
第三步:測試標(biāo)簽選擇
kubectl get pods -n-l" = "
如果 Service 的 Selector 和 Pod 的標(biāo)簽不匹配,Endpoints 就不會有任何條目。
4.1.4 修復(fù)方案
方案一:修改 Service Selector
kubectl patch svc-n -p'{"spec":{"selector":{"app":" "}}}'
方案二:修改 Pod 標(biāo)簽(臨時(shí)修復(fù),不推薦長期使用)
kubectl label pod-n --overwrite app=
方案三:使用 Endpoints(手動(dòng)管理)
對于不支持標(biāo)簽選擇器的場景,可以手動(dòng)創(chuàng)建 Endpoints:
apiVersion:v1 kind:Endpoints metadata: name:my-service namespace:subsets: -addresses: -ip:192.168.1.100 ports: -port:8080 protocol:TCP
4.1.5 驗(yàn)證方式
kubectl get endpoints-n
確認(rèn) Endpoints 有值后,從 Pod 內(nèi)訪問 Service 測試連通性:
kubectlexec-it-n -- curl -v http://my-service. .svc.cluster.local
4.2 DNS 解析異常
4.2.1 現(xiàn)象描述
Pod 內(nèi)無法通過 Service 名稱訪問其他服務(wù),報(bào) "could not resolve host" 錯(cuò)誤。
kubectlexec-it-n -- nslookup my-service # 或 kubectlexec-it -n -- curl http://my-service
返回 "server can't find my-service" 或 "Name or service not known"。
4.2.2 初步判斷
DNS 解析失敗的常見原因:
kube-dns 或 CoreDNS Pod 不正常
Pod 的 /etc/resolv.conf 配置錯(cuò)誤
NetworkPolicy 阻止了 DNS 流量
節(jié)點(diǎn) DNS 配置與集群 DNS 不一致
4.2.3 排查步驟
第一步:檢查 DNS Pod 狀態(tài)
kubectl get pods -n kube-system -l k8s-app=kube-dns # 或者 kubectl get pods -n kube-system -l app.kubernetes.io/name=coredns
CoreDNS Pod 應(yīng)該處于 Running 狀態(tài),READY 應(yīng)該為 1/1。
第二步:查看 DNS Pod 日志
kubectl logs -n kube-system--tail=50
如果有查詢失敗的日志,會顯示具體的查詢和錯(cuò)誤信息。
第三步:檢查 Pod 內(nèi) DNS 配置
kubectlexec-it-n -- cat /etc/resolv.conf
正常的 DNS 配置應(yīng)該類似:
nameserver 10.96.0.10 search.svc.cluster.local svc.cluster.local cluster.local options ndots:5
nameserver 地址應(yīng)該與集群的 kube-dns 服務(wù) IP 一致。
第四步:從 DNS Pod 直接測試查詢
kubectlexec-it -n kube-system-- cat /etc/resolv.conf # 使用 nslookup 或 dig(如果 Pod 內(nèi)有這些工具) kubectlexec-it -n kube-system -- nslookup kubernetes.default
第五步:檢查 NetworkPolicy
如果集群啟用了 NetworkPolicy,確認(rèn)沒有規(guī)則阻止 DNS 流量:
kubectl get networkpolicy -nkubectl describe networkpolicy -n
4.2.4 常見修復(fù)方案
DNS Pod 不正常:重啟 DNS Pod:
kubectl delete pod -n kube-system -l k8s-app=kube-dns # 或 kubectl rollout restart deployment/coredns -n kube-system
DNS Service IP 不對:檢查 kube-dns 或 CoreDNS 的 Service:
kubectl get svc kube-dns -n kube-system # 或者 kubectl get svc coredns -n kube-system
Pod DNS 配置錯(cuò)誤:檢查 kubelet 的 --cluster-dns 參數(shù)是否與 DNS Service IP 一致。
4.2.5 驗(yàn)證方式
從 Pod 內(nèi)測試 DNS 解析:
kubectlexec-it-n -- nslookup kubernetes.default kubectlexec-it -n -- nslookup my-service. .svc.cluster.local
4.3 NetworkPolicy 誤配置
NetworkPolicy 是 Kubernetes 提供的網(wǎng)絡(luò)隔離機(jī)制,配置錯(cuò)誤會導(dǎo)致 Pod 無法通信。
4.3.1 現(xiàn)象描述
Pod 無法訪問特定 Service 或被特定 Pod 訪問,NetworkPolicy 應(yīng)用后才出現(xiàn)此問題。
4.3.2 排查步驟
第一步:查看 Namespace 或 Pod 的 NetworkPolicy
kubectl get networkpolicy -nkubectl describe networkpolicy -n
第二步:分析 NetworkPolicy 規(guī)則
NetworkPolicy 是白名單機(jī)制,只有明確允許的流量才能通過。如果 Pod 需要接收來自其他 Pod 或外部的流量,必須有對應(yīng)的 Ingress 規(guī)則。
第三步:檢查 Pod 是否被正確選中
kubectl get pod-n --show-labels
4.3.3 修復(fù)方案
如果確認(rèn)是 NetworkPolicy 導(dǎo)致的問題,可以臨時(shí)刪除 Policy 驗(yàn)證:
kubectl delete networkpolicy-n
驗(yàn)證恢復(fù)后,重新編寫正確的 NetworkPolicy 規(guī)則。
NetworkPolicy 規(guī)則示例——允許同一 Namespace 內(nèi)的 Pod 訪問:
apiVersion:networking.k8s.io/v1 kind:NetworkPolicy metadata: name:allow-same-namespace namespace:spec: podSelector:{} policyTypes: -Ingress ingress: -from: -podSelector:{}
4.4 Ingress 故障
4.4.1 現(xiàn)象描述
外部無法通過 Ingress 域名訪問服務(wù),瀏覽器返回 404 或超時(shí)。
4.4.2 排查步驟
第一步:檢查 Ingress Controller Pod 狀態(tài)
kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx # 或 kubectl get pods -n kube-system | grep -E"nginx|ingress"
Ingress Controller Pod 應(yīng)該處于 Running 狀態(tài)。
第二步:檢查 Ingress 資源
kubectl get ingress -nkubectl describe ingress -n
第三步:檢查 Ingress Class
確認(rèn) Ingress 使用的是集群中已部署的 Ingress Class:
kubectl get ingressclass kubectl get ingress-n -o jsonpath='{.spec.ingressClassName}'
第四步:檢查后端 Service 和 Endpoints
kubectl get svc -nkubectl get endpoints -n
第五步:從 Ingress Controller Pod 內(nèi)測試
kubectlexec-it -n ingress-nginx-- curl -v http:// . .svc.cluster.local:
五、存儲常見問題
有狀態(tài)應(yīng)用的存儲問題往往比無狀態(tài)應(yīng)用更復(fù)雜,且風(fēng)險(xiǎn)更高。
5.1 PVC Pending
5.1.1 現(xiàn)象描述
PersistentVolumeClaim 處于 Pending 狀態(tài),Pod 無法啟動(dòng)。
kubectl get pvc -nNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS data-myapp-0 Pending standard
5.1.2 初步判斷
PVC Pending 的常見原因:
存儲類(StorageClass)不存在
存儲后端(CSI)不可用
存儲配額不足
沒有匹配的 PV(靜態(tài)供給場景)
PVC 的 accessModes 與可用的 PV 不匹配
5.1.3 排查步驟
第一步:查看 PVC 事件
kubectl describe pvc-n
Events 段會顯示具體原因:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning ProvisioningFailed 5m persistentvolume-controller Failed to provision volume: no storage class"slow-storage"
第二步:檢查 StorageClass
kubectl get storageclass
如果 PVC 引用的 StorageClass 不存在,需要?jiǎng)?chuàng)建:
apiVersion:storage.k8s.io/v1 kind:StorageClass metadata: name:slow-storage provisioner:kubernetes.io/no-provisioner volumeBindingMode:WaitForFirstConsumer
第三步:檢查 CSI 驅(qū)動(dòng)和存儲插件
kubectl get pods -n kube-system | grep -E"csi|storage" kubectl get csidriver
如果使用云廠商的 CSI(如 AWS EBS、Azure Disk、GCP PD),檢查對應(yīng)的 CSI Pod:
kubectl get pods -n kube-system | grep -E"ebs|disk|azuredisk|gcp-pd"
第四步:檢查 PVC 的 accessModes
kubectl get pvc-n -o jsonpath='{.spec.accessModes}' kubectl get pv -o jsonpath='{.spec.accessModes}'
常見 accessModes:
ReadWriteOnce:單個(gè)節(jié)點(diǎn)讀寫
ReadOnlyMany:多節(jié)點(diǎn)只讀
ReadWriteMany:多節(jié)點(diǎn)讀寫(需要特定存儲后端,如 NFS、CephFS)
5.1.4 常見修復(fù)方案
StorageClass 不存在:創(chuàng)建 StorageClass 或使用默認(rèn)存儲類:
# 將某存儲類設(shè)為默認(rèn) kubectl patch storageclass-p'{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
等待動(dòng)態(tài)供給:對于 WaitForFirstConsumer 模式的存儲類,需要調(diào)度一個(gè) Pod 觸發(fā)綁定。
CSI 問題:檢查 CSI 驅(qū)動(dòng)狀態(tài)和日志:
kubectl logs -n kube-system--tail=100
5.2 掛載失敗
5.2.1 現(xiàn)象描述
Pod 處于 ContainerCreating 狀態(tài),describe 顯示掛載卷失敗。
kubectl describe pod-n | grep -A10"Volumes"
Events 中可能顯示:
Warning FailedMount 2m ago kubelet MountVolume.SetUp failedforvolume"pvc-xxx": rpc error: code = Internal desc = could not mount disk: Format disk:exitstatus 1
5.2.2 排查步驟
第一步:在節(jié)點(diǎn)上檢查掛載狀態(tài)
# 查看當(dāng)前掛載的 PVC mount | grep pvc # 查看 kubelet 日志 journalctl -u kubelet --no-pager | grep -E"MountVolume|FailedMount"| tail -50
第二步:檢查文件系統(tǒng)
# 查看磁盤分區(qū) lsblk fdisk -l df -h
第三步:檢查 CSI 日志
kubectl logs -n kube-system--tail=100
5.2.3 修復(fù)方案
掛載失敗通常需要管理員介入??赡艿牟僮鳎?/p>
重新格式化存儲卷(數(shù)據(jù)會丟失,慎用)
檢查存儲后端健康狀態(tài)
重建 Pod(可能仍會失?。?/p>
六、資源與配額問題
6.1 OOMKilled
6.1.1 現(xiàn)象描述
Pod 被殺死,退出碼為 137(SIGKILL),Reason 為 OOMKilled。
kubectl get pod-n NAME READY STATUS RESTARTS AGE my-app-5d8f9c6b4-x7r2k 0/1 OOMKilled 1 5m
6.1.2 排查步驟
第一步:確認(rèn) OOMKilled 狀態(tài)
kubectl describe pod-n | grep -E"Last State|Reason|Exit Code"
Last State: Terminated Reason: OOMKilled Exit Code: 137
第二步:檢查 Pod 資源限制配置
kubectl get pod-n -o jsonpath='{.spec.containers[*].resources.limits.memory}'
第三步:查看節(jié)點(diǎn)內(nèi)存狀態(tài)
kubectl top nodes free -h
如果節(jié)點(diǎn)內(nèi)存本身就很緊張,Pod 很容易被 OOMKill。
第四步:分析應(yīng)用內(nèi)存使用
kubectlexec-it-n -- /bin/sh # 在容器內(nèi)查看進(jìn)程內(nèi)存使用 ps aux --sort=-%mem | head -10 cat /proc/meminfo
6.1.3 修復(fù)方案
方案一:增加內(nèi)存限制
kubectl patch deployment-n -p'{"spec":{"template":{"spec":{"containers":[{"name":" ","resources":{"limits":{"memory":"1Gi"}}}]}}}}'
方案二:優(yōu)化應(yīng)用內(nèi)存使用
Java 應(yīng)用(JVM 堆內(nèi)存設(shè)置過大):
env: -name:JAVA_OPTS value:"-Xmx512m -Xms256m"
Go 應(yīng)用(內(nèi)存限制和實(shí)際使用不匹配):
確認(rèn) Go 運(yùn)行時(shí) GOGC 參數(shù)是否合理
確認(rèn)是否有內(nèi)存泄漏
方案三:增加節(jié)點(diǎn)內(nèi)存或擴(kuò)容
6.1.4 驗(yàn)證方式
kubectl logs-n --previous kubectl top pod -n
確認(rèn) Pod 不再被 OOMKilled,內(nèi)存使用穩(wěn)定在限制值以下。
6.2 ResourceQuota 和 LimitRange
6.2.1 ResourceQuota 超限
ResourceQuota 限制 Namespace 的資源總量,超限后新 Pod 無法創(chuàng)建。
排查方法:
kubectl describe resourcequota -nkubectl get resourcequota -n -o yaml
輸出中會顯示各資源的使用量和限制量:
ResourceQuota Namespaces Status: Pods: 10/20 (80% used)
如果 pods 達(dá)到 20/20,新 Pod 無法創(chuàng)建。
修復(fù)方案:刪除不需要的 Pod 或申請?jiān)黾?ResourceQuota:
kubectl patch resourcequota-n -p'{"spec":{"hard":{"pods":"50"}}}'
6.2.2 LimitRange 超限
LimitRange 為 Namespace 內(nèi)的 Pod 設(shè)置默認(rèn)和最大的資源限制。
排查方法:
kubectl describe limitrange -n
如果 Pod 沒有設(shè)置 resources.limits,LimitRange 會設(shè)置默認(rèn)值。如果 Pod 請求的資源超過 LimitRange 的 max 值,Pod 無法創(chuàng)建。
七、認(rèn)證授權(quán)與調(diào)度問題
7.1 RBAC 權(quán)限問題
7.1.1 現(xiàn)象描述
Pod 或 ServiceAccount 無法執(zhí)行某些操作,報(bào) "forbidden" 錯(cuò)誤。
7.1.2 排查步驟
第一步:查看錯(cuò)誤信息
kubectl auth can-i--as=system :
示例:
kubectl auth can-i get pods --as=systemdefault:my-sa -n default
第二步:檢查 ServiceAccount
kubectl get sa-n -o yaml
第三步:檢查 Role/ClusterRole 和 RoleBinding/ClusterRoleBinding
kubectl get role -nkubectl get rolebinding -n kubectl describe role -n kubectl describe rolebinding -n
7.1.3 修復(fù)方案
創(chuàng)建必要的 Role:
apiVersion:rbac.authorization.k8s.io/v1 kind:Role metadata: name:my-role namespace:rules: -apiGroups:[""] resources:["pods","services"] verbs:["get","list","watch"]
關(guān)聯(lián)到 ServiceAccount:
apiVersion:rbac.authorization.k8s.io/v1 kind:RoleBinding metadata: name:my-rolebinding namespace:subjects: -kind:ServiceAccount name: namespace: roleRef: kind:Role name:my-role apiGroup:rbac.authorization.k8s.io
7.2 ServiceAccount 異常
7.2.1 現(xiàn)象描述
Pod 使用特定 ServiceAccount,但無法訪問 API Server 或其他需要認(rèn)證的資源。
7.2.2 排查步驟
第一步:檢查 Pod 使用的 ServiceAccount
kubectl get pod-n -o jsonpath='{.spec.serviceAccountName}'
第二步:確認(rèn)掛載的 token 是否有效
kubectlexec-it-n -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
第三步:用該 token 測試 API Server 訪問
kubectlexec-it-n -- sh # 在 Pod 內(nèi)測試 APISERVER=https://kubernetes.default.svc SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount TOKEN=$(cat${SERVICEACCOUNT}/token) curl -sk${APISERVER}/api --header"Authorization: Bearer${TOKEN}"
7.3 調(diào)度失敗——Taint 和 Toleration
7.3.1 現(xiàn)象描述
Pod 滿足資源條件但不滿足污點(diǎn)條件,無法調(diào)度到目標(biāo)節(jié)點(diǎn)。
7.3.2 排查步驟
第一步:查看 Pod 無法調(diào)度的事件
kubectl describe pod-n | grep -E"Taint| Tolerat"
第二步:查看節(jié)點(diǎn)污點(diǎn)
kubectl get node-o jsonpath='{.spec.taints}'
第三步:查看 Pod 容忍
kubectl get pod-n -o jsonpath='{.spec.tolerations}'
7.3.3 常見污點(diǎn)類型
node.kubernetes.io/not-ready:NoExecute——節(jié)點(diǎn)未就緒
node.kubernetes.io/unreachable:NoExecute——節(jié)點(diǎn)不可達(dá)
node.cloudprovider.com/unmanaged:NoSchedule——云節(jié)點(diǎn)初始化未完成
node-role.kubernetes.io/control-plane:NoSchedule——控制平面節(jié)點(diǎn)
7.3.4 修復(fù)方案
方案一:添加匹配的容忍
kubectl patch deployment-n -p'{"spec":{"template":{"spec":{"tolerations":[{"key":" ","operator":"Exists","effect":"NoSchedule"}]}}}}'
方案二:移除節(jié)點(diǎn)污點(diǎn)(謹(jǐn)慎操作)
kubectl taint node:NoSchedule-
八、生產(chǎn)環(huán)境排查流程
8.1 快速定位路徑
遇到問題時(shí),按以下順序快速定位:
第一步:kubectl get pods -n確認(rèn) Pod STATUS:CrashLoopBackOff / ImagePullBackOff / Pending / Terminating / Running 第二步:kubectl describe pod -n 查看 Events 和 Conditions,得出初步判斷方向 第三步:kubectl logs -n --previous 查看容器退出日志 第四步:kubectl top pod / kubectl top node 確認(rèn)資源使用情況 第五步:根據(jù)狀態(tài)類型走專項(xiàng)排查路徑(見前文各節(jié))
8.2 分層排查法
第一層:集群層
# 查看所有節(jié)點(diǎn)狀態(tài) kubectl get nodes # 查看所有命名空間 kubectl get namespaces # 查看集群級別事件 kubectl get events --all-namespaces --sort-by='.lastTimestamp'
第二層:網(wǎng)絡(luò)層
# 查看 Service 和 Endpoints kubectl get svc,endpoints -n# 查看 NetworkPolicy kubectl get networkpolicy -n # 從 Pod 內(nèi)測試網(wǎng)絡(luò)連通性 kubectlexec-it -n -- ping/curl/nslookup
第三層:存儲層
# 查看 PVC 和 PV kubectl get pvc,pv -n# 查看 StorageClass kubectl get storageclass
第四層:應(yīng)用層
# 查看 Pod 詳細(xì)配置 kubectl get pod-n -o yaml # 查看應(yīng)用日志 kubectl logs -n --tail=200 -f # 進(jìn)入容器內(nèi)部 kubectlexec-it -n -- /bin/sh
8.3 常用 kubectl 調(diào)試技巧
# 查看資源當(dāng)前狀態(tài)和期望狀態(tài)的差異 kubectl diff -f# 實(shí)時(shí)觀察資源變化 watch kubectl get pods -n # 查看資源被誰創(chuàng)建(幫助定位異常配置來源) kubectl get pod -n -o jsonpath='{.metadata.ownerReferences}' # 查看 Pod 的所有標(biāo)簽 kubectl get pod -n --show-labels # 按標(biāo)簽篩選 Pod kubectl get pods -n -l'app=myapp,tier=frontend' # 查看資源歷史修改(如果啟用了審計(jì)日志) kubectl rollouthistorydeployment -n # 回滾到上一個(gè)版本 kubectl rollout undo deployment -n
九、最佳實(shí)踐
9.1 日志與監(jiān)控
集中日志收集:確保所有 Pod 的日志統(tǒng)一收集到日志平臺(ELK、Loki、Graylog)。不要依賴kubectl logs排查生產(chǎn)問題。
# 示例:使用 Fluentd Bit 收集日志
apiVersion:v1
kind:ConfigMap
metadata:
name:fluent-bit-config
namespace:kube-system
data:
fluent-bit.conf:|
[SERVICE]
Flush 5
Log_Level info
Daemon off
[INPUT]
Name tail
Path /var/log/containers/*.log
Parser docker
Tag kube.*
[OUTPUT]
Name es
Match kube.*
Host elasticsearch.logging.svc
Port 9200
監(jiān)控告警:部署 Prometheus + Grafana 監(jiān)控集群和 Pod 資源使用。關(guān)鍵告警:
Node NotReady / DiskPressure / MemoryPressure
Pod CrashLoopBackOff / OOMKilled
PVC Pending 超過 5 分鐘
Pod 重啟次數(shù)超過閾值
CPU/內(nèi)存使用率持續(xù)高于 80%
健康檢查配置:合理配置 livenessProbe 和 readinessProbe:
livenessProbe: httpGet: path:/healthz port:8080 initialDelaySeconds:30 periodSeconds:10 failureThreshold:3 readinessProbe: httpGet: path:/ready port:8080 initialDelaySeconds:5 periodSeconds:5 failureThreshold:3
livenessProbe 用于判斷容器是否需要重啟,readinessProbe 用于判斷 Pod 是否應(yīng)該接收流量。如果 livenessProbe 配置過短,頻繁重啟會導(dǎo)致業(yè)務(wù)中斷。
9.2 資源配額設(shè)計(jì)
命名空間級別資源約束:為每個(gè)命名空間設(shè)置 ResourceQuota 和 LimitRange。
apiVersion:v1 kind:ResourceQuota metadata: name:default-quota namespace:spec: hard: requests.cpu:"10" requests.memory:20Gi limits.cpu:"20" limits.memory:40Gi pods:"50"
Pod 資源請求與限制:為每個(gè)容器設(shè)置合理的 requests 和 limits。
requests:調(diào)度依據(jù),保證 Pod 調(diào)度的公平性
limits:資源上限,防止單個(gè)容器耗盡節(jié)點(diǎn)資源
resources: requests: memory:"256Mi" cpu:"100m" limits: memory:"512Mi" cpu:"500m"
LimitRange 默認(rèn)值:如果某些 Pod 沒有設(shè)置資源限制,LimitRange 提供默認(rèn)值:
apiVersion:v1 kind:LimitRange metadata: name:default-limit namespace:spec: limits: -type:Container default: memory:512Mi cpu:200m defaultRequest: memory:256Mi cpu:100m max: memory:2Gi cpu:"1"
9.3 災(zāi)備與回滾
資源配置版本管理:所有 Kubernetes 資源配置都應(yīng)該存儲在 Git 倉庫中(GitOps 實(shí)踐)。
Deployment 回滾:
# 查看歷史版本 kubectl rollouthistorydeployment-n # 回滾到上一個(gè)版本 kubectl rollout undo deployment -n # 回滾到指定版本 kubectl rollout undo deployment -n --to-revision=
StatefulSet 的滾動(dòng)更新策略:StatefulSet 的更新需要謹(jǐn)慎處理,有序刪除、有序創(chuàng)建:
spec: updateStrategy: type:RollingUpdate rollingUpdate: maxUnavailable:1 maxSurge:1
數(shù)據(jù)備份:有狀態(tài)應(yīng)用必須配置定期備份策略。MySQL、Redis、MongoDB 等數(shù)據(jù)庫的備份不應(yīng)依賴 Kubernetes 自身,應(yīng)使用外部備份工具。
9.4 生產(chǎn)操作安全規(guī)范
操作前必查清單:
影響范圍確認(rèn):操作會影響哪些 Pod、哪些用戶、哪些業(yè)務(wù)?
配置備份:kubectl get
回滾方案:準(zhǔn)備好回滾命令
執(zhí)行窗口:生產(chǎn)環(huán)境變更在業(yè)務(wù)低峰期執(zhí)行
通知相關(guān)方:提前通知業(yè)務(wù)方和值班人員
審批流程:符合企業(yè)變更管理流程
高風(fēng)險(xiǎn)操作:
刪除 Namespace(不可逆)
修改 RBAC 權(quán)限(可能導(dǎo)致集群管理權(quán)限丟失)
刪除 StorageClass(可能導(dǎo)致 PV 無法恢復(fù))
修改 etcd 數(shù)據(jù)(可能導(dǎo)致集群不可用)
大規(guī)模刪除 Pod(可能導(dǎo)致服務(wù)中斷)
驗(yàn)證流程:
操作前:確認(rèn)服務(wù)當(dāng)前狀態(tài)、基線指標(biāo)
操作中:觀察 Pod 狀態(tài)變化、錯(cuò)誤日志
操作后:確認(rèn)服務(wù)恢復(fù)、指標(biāo)正常、業(yè)務(wù)連通
十、總結(jié)
Kubernetes 生產(chǎn)環(huán)境的故障排查,核心在于系統(tǒng)化思維和分層定位。從 Node 狀態(tài)到 Pod 狀態(tài),從網(wǎng)絡(luò)連通性到存儲掛載,從資源配額到權(quán)限配置,每一層都有可能出現(xiàn)故障點(diǎn)。
常見問題的快速定位表:
| 現(xiàn)象 | 第一步排查命令 | 常見原因 |
|---|---|---|
| CrashLoopBackOff | kubectl logs --previous | 應(yīng)用配置錯(cuò)誤、依賴不可達(dá)、OOM |
| ImagePullBackOff | kubectl describe pod 事件 | 鏡像不存在、認(rèn)證失敗、網(wǎng)絡(luò)不通 |
| Pending | kubectl describe pod 事件 | 資源不足、污點(diǎn)不匹配、PVC Pending |
| Terminating 卡死 | kubectl get pod -o yaml finalizers | 掛載卡死、Finalizers 引用缺失 |
| NotReady | kubectl describe node Conditions | 磁盤滿、內(nèi)存滿、網(wǎng)絡(luò)異常 |
| Endpoints 為空 | kubectl get svc -o jsonpath Selector | 標(biāo)簽不匹配、Pod 未運(yùn)行 |
| DNS 解析失敗 | kubectl logs -n kube-system coredns | CoreDNS 異常、NetworkPolicy 阻斷 |
| PVC Pending | kubectl describe pvc 事件 | StorageClass 不存在、CSI 異常 |
最重要的幾條經(jīng)驗(yàn):
永遠(yuǎn)先看狀態(tài)和事件,再看日志。kubectl describe 的輸出往往已經(jīng)足夠定位方向。
生產(chǎn)操作前必須備份配置,保留回滾能力。Kubernetes 的聲明式 API 使得配置回滾非常容易。
不要輕易重啟 Pod 或 Node,這會丟失現(xiàn)場。優(yōu)先調(diào)查根因。
資源配置要合理——requests 保證調(diào)度公平性,limits 防止資源耗盡,兩者缺一不可。
監(jiān)控和日志是運(yùn)維的根基。沒有監(jiān)控,故障就不知道;沒有日志,排查就無從下手。
故障排查能力是運(yùn)維工程師最核心的技能之一。排查得快不快、準(zhǔn)不準(zhǔn),取決于對 Kubernetes 各組件協(xié)作關(guān)系理解的深度。希望本文提供的排查路徑、關(guān)鍵命令和修復(fù)方案,能夠幫助初中級運(yùn)維工程師在實(shí)際工作中快速定位問題、解決問題,在生產(chǎn)環(huán)境中更加從容。
-
集群
+關(guān)注
關(guān)注
0文章
157瀏覽量
17697 -
容器
+關(guān)注
關(guān)注
0文章
540瀏覽量
23044 -
kubernetes
+關(guān)注
關(guān)注
0文章
280瀏覽量
9540
原文標(biāo)題:吃透 K8s 排障:生產(chǎn)常見問題 + 實(shí)用排查命令匯總
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
Kubernetes生產(chǎn)環(huán)境常見問題與排查命令總結(jié)
評論