引言
生產(chǎn)環(huán)境的Kubernetes集群運行久了,各種奇奇怪怪的問題都會冒出來。本文挑選10個日常運維中最高頻的故障場景,從現(xiàn)象到根因到修復,手把手過一遍。每個案例都給出完整的排查路徑、關(guān)鍵命令和驗證方法,照著做能解決大部分常見問題。
集群環(huán)境說明:本文以Kubernetes 1.28版本為例,節(jié)點系統(tǒng)為CentOS 7.9或Ubuntu 22.04,容器運行時為containerd 1.7.x。多節(jié)點集群場景,包含3個控制面節(jié)點和若干工作節(jié)點。
問題一:Pod一直處于Pending狀態(tài)
問題背景
Pod創(chuàng)建后一直卡在Pending狀態(tài),既不調(diào)度到節(jié)點,也不報錯。這種情況在生產(chǎn)環(huán)境中很常見,新手往往不知道該從哪里入手。
適用場景
新建應用部署后發(fā)現(xiàn)Pod起不來
節(jié)點擴容后Pod仍然無法調(diào)度
資源緊張時應用無法重新調(diào)度
核心知識點
Pending狀態(tài)的Pod意味著調(diào)度器無法將它分配到任何節(jié)點。常見原因有三類:資源不足、親和性/污點限制、存儲卷掛載等待。
實戰(zhàn)步驟
第一步:查看Pod狀態(tài)詳情
kubectl get pod -n-o wide kubectl describe pod -n
describe輸出中的Events部分最關(guān)鍵,看最后幾行事件記錄。
典型現(xiàn)象示例:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 3m default-scheduler 0/5 nodes are available: 1 Insufficient cpu, 3 node(s) had taints that the pod didn't tolerate, 1 resource allocation disabled.
第二步:檢查集群資源狀態(tài)
kubectl top nodes kubectl describe node
查看每個節(jié)點的CPU、內(nèi)存、存儲使用情況。特別注意Allocatable字段,它才是實際可調(diào)度的資源量。
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.allocatable.cpu}{" CPU "}{.status.allocatable.memory}{" "}{.status.conditions[?(@.type=="Ready")].status}{"
"}{end}'
第三步:檢查污點和容忍
kubectl get node -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
如果節(jié)點有污點,Pod沒有對應的容忍配置就不會調(diào)度。
第四步:檢查存儲類和PVC狀態(tài)
kubectl get pvc -nkubectl describe pvc
掛載遲遲不能完成的PVC會阻塞Pod調(diào)度。
根因定位與修復
原因一:資源不足
CPU或內(nèi)存不夠時,調(diào)度器找不到滿足條件的節(jié)點。
修復方案:要么擴容節(jié)點,要么降低Pod資源請求值,要么清理現(xiàn)有低優(yōu)先級Pod。
resources: requests: memory:"128Mi" cpu:"100m" limits: memory:"256Mi" cpu:"200m"
原因二:節(jié)點污點限制
kubectl taint nodekey=value:NoSchedule-
臨時去掉污點讓Pod調(diào)度進去,但生產(chǎn)環(huán)境建議通過添加容忍來解決問題。
tolerations: -key:"key" operator:"Exists" effect:"NoSchedule"
原因三:PVC掛載超時
檢查StorageClass是否存在、PV是否正確綁定、存儲后端是否正常。
驗證方式
kubectl get pod -n# 狀態(tài)變?yōu)?Running 表示調(diào)度成功 # 繼續(xù)觀察是否進入 Running 狀態(tài) kubectl logs -n --previous
風險提醒
修改污點會影響其他Pod的調(diào)度行為。移除污點前確認該節(jié)點是否專門用于特定 workloads。
回滾方案
如果是通過修改Pod YAML解決的問題,直接重新apply原配置即可。如果涉及節(jié)點污點修改,用taint命令恢復或打標簽替代。
問題二:Pod一直處于CrashLoopBackOff狀態(tài)
問題背景
Pod啟動后立刻崩潰,反復重啟,始終無法正常運行。這是線上最常見的Pod故障之一,往往意味著應用本身有問題。
適用場景
應用剛部署就報錯
更新版本后突然無法啟動
節(jié)點異常后應用無法恢復
核心知識點
CrashLoopBackOff是Kubernetes報告容器反復崩潰的狀態(tài)。容器退出碼非0,kubelet會按指數(shù)退避策略重啟,每次等待時間翻倍:10秒、20秒、40秒...最長5分鐘。
實戰(zhàn)步驟
第一步:獲取容器退出碼和重啟原因
kubectl get pod -n-o jsonpath='{.status.containerStatuses[*]}{" "}'
重點關(guān)注exitCode、lastState、restartCount字段。
kubectl describe pod -n| grep -A 20"Last State"
第二步:查看應用日志
kubectl logs -n--previous
--previous參數(shù)拿的是上次崩潰前的容器日志,非常關(guān)鍵。
第三步:進入容器內(nèi)部排查
kubectlexec-it -n-- /bin/sh
如果Pod內(nèi)只有一個容器,可以省略-c參數(shù)。
第四步:檢查容器啟動命令和環(huán)境變量
kubectl get pod -n-o jsonpath='{.spec.containers[*].command}' kubectl get pod -n -o jsonpath='{.spec.containers[*].env}'
第五步:檢查健康檢查配置
kubectl describe pod -n| grep -A 5"Liveness" kubectl describe pod -n | grep -A 5"Readiness"
探針失敗次數(shù)過多也會導致容器被認為不健康。
根因定位與修復
原因一:應用啟動命令錯誤
檢查command和args是否正確,鏡像ENTRYPOINT和CMD是否有沖突。
command:["/bin/sh","-c"] args:["nodeapp.js&&sleepinfinity"]
原因二:依賴服務不可達
應用啟動時需要連接數(shù)據(jù)庫、Redis等,如果連接失敗會直接退出。
# 在Pod內(nèi)測試連接 kubectlexec-it -n-- nc -zv 3306 kubectlexec-it -n -- nslookup
原因三:配置文件錯誤或缺失
掛載的ConfigMap或Secret沒有正確創(chuàng)建。
kubectl get configmap -nkubectl get secret -n
原因四:權(quán)限問題
容器內(nèi)進程沒有足夠權(quán)限讀寫掛載的目錄。
kubectlexec-it -n-- ls -la /data kubectlexec-it -n -- id
原因五:健康檢查過早殺死進程
startupProbe配置不當會導致容器還在啟動中就被殺掉。
startupProbe: httpGet: path:/healthz port:8080 failureThreshold:30 periodSeconds:10
驗證方式
# 觀察重啟次數(shù)是否歸零 kubectl get pod -n-w # 確認容器運行穩(wěn)定 kubectlexec-it -n -- ps aux
風險提醒
容器內(nèi)的數(shù)據(jù)丟失無法恢復(無持久化存儲時)。修復前先確認應用是否支持多次重啟不丟數(shù)據(jù)。
回滾方案
如果是版本更新導致的問題,回滾鏡像版本:
kubectl rollout undo deployment-n kubectl rollout status deployment -n
問題三:Pod無法通過Service訪問
問題背景
Pod之間無法通過Service名稱通信,curl或wget都超時。應用明明運行正常,但就是連不上。
適用場景
應用間調(diào)用失敗
Ingress進來流量無法到達后端Pod
集群內(nèi)部DNS解析異常
核心知識點
Service訪問涉及三個環(huán)節(jié):DNS解析、kube-proxy轉(zhuǎn)發(fā)、Pod監(jiān)聽。任何一個環(huán)節(jié)出問題都會導致訪問失敗。
實戰(zhàn)步驟
第一步:確認Pod和Service都存在
kubectl get pod -n-o wide | grep kubectl get svc -n | grep
第二步:從同命名空間其他Pod測試訪問
kubectlexec-it -n-- curl -v http:// : /
第三步:檢查Endpoints是否正常
kubectl get endpoints -n
Endpoints為空說明selector沒有匹配到任何Pod。
kubectl describe svc -n
第四步:檢查kube-proxy是否正常運行
kubectl get pod -n kube-system -o wide | grep kube-proxy kubectl logs -n kube-system--tail=50
第五步:測試ClusterIP連通性
kubectlexec-it -n-- curl -v http:// : /
第六步:檢查iptables規(guī)則
kubectlexec-it-- iptables -L -t nat | grep
根因定位與修復
原因一:Endpoints為空
selector配置錯誤或匹配到的Pod還沒ready。
spec: selector: app:my-app# 檢查標簽是否匹配
修復:確認Pod標簽和Service selector一致。
kubectl get pod -n--show-labels | grep
原因二:kube-proxy異常
kube-proxy崩潰或watch資源出錯。
systemctl status kube-proxy journalctl -u kube-proxy -n 50
重啟kube-proxy:
kubectl delete pod -n kube-system
原因三:DNS解析失敗
kubectlexec-it -n-- nslookup kubectlexec-it -n -- cat /etc/resolv.conf
CoreDNS相關(guān)問題:
kubectl get pod -n kube-system -o wide | grep dns kubectl logs -n kube-system--tail=50
原因四:Pod網(wǎng)絡(luò)策略阻止
kubectl get networkpolicy -nkubectl describe networkpolicy
驗證方式
# 多次測試確認穩(wěn)定
foriin{1..10};dokubectlexec-it -n -- curl -s http://:/healthz &&echo" OK"||echo" FAIL";done
# 檢查sessionAffinity是否生效
kubectlexec-it -n -- ss -s
風險提醒
修改kube-proxy重啟會影響所有Service流量,生產(chǎn)環(huán)境滾動操作。NetworkPolicy配置錯誤可能阻斷所有流量。
回滾方案
kube-proxy是DaemonSet,不支持rollout undo。如果需要回滾配置,手動恢復之前的ConfigMap或重啟kube-proxy Pod:
# 重啟kube-proxy Pod觸發(fā)配置重新加載 kubectl delete pod -n kube-system -l k8s-app=kube-proxy # 或者恢復之前的網(wǎng)絡(luò)策略yaml kubectl apply -f
問題四:鏡像拉取失敗
問題背景
Pod調(diào)度到節(jié)點后,鏡像下載失敗,容器始終無法啟動。這種問題在配置了私有鏡像倉庫但沒做鏡像拉取授權(quán)時特別常見。
適用場景
部署新應用時報錯ImagePullBackOff
節(jié)點重啟后原地重建Pod失敗
更換鏡像倉庫地址后無法拉取
核心知識點
ImagePullBackOff表示kubelet反復嘗試拉取鏡像但持續(xù)失敗。常見原因包括:鏡像不存在、認證失敗、網(wǎng)絡(luò)不通、registry白名單限制。
實戰(zhàn)步驟
第一步:查看Pod事件
kubectl describe pod -n| grep -A 10"Events"
典型錯誤信息:
Failed to pull image"registry.example.com/app:latest": rpc error: code = Unknown desc = Error: Not Found
Failed to pull image"registry.example.com/app:latest": rpc error: code = Unknown desc = unauthorized: authentication required
Failed to pull image"registry.example.com/app:latest": rpc error: code = Unknown desc = http: server gave HTTP response to HTTPS client
第二步:確認鏡像確實存在
# 在有網(wǎng)絡(luò)權(quán)限的節(jié)點上直接測試 ctr -n k8s.io images ls | grepcrictl images | grep
第三步:檢查鏡像倉庫認證信息
kubectl get secret -n| grep docker kubectl describe secret
Secret類型必須是kubernetes.io/dockerconfigjson。
第四步:檢查節(jié)點hosts和證書
cat /etc/hosts | grepls -la /etc/docker/certs.d/ /
第五步:在節(jié)點上手動拉取測試
crictl pull/ : ctr -n k8s.io images pull / :
根因定位與修復
原因一:鏡像不存在或tag錯誤
# 確認正確鏡像地址 docker pull/ :
修復:更正鏡像地址或tag。
原因二:認證憑據(jù)錯誤
創(chuàng)建或更新Secret:
kubectl create secret docker-registry--docker-server= --docker-username= --docker-password= --docker-email= -n
PodSpec引用Secret:
spec: imagePullSecrets: -name:
原因三:私有倉庫證書問題
配置私有倉庫CA證書。對于containerd 1.7.x版本,需要在/etc/containerd/config.toml中配置:
# 編輯containerd配置 vi /etc/containerd/config.toml # 在 [plugins."io.containerd.grpc.v1.cri".registry] 下添加: [plugins."io.containerd.grpc.v1.cri".registry.configs."".tls] ca_file ="/etc/ssl/certs/ .crt"
或者在節(jié)點上直接安裝CA證書(適用于所有容器運行時):
# Debian/Ubuntu cp ca.crt /usr/local/share/ca-certificates/.crt update-ca-certificates # RHEL/CentOS cp ca.crt /etc/pki/ca-trust/source/anchors/ .crt update-ca-trust extract
配置修改后重啟containerd:
systemctl restart containerd
原因四:網(wǎng)絡(luò)訪問限制
檢查節(jié)點能否訪問鏡像倉庫:
curl -I https:///v2/
驗證方式
# 刪除Pod觸發(fā)重新調(diào)度 kubectl delete pod -n# 觀察鏡像拉取是否成功 kubectl get events -n --sort-by='.lastTimestamp'| tail -20
風險提醒
刪除Pod會影響業(yè)務連續(xù)性,確認有足夠副本數(shù)再操作。私密憑據(jù)更新需要同步到所有使用它的命名空間。
回滾方案
恢復到之前可用的鏡像版本:
spec: containers: -name:app image:/ :
問題五:Node NotReady
問題背景
集群中某個節(jié)點狀態(tài)變成NotReady,kubelet無法正常匯報節(jié)點狀態(tài)。該節(jié)點上的Pod不會調(diào)度新實例,但現(xiàn)有Pod是否受影響取決于情況。
適用場景
節(jié)點異常后無法管理
節(jié)點上應用無響應
集群容量異常減少
核心知識點
節(jié)點進入NotReady狀態(tài)是因為kubelet在40秒內(nèi)沒有向API Server發(fā)送心跳。常見原因包括:kubelet進程掛了、系統(tǒng)資源耗盡、網(wǎng)絡(luò)不通、證書過期。
實戰(zhàn)步驟
第一步:確認節(jié)點狀態(tài)
kubectl get nodes kubectl describe node
kubectl get node-o jsonpath='{.status.conditions[*]}'
第二步:登錄節(jié)點檢查kubelet狀態(tài)
systemctl status kubelet journalctl -u kubelet -n 50 --no-pager
第三步:檢查節(jié)點資源
free -h df -h top -bn1 | head -20
第四步:檢查容器運行時
systemctl status containerd # 或 docker systemctl status kubelet
第五步:檢查證書是否過期
openssl x509 -in/var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates openssl x509 -in/var/lib/kubelet/pki/kubelet-server-current.pem -noout -dates
根因定位與修復
原因一:kubelet進程崩潰或被殺死
systemctl restart kubelet systemctlenablekubelet
原因二:系統(tǒng)內(nèi)存或磁盤耗盡
清理磁盤:
# 清理舊日志 journalctl --vacuum-size=500M # 清理containerd未使用鏡像 crictl rmi $(crictl images -q) # 清理docker未使用鏡像(如果使用docker運行時) docker system prune -af # 清理containerd舊鏡像 # 先查看有哪些未使用的鏡像 ctr -n k8s.io images ls -q | head -20 # 手動刪除不需要的鏡像(不要刪除正在使用的) ctr -n k8s.io images rm# 清理/var/lib/kubelet目錄下的臨時文件 find /var/lib/kubelet -name"*.tmp"-delete
增加節(jié)點資源或調(diào)度更多Pod出去。
原因三:kubelet證書過期
自動輪轉(zhuǎn)失敗時需要手動更新。在故障節(jié)點上執(zhí)行:
# 刪除舊的kubelet證書和kubeconfig rm -rf /var/lib/kubelet/pki/ rm -f /var/lib/kubelet/kubelet.conf # 重啟kubelet,kubelet會自動向API Server申請新證書 systemctl restart kubelet # 確認證書已重新申請 ls -la /var/lib/kubelet/pki/ openssl x509 -in/var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
原因四:網(wǎng)絡(luò)不通
pingtelnet 6443 curl -k https:// :6443/healthz
檢查節(jié)點防火墻:
systemctl status firewalld iptables -L -n | grep 6443
原因五:containerd或docker異常
systemctl restart containerd # 或 systemctl restart docker
驗證方式
kubectl get node# 狀態(tài)變?yōu)?Ready # 確認節(jié)點可調(diào)度 kubectl describe node | grep -A 5"Allocatable" # 確認Pod可以調(diào)度到該節(jié)點 kubectl describe node | grep -A 5"Taints"
風險提醒
重啟kubelet會導致節(jié)點上Pod短暫網(wǎng)絡(luò)中斷。驅(qū)逐Pod會影響運行中的業(yè)務。操作前確認集群有足夠冗余。
回滾方案
如果問題無法快速恢復,先隔離節(jié)點防止Pod繼續(xù)調(diào)度:
kubectl cordonkubectl drain --ignore-daemonsets --delete-emptydir-data
等節(jié)點恢復后un cordon:
kubectl uncordon
問題六:存儲卷掛載異常
問題背景
Pod掛載的PVC一直處于Pending狀態(tài),或者Pod啟動后無法正常讀寫數(shù)據(jù)目錄。存儲問題是生產(chǎn)環(huán)境中后果最嚴重的故障之一。
適用場景
數(shù)據(jù)庫Pod無法啟動
有狀態(tài)應用部署失敗
日志寫入報錯
核心知識點
Kubernetes存儲涉及StorageClass、PersistentVolumeClaim、PersistentVolume、CSI驅(qū)動四個組件。任何一個環(huán)節(jié)斷裂都會導致掛載失敗。
實戰(zhàn)步驟
第一步:檢查PVC狀態(tài)
kubectl get pvc -nkubectl describe pvc -n
Pending狀態(tài)的PVC說明還沒有找到合適的PV。
第二步:檢查PV狀態(tài)
kubectl get pv kubectl describe pv
第三步:檢查StorageClass
kubectl get storageclass kubectl describe storageclass
第四步:檢查CSI驅(qū)動狀態(tài)
kubectl get pod -n kube-system | grep csi kubectl logs -n kube-system--tail=50
第五步:檢查節(jié)點掛載情況
# 在Pod所在節(jié)點執(zhí)行 mount | grepdf -h | grep
根因定位與修復
原因一:StorageClass不存在
# 確認集群有哪些StorageClass kubectl get storageclass # 創(chuàng)建必要的StorageClass kubectl apply -f - <
原因二:PVC綁定到錯誤的PV
# 檢查綁定狀態(tài) kubectl get pvc -n-o wide # 刪除重建PVC(數(shù)據(jù)會丟失) kubectl delete pvc -n
原因三:CSI驅(qū)動問題
# 重啟CSI驅(qū)動 kubectl delete pod -n kube-system# 檢查驅(qū)動版本兼容性 kubectl get csidrivers
原因四:節(jié)點無法訪問存儲后端
NFS、Ceph、GlusterFS等網(wǎng)絡(luò)存儲需要節(jié)點能連通。
showmount -eceph -s
原因五:權(quán)限問題
# 檢查FSGroup配置 kubectl get pod -n-o jsonpath='{.spec.securityContext.fsGroup}' kubectl get pod -n -o jsonpath='{.spec.initContainers[*].securityContext}'
修改Pod安全上下文:
spec: securityContext: fsGroup:2000 runAsUser:1000
驗證方式
# 進入Pod測試讀寫 kubectlexec-it -n-- sh -c"echo test > /data/test.txt && cat /data/test.txt" # 確認掛載點正常 kubectlexec-it -n -- df -h | grep /data # 檢查文件權(quán)限 kubectlexec-it -n -- ls -la /data
風險提醒
刪除PVC會永久丟失數(shù)據(jù)。修改存儲類不會影響已綁定的PV/VC??绻?jié)點存儲遷移需要先備份數(shù)據(jù)。
回滾方案
# 如果使用了錯誤的StorageClass,重新創(chuàng)建PVC指定正確的storageClassName # 如果是權(quán)限問題,恢復安全上下文配置 # 如果是CSI問題,回滾CSI驅(qū)動版本
問題七:資源配額耗盡導致Pod被驅(qū)逐
問題背景
集群或命名空間的ResourceQuota/LimitRange限制被觸發(fā),Pod被強制終止。應用無預警崩潰,影響業(yè)務可用性。
適用場景
多個團隊共用集群時資源競爭
資源限制配置過于嚴格
應用內(nèi)存泄漏逐漸逼近限制
核心知識點
Kubernetes通過ResourceQuota限制命名空間總資源、LimitRange限制單個Pod/容器的資源請求。超出限制會觸發(fā)Evicted狀態(tài)。
實戰(zhàn)步驟
第一步:確認Pod被驅(qū)逐
kubectl get pod -n| grep Evicted kubectl describe pod -n
第二步:檢查命名空間資源配額
kubectl get resourcequota -nkubectl describe resourcequota -n kubectl get limitrange -nkubectl describe limitrange -n
第三步:檢查實際資源使用
kubectl top pod -nkubectl top nodes
第四步:分析配額消耗
# 計算當前命名空間總資源 kubectl api-resources --verbs=list --namespaced -o wide | grep -i quota
根因定位與修復
原因一:內(nèi)存Limit不足
Pod實際使用超過limits設(shè)置,被OOMKilled。
resources: requests: memory:"512Mi" limits: memory:"1Gi"
增加limits或優(yōu)化應用內(nèi)存使用。
原因二:命名空間總CPU配額耗盡
檢查當前ResourceQuota:
kubectl get resourcequota -n-o yaml
增加ResourceQuota:
apiVersion:v1 kind:ResourceQuota metadata: name:increase-quota spec: hard: requests.cpu:"20" requests.memory:40Gi limits.cpu:"40" limits.memory:80Gi
原因三:PVC數(shù)量超過限制
kubectl get pvc -n| wc -l
刪除不需要的PVC:
kubectl delete pvc-n
原因四:Pod數(shù)量超過限制
apiVersion:v1 kind:ResourceQuota metadata: name:pod-quota spec: hard: pods:"100"
驗證方式
# 持續(xù)監(jiān)控資源使用 watch -n 5'kubectl top pod -n' # 確認Pod不再被驅(qū)逐 kubectl get events -n --sort-by='.lastTimestamp'| grep -i evict
風險提醒
增加ResourceQuota需要集群層面有足夠資源。刪除PVC會丟失數(shù)據(jù)。修改LimitRange只影響新建的Pod。
回滾方案
# 恢復ResourceQuota到之前的值 kubectl apply -f# 如果是單個Pod問題,恢復limits配置 kubectl patch deployment -n --typemerge -p'{"spec":{"template":{"spec":{"containers":[{"name":"app","resources":{"limits":{"memory":"512Mi"}}}]}}}}'
問題八:etcd集群故障
問題背景
etcd是Kubernetes的核心數(shù)據(jù)存儲,集群狀態(tài)全部保存在其中。etcd故障會導致API Server不可用,整個集群基本癱瘓。
適用場景
控制面節(jié)點異常
集群無法響應任何kubectl命令
證書驗證失敗
核心知識點
生產(chǎn)環(huán)境etcd應該至少3節(jié)點集群,容忍1節(jié)點故障。數(shù)據(jù)損壞、磁盤滿、證書過期、網(wǎng)絡(luò)分區(qū)是最常見的故障原因。
實戰(zhàn)步驟
第一步:檢查etcd服務狀態(tài)
systemctl status etcd journalctl -u etcd -n 50 --no-pager
第二步:檢查etcd健康狀態(tài)
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key endpoint health
第三步:檢查etcd成員狀態(tài)
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key member list -w table
第四步:檢查磁盤空間
df -h /var/lib/etcd du -sh /var/lib/etcd/*
第五步:檢查證書
openssl x509 -in/etc/kubernetes/pki/etcd/server.crt -noout -dates openssl x509 -in/etc/kubernetes/pki/etcd/peer.crt -noout -dates
根因定位與修復
原因一:磁盤空間不足
etcd數(shù)據(jù)目錄所在磁盤占滿會導致寫入失敗,集群不可寫。
清理方案:
# 先檢查wal目錄大小 du -sh /var/lib/etcd/member/wal # 執(zhí)行defrag(不會丟數(shù)據(jù)) ETCDCTL_API=3 etcdctl defrag --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key # 清理舊快照 find /var/lib/etcd -name"*.snap"-mtime +7 -delete
如果磁盤確實滿了,需要擴容或清理其他文件。
原因二:etcd啟動失敗
# 查看詳細錯誤 journalctl -u etcd -n 100 | grep -i error # 檢查配置文件 cat /etc/kubernetes/etcd.conf
原因三:節(jié)點證書過期
檢查證書過期時間:
# 檢查kubelet客戶端證書 openssl x509 -in/var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates # 檢查kubelet服務器證書 openssl x509 -in/var/lib/kubelet/pki/kubelet-server-current.pem -noout -dates # 檢查API Server訪問證書(控制面節(jié)點) openssl x509 -in/etc/kubernetes/pki/apiserver.crt -noout -dates
如果證書已過期,在控制面節(jié)點上使用kubeadm重新生成。首先備份舊證書:
# 備份舊證書 mkdir -p /backup/pki-$(date +%Y%m%d) cp -r /etc/kubernetes/pki/* /backup/pki-$(date +%Y%m%d)/
創(chuàng)建kubeadm配置文件指定證書有效期:
cat > /tmp/kubeadm-config.yaml <peerCertSANs: - <控制面節(jié)點IP> certificates: validityPeriod: 87600h # 10年 EOF
重新生成控制面證書:
# 重新生成apiserver證書 kubeadm init phase certs apiserver --config=/tmp/kubeadm-config.yaml # 重新生成etcd證書 kubeadm init phase certs etcd-server --config=/tmp/kubeadm-config.yaml kubeadm init phase certs etcd-peer --config=/tmp/kubeadm-config.yaml kubeadm init phase certs etcd-client --config=/tmp/kubeadm-config.yaml # 重啟API Server systemctl restart kubelet
確認證書時間已更新:
openssl x509 -in/etc/kubernetes/pki/apiserver.crt -noout -dates openssl x509 -in/etc/kubernetes/pki/etcd/server.crt -noout -dates
原因四:單個節(jié)點故障恢復
先確認故障節(jié)點的member ID:
# 查看所有成員 ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key member list
從集群移除故障節(jié)點(用實際member ID替換
):
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key member remove# 重新添回節(jié)點(如果節(jié)點恢復) ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key member add <節(jié)點名稱> --peer-urls=https://<節(jié)點IP>:2380 # 重啟etcd服務 systemctl restart etcd
驗證方式
# 確認所有節(jié)點健康 ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key endpoint health --cluster # 測試寫入 ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key puttest-key"test-value"
風險提醒
etcd數(shù)據(jù)損壞可能是不可逆的。操作前務必先備份:etcdctl snapshot save。修改etcd配置后必須重啟服務,會有短暫不可用。
回滾方案
# 從快照恢復 ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db --data-dir=/var/lib/etcd --initial-cluster=--initial-advertise-peer-urls=https:// :2380 systemctl restart etcd
問題九:DNS解析異常
問題背景
集群內(nèi)Pod之間無法通過Service名稱通信,DNS查詢超時或返回錯誤結(jié)果。CoreDNS是集群DNS的核心組件,它的健康直接決定服務發(fā)現(xiàn)是否正常。
適用場景
應用啟動后連不上數(shù)據(jù)庫
Pod間調(diào)用莫名超時
集群內(nèi)網(wǎng)絡(luò)時斷時續(xù)
核心知識點
Kubernetes DNS基于CoreDNS實現(xiàn),通過kube-dns服務暴露。Pod的/etc/resolv.conf指向kube-dns的ClusterIP進行查詢。Service域名格式為
. .svc.cluster.local。 實戰(zhàn)步驟
第一步:確認CoreDNS Pod狀態(tài)
kubectl get pod -n kube-system -o wide | grep coredns kubectl logs -n kube-system--tail=50
第二步:進入測試Pod驗證DNS
kubectl run -it --rm debug --image=busybox -n default --restart=Never -- nslookup kubernetes.default kubectl run -it --rm debug --image=busybox -n default --restart=Never -- nslookup.
如果不指定命名空間,默認使用default命名空間。測試完后Pod會自動刪除。
第三步:檢查Pod的resolv.conf
kubectlexec-it-n -- cat /etc/resolv.conf
確認nameserver指向正確的ClusterIP。
第四步:測試直接IP連通性
kubectlexec-it-n -- ping kubectlexec-it -n -- curl -v https:// :
第五步:檢查CoreDNS配置
kubectl get configmap -n kube-system coredns -o yaml
根因定位與修復
原因一:CoreDNS Pod異常
# 重啟CoreDNS kubectl delete pod -n kube-system# 確認副本數(shù) kubectl get deployment -n kube-system coredns kubectl scale deployment coredns -n kube-system --replicas=3
原因二:upstream DNS配置錯誤
CoreDNS的forward配置決定了集群外域名查詢走哪里。
# ConfigMap中檢查 forward./etc/resolv.conf # 或指定上游服務器 forward.8.8.8.8
原因三:headless Service問題
kubectl get svc-n -o yaml | grep clusterIP
headless Service的clusterIP為None,這時DNS會返回Pod IP列表而不是單個IP。
原因四:busybox鏡像版本問題
舊版本busybox的nslookup實現(xiàn)不完整。換用其他鏡像測試:
kubectl run -it --rm debug --image=alpine --restart=Never -- sh # apk add bind-tools # nslookup
原因五:網(wǎng)絡(luò)策略阻止DNS流量
kubectl get networkpolicy -n kube-system
確認沒有規(guī)則阻止CoreDNS的53端口。
驗證方式
# 持續(xù)測試DNS解析 kubectlexec-it-n -- sh -c'for i in {1..10}; do nslookup kubernetes.default && break || sleep 1; done' # 檢查解析延遲 kubectlexec-it -n -- time nslookup
風險提醒
CoreDNS是集群核心組件,修改配置和重啟都會短暫影響DNS服務。滾動重啟CoreDNS一般不會影響業(yè)務,但有短暫解析失敗。
回滾方案
# 恢復CoreDNS ConfigMap kubectl apply -f coredns-configmap-backup.yaml # 如果是縮容問題,恢復副本數(shù) kubectl scale deployment coredns -n kube-system --replicas=<原數(shù)量>
問題十:Pod安全策略導致權(quán)限不足
問題背景
應用運行在非root用戶、強制安全上下文或限制性PodSecurityPolicy下,某些目錄無法寫入、某些端口無法監(jiān)聽、某些系統(tǒng)調(diào)用被拒絕。
適用場景
應用報Permission denied錯誤
容器內(nèi)無法創(chuàng)建文件
特權(quán)操作被拒絕
核心知識點
Pod安全通過PSP(PodSecurityPolicy,已廢棄)、Pod Security Standards、SecurityContext三層面控制。容器級別的runAsUser、capabilities、allowPrivilegeEscalation等設(shè)置會限制進程權(quán)限。
實戰(zhàn)步驟
第一步:查看Pod安全上下文
kubectl get pod -n-o yaml | grep -A 20 securityContext kubectl describe pod -n | grep -A 10"Security"
第二步:查看容器安全上下文
kubectl get pod -n-o jsonpath='{.spec.containers[*].securityContext}'
第三步:檢查Pod所在節(jié)點的安全模塊狀態(tài)
# 檢查是否啟用SELinux getenforce # 檢查AppArmor狀態(tài) apparmor_status # 檢查seccomp配置文件 cat /proc/sys/kernel/seccomp/computer_mode
第四步:查看相關(guān)事件和日志
kubectl describe pod -n| grep -A 5"Warning" # 檢查audit日志 auditctl -l | grep
根因定位與修復
原因一:非root用戶無法寫入目錄
修改安全上下文使用root運行(不推薦用于有漏洞的鏡像):
spec: securityContext: runAsUser:0
更好的方案是修改目錄權(quán)限:
spec: securityContext: runAsUser:1000 volumes: -name:data persistentVolumeClaim: claimName:my-pvc initContainers: -name:fix-permission image:busybox command:["sh","-c","chown -R 1000:1000 /data"] volumeMounts: -name:data mountPath:/data
原因二:缺少必要capability
應用需要綁定低位端口(如80、443)但沒有SYS_ADMIN capability。
spec: containers: -name:app securityContext: capabilities: add: -NET_BIND_SERVICE drop: -ALL
原因三:特權(quán)模式被禁用
運行特權(quán)容器被PSP或PSA拒絕:
spec: containers: -name:app securityContext: privileged:false allowPrivilegeEscalation:false
原因四:hostPath掛載被拒絕
spec: volumes: -name:host-sys hostPath: path:/sys type:Directory containers: -name:app volumeMounts: -name:host-sys mountPath:/host/sys readOnly:true
確保PSP允許hostPath類型。
驗證方式
# 確認應用正常運行 kubectlexec-it -n-- id # 應該顯示配置的runAsUser # 測試寫入權(quán)限 kubectlexec-it -n -- touch /data/test-file kubectlexec-it -n -- rm /data/test-file # 確認非特權(quán)運行 kubectlexec-it -n -- cat /proc/self/status | grep Cap
風險提醒
給予容器過高權(quán)限(privileged、SYS_ADMIN)會增大安全風險。生產(chǎn)環(huán)境應遵循最小權(quán)限原則。hostPath訪問節(jié)點文件系統(tǒng)可能導致容器逃逸。
回滾方案
# 恢復到之前的安全上下文配置 kubectl patch deployment-n --typemerge -p'{"spec":{"template":{"spec":{"securityContext":{"runAsUser":1000}}}}}'
總結(jié)
高頻問題排查矩陣
問題現(xiàn)象 首選排查命令 常見根因 Pod Pending kubectl describe pod 看Events 資源不足、污點、存儲等待 CrashLoopBackOff kubectl logs --previous 啟動命令錯誤、依賴不可達、權(quán)限問題 Service無法訪問 kubectl get endpoints Selector不匹配、kube-proxy異常、網(wǎng)絡(luò)策略 鏡像拉取失敗 kubectl describe pod 看錯誤 認證失敗、鏡像不存在、網(wǎng)絡(luò)不通 Node NotReady systemctl status kubelet kubelet崩潰、資源耗盡、證書過期 存儲卷異常 kubectl describe pvc StorageClass缺失、CSI驅(qū)動問題、權(quán)限 Pod被驅(qū)逐 kubectl describe pod 看配額 資源Limit不足、命名空間配額耗盡 etcd故障 etcdctl endpoint health 磁盤滿、證書過期、成員不一致 DNS異常 nslookup 測試 CoreDNS異常、upstream配置錯誤 權(quán)限不足 kubectl describe pod 看安全上下文 runAsUser限制、capability缺失 日常巡檢清單
# 節(jié)點健康 kubectl get nodes -o wide kubectl top nodes # Pod健康 kubectl get pods -A | grep -v Running kubectl get pods -A | grep -i evicted # 資源配額 kubectl get resourcequota -A kubectl describe limitrange -n# 存儲狀態(tài) kubectl get pvc -A kubectl get pv # 核心組件 kubectl get pods -n kube-system # 事件 kubectl get events -A --sort-by='.lastTimestamp'| tail -50
預防性措施
資源規(guī)劃:為每個命名空間設(shè)置合理的ResourceQuota,為每個Pod設(shè)置準確的resources requests和limits
高可用部署:關(guān)鍵應用使用反親和性分布到不同節(jié)點,控制面節(jié)點至少3個
監(jiān)控告警:對節(jié)點CPU、內(nèi)存、磁盤、Pod重啟、調(diào)度延遲等關(guān)鍵指標建立告警
定期演練:每個季度模擬一次故障,驗證備份可用性和恢復流程
版本管理:保持kubelet、containerd、etcd等核心組件版本一致,升級前先在測試環(huán)境驗證
日志收集:確保kubelet、containerd、etcd、CoreDNS日志匯聚到統(tǒng)一平臺,便于事后復盤
遇到問題先看事件、再查日志、最后看配置,按這個順序能覆蓋80%以上的常見故障。復雜問題往往需要綜合分析多個組件的狀態(tài),善用kubectl get和kubectl describe兩個命令能快速定位問題邊界。
-
集群
+關(guān)注
關(guān)注
0文章
157瀏覽量
17697 -
容器
+關(guān)注
關(guān)注
0文章
540瀏覽量
23044 -
kubernetes
+關(guān)注
關(guān)注
0文章
280瀏覽量
9540
原文標題:別踩坑!K8s 集群運維 10 個高頻問題一站式解決
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
Kubernetes集群運維中的常見問題和排查路徑
評論