Pod CrashLoopBackOff:最常见也最容易定位的故障
CrashLoopBackOff意味着容器启动后反复崩溃,kubelet按指数退避策略重启。排查第一步永远是看容器日志和退出码:
# 查看Pod状态和重启次数
kubectl get pods -n production -o wide | grep -i crash
# 获取上次崩溃的日志(重要:不加--previous只能看当前运行容器的日志)
kubectl logs web-app-7d4f8c-x2k9 -n production --previous
# 查看事件
kubectl describe pod web-app-7d4f8c-x2k9 -n production | grep -A5 "Events"
# 检查退出码
kubectl get pod web-app-7d4f8c-x2k9 -n production -o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'
退出码对应不同故障类型:
Exit Code 137:OOM Killed,容器内存超限。解法:调大resources.limits.memory,或排查应用内存泄漏。
Exit Code 1:应用自身错误,日志里有具体报错栈。
Exit Code 137 + OOMKilled=True:确认是cgroup内存限制触发。对比容器的memory limit和JVM -Xmx参数——如果Xmx等于或大于memory limit,JVM堆外内存必然超限。经验值:Xmx设为memory limit的70%-80%,留出堆外空间。
Exit Code 2 / 126:Entrypoint或启动脚本错误。检查Dockerfile的ENTRYPOINT是否正确,ConfigMap/Secret挂载是否到位。
ImagePullBackOff:镜像拉取失败链路分析
镜像拉取失败在私有化部署环境极为常见,故障链路涉及镜像仓库、网络、认证三个层面:
# 查看具体拉取错误
kubectl describe pod myapp-5c7f9b-m3x2 -n production | grep -A10 "Events"
# 典型输出:
# Warning Failed 3m kubelet Error: ImagePullBackOff
# Warning Failed 1m kubelet Failed to pull image "registry.internal/myapp:v2.3":
# rpc error: code = Unknown desc = Error response from daemon:
# pull access denied for registry.internal/myapp
# 验证节点上能否拉取镜像
kubectl debug node/worker-03 -it --image=busybox -- sh
# 在debug容器中手动拉取
crictl pull registry.internal/myapp:v2.3
# 检查imagePullSecrets
kubectl get secret regcred -n production -o yaml | grep -A2 "dockerconfigjson"
高频场景排查清单:
1. 私有仓库认证信息过期或不存在——确认imagePullSecrets正确挂载且token有效
2. 镜像tag不存在——检查tag拼写,确认CI/CD已推送该版本
3. 节点网络不通仓库——从节点curl registry.internal/v2/_catalog验证
4. 仓库存储满或限速——检查Harbor/Nexus存储和带宽
节点NotReady:从kubelet到网络的全链路排查
节点NotReady意味着kubelet停止向API Server上报节点状态,超过node-monitor-grace-period(默认40秒)后节点被标记NotReady。排查方向:
# 1. 查看节点条件和事件
kubectl describe node worker-03 | grep -A10 "Conditions"
# 关注Ready条件:Status=Unknown说明kubelet失联
# 2. SSH到节点检查kubelet状态
systemctl status kubelet
journalctl -u kubelet --since "10 min ago" --no-pager | tail -50
# 3. 常见原因:磁盘满导致kubelet无法写文件
df -h /var/lib/kubelet
# kubelet需要在/var/lib/kubelet下写入pod配置和volume数据
# 磁盘满时kubelet无法创建新文件,直接停止上报
# 4. PLEG(Pod Lifecycle Event Generator)超时
journalctl -u kubelet | grep "PLEG is not healthy"
# PLEG超时通常因为容器运行时响应慢,检查docker/containerd状态
systemctl status containerd
crictl ps # 查看容器运行时是否正常
磁盘满是最常见的NotReady原因。Kubernetes默认配置下,节点磁盘使用率>85%时kubelet主动设置DiskPressure条件,>95%时停止调度新Pod。但旧文件残留(退容器的日志、未清理的镜像层)会逐步填满磁盘。
# 清理节点磁盘
# 清理退出的容器
crictl rm $(crictl ps -a -q --filter "status=exited") 2>/dev/null
# 清理未使用的镜像
crictl rmi $(crictl images -q) 2>/dev/null
# 清理日志(限制单日志文件大小)
find /var/log/pods -name "*.log" -size +100M -exec truncate -s 0 {} \;
# 长期方案:配置日志轮转
cat > /etc/logrotate.d/kube-pods <<'EOF'
/var/log/pods/*/*.log {
daily
rotate 3
maxsize 50M
compress
missingok
copytruncate
}
EOF
Service访问不通:从DNS到iptables的全链路验证
Service访问故障在Kubernetes排障中难度最高,因为涉及DNS、kube-proxy、iptables/eBPF、CNI四层网络。按顺序排查:
# 1. DNS解析验证
kubectl exec -it debug-pod -- nslookup my-service.production.svc.cluster.local
# 如果返回NXDOMAIN,检查CoreDNS
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system coredns-6d4b7b6b-x2k9
# 2. ClusterIP连通性
kubectl exec -it debug-pod -- curl -v http://10.96.0.50:8080/healthz
# 3. Endpoints是否就绪
kubectl get endpoints my-service -n production
# 如果ENDPOINTS为,说明没有Pod满足readiness探针条件
# 4. iptables规则验证(iptables模式)
iptables -t nat -L KUBE-SERVICES -n | grep 10.96.0.50
iptables -t nat -L KUBE-SVC-XXXX -n # 跟踪DNAT链路
最容易被忽视的坑:readinessProbe配置不当导致Endpoints为空。Pod Running但readinessProbe失败时,Pod不在Service Endpoints中,流量不会转发到该Pod。检查方式——对比Pod数量和Endpoints数量,数量不一致就是readinessProbe拦截了部分Pod。
etcd性能退化与集群稳定性
etcd是Kubernetes的控制面存储,其性能直接影响API Server响应速度和集群调度能力。etcd写入延迟超过100ms时,kubectl操作明显变慢;超过500ms时可能出现leader选举抖动。
# etcd健康检查
ETCDCTL_API=3 etcdctl endpoint health --cluster \
--endpoints=https://etcd-1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# 查看etcd延迟
ETCDCTL_API=3 etcdctl endpoint status --write-out=table
# 关键指标:数据库大小
ETCDCTL_API=3 etcdctl endpoint status --write-out=fields | grep db_size
# db_size超过2GB需要考虑压缩和碎片整理
etcdctl compact $(etcdctl endpoint status --write-out=json | python3 -c "import sys,json;print(json.load(sys.stdin)[0]['Status']['revision'])")
etcdctl defrag
etcd维护要点:定期执行compaction清理历史版本(默认保留10000个revision),碎片整理释放磁盘空间,监控db_size不超过8GB(超过后etcd会拒绝写入)。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-ji-qun-gu-zhang-zhen-duan-shi-zhan-cong/