建议收藏:Kubernetes 生产环境 10 大高频故障排查实战

 互联网   2026-05-15 09:46   8 人阅读  0 条评论
建议收藏:Kubernetes 生产环境 10 大高频故障排查实战  第1张

Kubernetes 在测试环境里,往往表现得很稳定;可一旦进入生产环境,随着业务规模扩大、应用数量增多、节点运行时间拉长,各种问题就会陆续冒出来。

有些故障表面看只是一个 Pod 起不来,背后却可能牵涉到调度器、容器运行时、网络、存储、DNS,甚至控制面本身。
如果没有一套稳定的排查思路,遇到问题时就很容易陷入“到处看日志、四处改配置、越改越乱”的状态。

其实,大多数 Kubernetes 问题都有比较固定的定位路径:

先看状态,再看 Events;先缩小范围,再查日志;最后再回到配置本身。

本文结合生产环境中的典型案例,整理出 10 个最常见的 Kubernetes 高频故障场景,覆盖:

  • Pod Pending
  • CrashLoopBackOff
  • Service 无法访问
  • 镜像拉取失败
  • Node NotReady
  • 存储卷挂载异常
  • 资源限制与驱逐
  • etcd 故障
  • DNS 解析异常
  • 权限与安全上下文问题

如果你平时负责 Kubernetes 集群运维,这篇文章建议直接收藏,关键时刻真能省不少时间。



一、先记住一条通用排障思路

很多人排查 Kubernetes 故障时,上来就改 YAML,或者只盯着 Pod 状态不放。
实际上,更高效的顺序应该是:

1)先看对象状态

先搞清楚出问题的是谁:

  • Pod 异常
  • Node 异常
  • PVC 异常
  • Service 不通
  • CoreDNS 异常
  • 控制面异常

常用命令:

kubectl get pods -A
kubectl get nodes
kubectl get svc -A
kubectl get pvc -A

2)再看 describe 和 Events

绝大多数常见问题,都会在事件里留下线索。
尤其是调度失败、挂载失败、探针失败、镜像拉取失败,先看 Events 往往比先翻日志更高效。

kubectl describe pod -n <namespace> <pod-name>
kubectl describe node <node-name>
kubectl describe pvc -n <namespace> <pvc-name>

3)再看相关组件日志

如果事件只能告诉你“失败了”,但原因仍然不够清楚,就继续下钻到组件:

  • kubelet
  • containerd
  • kube-proxy
  • CoreDNS
  • CSI
  • etcd

4)最后回到配置本身

等故障范围缩小以后,再去核对:

  • 资源配置
  • 标签和选择器
  • 镜像地址
  • 探针
  • 安全上下文
  • 存储配置
  • 网络策略

这套方法很朴素,但真正在生产环境里非常有效。


二、问题 1:Pod 一直处于 Pending 状态

问题现象

Pod 创建后长时间停留在 Pending,始终没有进入 Running。

常见场景

  • 新部署的应用起不来
  • 扩容后副本仍调度失败
  • 集群资源紧张时无法重新调度

排查思路

Pending 往往表示 Pod 还没有进入正常运行阶段。
最常见的原因主要有三类:

  1. 调度器找不到可用节点
  2. Pod 被污点、亲和性或资源约束挡住了
  3. PVC 未成功绑定,导致 Pod 无法继续推进

排查步骤

先看 Pod 详情

kubectl get pod -n <namespace> <pod-name> -o wide
kubectl describe pod -n <namespace> <pod-name>

重点看 Events。例如:

Warning  FailedScheduling  default-scheduler  0/5 nodes are available: 1 Insufficient cpu, 3 node(s) had taints that the pod didn't tolerate.

再看节点资源

kubectl top nodes
kubectl describe node <node-name>
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.allocatable.cpu}{" CPU\t"}{.status.allocatable.memory}{"\t"}{.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}'

重点关注 Allocatable,不要只看机器总资源。

检查污点

kubectl get node -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

检查 PVC 状态

kubectl get pvc -n <namespace>
kubectl describe pvc -n <namespace> <pvc-name>

常见根因与修复

1)资源不足

常见报错:

  • Insufficient cpu
  • Insufficient memory

处理方式:

  • 扩容节点
  • 降低 Pod 的 requests
  • 优化资源占用
  • 清理低优先级工作负载
resources:
requests:
memory:"128Mi"
cpu:"100m"
limits:
memory:"256Mi"
cpu:"200m"

2)节点污点限制

临时处理可以移除污点:

kubectl taint node <node-name> key=value:NoSchedule-

更稳妥的方式是在 Pod 里增加容忍:

tolerations:
-key:"key"
operator:"Exists"
effect:"NoSchedule"

3)PVC 绑定失败

重点检查:

  • StorageClass 是否存在
  • PV / PVC 是否匹配
  • CSI 驱动是否正常
  • 存储后端是否可达

验证方法

kubectl get pod -n <namespace> <pod-name> -w

风险提示

移除节点污点会改变整个节点的调度行为,操作前先确认该节点是否承担专用角色。


三、问题 2:Pod 一直处于 CrashLoopBackOff 状态

问题现象

Pod 能调度到节点,但容器启动后很快退出,并反复重启。

常见场景

  • 新版本上线后立即崩溃
  • 依赖服务未就绪导致应用退出
  • 健康检查过严,容器还没启动完就被杀掉

排查思路

CrashLoopBackOff 的核心不是“起不来”,而是:

容器启动了,但启动后很快崩了。

重点看这 5 个方向:

  1. 退出码
  2. 崩溃前日志
  3. 启动命令
  4. 外部依赖
  5. 健康检查

排查步骤

看退出信息

kubectl get pod -n <namespace> <pod-name> -o jsonpath='{.status.containerStatuses[*]}{"\n"}'
kubectl describe pod -n <namespace> <pod-name> | grep -A 20 "Last State"

看上一次崩溃日志

kubectl logs -n <namespace> <pod-name> --previous

看启动命令和环境变量

kubectl get pod -n <namespace> <pod-name> -o jsonpath='{.spec.containers[*].command}'
kubectl get pod -n <namespace> <pod-name> -o jsonpath='{.spec.containers[*].args}'
kubectl get pod -n <namespace> <pod-name> -o jsonpath='{.spec.containers[*].env}'

看探针配置

kubectl describe pod -n <namespace> <pod-name> | grep -A 5 "Liveness"
kubectl describe pod -n <namespace> <pod-name> | grep -A 5 "Readiness"
kubectl describe pod -n <namespace> <pod-name> | grep -A 5 "Startup"

测试依赖连通性

kubectl exec -it -n <namespace> <pod-name> -- nc -zv <service-name> 3306
kubectl exec -it -n <namespace> <pod-name> -- nslookup <service-name>

常见根因与修复

1)启动命令错误

command: ["/bin/sh""-c"]
args: ["node app.js && sleep infinity"]

2)依赖服务不可达

数据库、Redis、MQ 等依赖异常时,应用常常直接退出。

3)ConfigMap / Secret 缺失

kubectl get configmap -n <namespace> <configmap-name>
kubectl get secret -n <namespace> <secret-name>

4)目录权限不足

kubectl exec -it -n <namespace> <pod-name> -- ls -la /data
kubectl exec -it -n <namespace> <pod-name> -- id

5)探针过早失败

更合理的做法是给启动较慢的应用配置 startupProbe:

startupProbe:
httpGet:
path:/healthz
port:8080
failureThreshold:30
periodSeconds:10

验证方法

kubectl get pod -n <namespace> <pod-name> -w
kubectl exec -it -n <namespace> <pod-name> -- ps aux

回滚方案

kubectl rollout undo deployment <deployment-name> -n <namespace>
kubectl rollout status deployment <deployment-name> -n <namespace>

四、问题 3:Pod 无法通过 Service 访问

问题现象

Pod 之间通过 Service 名称访问失败,curl 超时,或者 Ingress 流量无法转发到后端。

排查思路

Service 通信链路通常可以拆成三层:

  1. DNS 解析
  2. Service 到后端的转发
  3. 后端 Pod 端口监听

排查步骤

确认对象存在

kubectl get pod -n <namespace> -o wide
kubectl get svc -n <namespace> <svc-name>

从其他 Pod 发起访问测试

kubectl exec -it -n <namespace> <source-pod> -- curl -v http://<svc-name>:<port>/

检查 Endpoints 和 EndpointSlice

kubectl get endpoints -n <namespace> <svc-name>
kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<svc-name>
kubectl describe svc -n <namespace> <svc-name>

如果 Endpoints 为空,说明 Service 没匹配到后端。

检查 kube-proxy

kubectl get pod -n kube-system -l k8s-app=kube-proxy -o wide
kubectl logs -n kube-system <kube-proxy-pod> --tail=100

测试 ClusterIP

kubectl exec -it -n <namespace> <source-pod> -- curl -v http://<cluster-ip>:<port>/

必要时到节点侧看规则

登录节点执行:

iptables -t nat -L -n | grep <cluster-ip>
ipvsadm -Ln

常见根因与修复

1)selector 不匹配

kubectl get pod -n <namespace> --show-labels

2)Pod 没 Ready

Service 默认不会把未 Ready 的 Pod 加进后端。

3)kube-proxy 异常

kubectl delete pod -n kube-system -l k8s-app=kube-proxy

4)DNS 异常

kubectl exec -it -n <namespace> <pod-name> -- nslookup <svc-name>
kubectl exec -it -n <namespace> <pod-name> -- cat /etc/resolv.conf

5)NetworkPolicy 阻断

kubectl get networkpolicy -n <namespace>
kubectl describe networkpolicy -n <namespace> <policy-name>

风险提示

重启 kube-proxy 和修改 NetworkPolicy 都可能影响业务流量,生产环境必须分批观察。


五、问题 4:镜像拉取失败

问题现象

Pod 调度成功,但镜像下载失败,状态显示 ImagePullBackOff 或 ErrImagePull。

排查思路

这类问题通常集中在 4 个方向:

  1. 镜像地址写错
  2. tag 不存在
  3. 认证失败
  4. 节点到仓库网络或 TLS 异常

排查步骤

看事件

kubectl describe pod -n <namespace> <pod-name> | grep -A 15 "Events"

节点侧手动拉取测试

crictl pull <registry>/<image>:<tag>
ctr -n k8s.io images pull <registry>/<image>:<tag>

检查镜像仓库认证

kubectl get secret -n <namespace>
kubectl describe secret -n <namespace> <registry-secret-name>

检查仓库网络与证书

curl -I https://<registry>/v2/

常见根因与修复

1)镜像地址或 tag 错误

最常见,也最容易忽略。

2)认证凭据错误

kubectl create secret docker-registry <secret-name> \
  --docker-server=<registry> \
  --docker-username=<user> \
  --docker-password=<password> \
  --docker-email=<email> \
  -n <namespace>

Pod 里引用:

spec:
imagePullSecrets:
-name:<secret-name>

3)TLS 证书不被信任

私有仓库常见问题是内部 CA 没有安装到节点信任链里。

4)节点网络不通

例如 DNS 不通、防火墙阻断、代理配置缺失。

验证方法

kubectl delete pod -n <namespace> <pod-name>
kubectl get events -n <namespace> --sort-by='.lastTimestamp' | tail -20

风险提示

删除 Pod 前先确认副本数是否足够,避免直接影响线上流量。


六、问题 5:Node 变成 NotReady

问题现象

节点状态显示 NotReady,新 Pod 无法继续调度到该节点。

排查思路

优先排查这 4 个方向:

  1. kubelet 是否正常
  2. containerd 是否正常
  3. 系统资源是否耗尽
  4. 节点与 API Server 是否连通

排查步骤

看节点状态

kubectl get nodes
kubectl describe node <node-name>
kubectl get node <node-name> -o jsonpath='{.status.conditions[*]}'

登录节点检查 kubelet

systemctl status kubelet
journalctl -u kubelet -n 100 --no-pager

检查系统资源

free -h
df -h
top -bn1 | head -20

检查 containerd

systemctl status containerd

检查与 API Server 连通性

ping <api-server-ip>
curl -k https://<api-server-ip>:6443/healthz

检查 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

常见根因与修复

1)kubelet 异常

systemctl restart kubelet

2)磁盘或内存耗尽

journalctl --vacuum-size=500M
crictl image prune

3)containerd 异常

systemctl restart containerd
systemctl restart kubelet

4)节点到控制面网络不通

重点查路由、防火墙、安全组和 LB 配置。

隔离与恢复

如果一时修不好,先隔离节点:

kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

恢复后再:

kubectl uncordon <node-name>

七、问题 6:存储卷挂载异常

问题现象

  • PVC 长期 Pending
  • Pod 启动后无法读写数据目录
  • 有状态服务无法正常挂载卷

排查思路

重点检查四层链路:

  1. StorageClass
  2. PVC
  3. PV
  4. CSI 驱动 / 存储后端

排查步骤

看 PVC

kubectl get pvc -n <namespace>
kubectl describe pvc -n <namespace> <pvc-name>

看 PV

kubectl get pv
kubectl describe pv <pv-name>

看 StorageClass

kubectl get storageclass
kubectl describe storageclass <sc-name>

看 CSI

kubectl get pod -n kube-system | grep csi
kubectl logs -n kube-system <csi-driver-pod> --tail=100
kubectl get csidrivers

到节点检查挂载

登录节点执行:

mount | grep <pv-name>
df -h | grep <mount-path>

常见根因与修复

1)StorageClass 不存在或 provisioner 错误

2)PVC 与 PV 不匹配

3)CSI 驱动异常

kubectl delete pod -n kube-system <csi-driver-pod>

4)节点无法访问存储后端

比如 NFS:

showmount -e <nfs-server>

5)目录权限不匹配

securityContext:
fsGroup:2000
runAsUser:1000

验证方法

kubectl exec -it -n <namespace> <pod-name> -- sh -c "echo test > /data/test.txt && cat /data/test.txt"

风险提示

删除 PVC 可能导致数据永久丢失,生产环境必须先确认备份。


八、问题 7:资源限制或节点压力导致 Pod 异常

问题现象

Pod 被杀掉、被驱逐,或者根本创建失败。
常见表现包括:

  • OOMKilled
  • Evicted
  • ResourceQuota 超限

排查思路

这类问题要分开看:

  • OOMKilled:通常是容器超过内存 limit
  • Evicted:通常是节点压力触发驱逐
  • 创建失败:通常是 quota / limitrange 限制

排查步骤

kubectl get pod -n <namespace>
kubectl describe pod -n <namespace> <pod-name>
kubectl get resourcequota -n <namespace>
kubectl describe resourcequota -n <namespace>
kubectl get limitrange -n <namespace>
kubectl describe limitrange -n <namespace>
kubectl top pod -n <namespace>
kubectl top nodes
kubectl get events -n <namespace> --sort-by='.lastTimestamp' | tail -30

常见根因与修复

1)内存 limit 太小

resources:
requests:
memory:"512Mi"
limits:
memory:"1Gi"

2)节点资源压力

如果是 Evicted,不要只盯 Pod,更要看节点层面的容量。

3)命名空间配额耗尽

可以适当调整:

apiVersion:v1
kind:ResourceQuota
metadata:
name:increase-quota
spec:
hard:
requests.cpu:"20"
requests.memory:40Gi
limits.cpu:"40"
limits.memory:80Gi

4)LimitRange 默认限制不合理

很多应用一上线就 OOM,问题根本不在代码,而在命名空间默认 limit 太小。


九、问题 8:etcd 集群故障

问题现象

  • kubectl 请求超时
  • API Server 不稳定
  • 控制面整体异常

排查思路

etcd 出问题时,表面看起来常常像“整个集群都怪怪的”。
这时优先确认:

  1. etcd 进程是否健康
  2. endpoint 是否健康
  3. member 是否完整
  4. 磁盘是否满了
  5. 证书是否过期

排查步骤

看 etcd 状态

如果是静态 Pod:

kubectl -n kube-system get pod -l component=etcd -o wide
kubectl -n kube-system logs <etcd-pod> --tail=100

如果是 systemd:

systemctl status etcd
journalctl -u etcd -n 100 --no-pager

看健康状态

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 \
  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
kubeadm certs check-expiration

常见根因与修复

1)磁盘空间不足

可以先做 defrag:

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

2)成员异常或网络分区

涉及 member remove 时一定要慎重。

3)证书过期

先用:

kubeadm certs check-expiration

确认是否真是证书问题。

风险提示

etcd 是集群最核心的组件之一。涉及成员变更、证书续期、快照恢复前,务必先做备份。

备份示例:

ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%F-%H%M).db

十、问题 9:DNS 解析异常

问题现象

Pod 无法通过服务名访问目标服务,nslookup 超时或返回异常结果。

排查思路

DNS 问题优先看三件事:

  1. CoreDNS 是否健康
  2. Pod 的 resolv.conf 是否正确
  3. 53 端口流量是否被拦截

排查步骤

看 CoreDNS 状态

kubectl get pod -n kube-system -l k8s-app=kube-dns -o wide
kubectl logs -n kube-system <coredns-pod> --tail=100

起一个测试 Pod 做解析验证

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 <svc-name>.<namespace>.svc.cluster.local

看业务 Pod 的 resolv.conf

kubectl exec -it -n <namespace> <pod-name> -- cat /etc/resolv.conf

看 CoreDNS 配置

kubectl get configmap -n kube-system coredns -o yaml

看网络策略

kubectl get networkpolicy -A

常见根因与修复

1)CoreDNS Pod 异常

kubectl rollout restart deployment coredns -n kube-system

2)上游 DNS 配置错误

3)Headless Service 结果与预期不一致

clusterIP: None 返回的是 Pod IP 列表,不是单个 VIP。

4)NetworkPolicy 阻断 53 端口

这是生产环境里很常见的误伤点。


十一、问题 10:安全上下文导致权限不足

问题现象

应用报 Permission denied,常见表现包括:

  • 无法写目录
  • 无法绑定低位端口
  • 某些系统调用被拒绝

排查思路

在 Kubernetes 1.28 中,重点关注:

  1. securityContext
  2. Pod Security Admission
  3. SELinux / AppArmor / seccomp
  4. 宿主机目录权限

排查步骤

kubectl get pod -n <namespace> <pod-name> -o yaml | grep -A 30 securityContext
kubectl describe pod -n <namespace> <pod-name>
kubectl get ns <namespace> --show-labels
kubectl exec -it -n <namespace> <pod-name> -- id
kubectl exec -it -n <namespace> <pod-name> -- ls -la /data

节点侧检查:

getenforce
apparmor_status

seccomp 检查:

kubectl get pod -n <namespace> <pod-name> -o jsonpath='{.spec.securityContext.seccompProfile}'
kubectl get pod -n <namespace> <pod-name> -o jsonpath='{.spec.containers[*].securityContext.seccompProfile}'

常见根因与修复

1)非 root 用户无法写目录

推荐修目录权限,而不是直接切 root:

securityContext:
runAsUser:1000
fsGroup:1000
initContainers:
-name:fix-permission
image:busybox
command: ["sh""-c""chown -R 1000:1000 /data"]

2)缺少能力绑定低位端口

securityContext:
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]

3)只读根文件系统与应用行为冲突

4)命名空间安全策略限制

风险提示

不要轻易把容器改成 privileged: true 或 runAsUser: 0,生产环境应尽量遵循最小权限原则。


十二、10 大高频问题排查矩阵

问题现象
首选排查命令
常见根因
Pod Pending
kubectl describe pod
资源不足、污点、PVC 未绑定
CrashLoopBackOff
kubectl logs --previous
启动命令错误、依赖不可达、探针失败
Service 不通
kubectl get endpoints
selector 不匹配、Pod 未 Ready、kube-proxy 异常
镜像拉取失败
kubectl describe pod
镜像不存在、认证失败、TLS/网络问题
Node NotReady
systemctl status kubelet
kubelet 异常、containerd 故障、磁盘满
存储卷异常
kubectl describe pvc
StorageClass/CSI/权限问题
OOM / Evicted / 配额失败
kubectl describe pod
limit 不合理、节点压力、Quota 超限
etcd 故障
etcdctl endpoint health
磁盘满、证书过期、成员异常
DNS 异常
nslookup
 + CoreDNS 日志
CoreDNS 异常、配置错误、策略阻断
权限不足
kubectl describe pod
 + securityContext
runAsUser、capabilities、PSA 限制

十三、建议长期保留的一份巡检清单

# 节点健康
kubectl get nodes -o wide
kubectl top nodes

# 异常 Pod
kubectl get pods -A | egrep -v 'Running|Completed'
kubectl get pods -A | grep -i Evicted

# 资源配额
kubectl get resourcequota -A
kubectl get limitrange -A

# 存储状态
kubectl get pvc -A
kubectl get pv

# 核心组件
kubectl get pods -n kube-system

# 最近事件
kubectl get events -A --sort-by='.lastTimestamp' | tail -50

如果条件允许,建议同时对以下指标配置监控告警:

  • Node NotReady
  • Pod 重启次数异常
  • Pending Pod 数量
  • PVC Pending 数量
  • CoreDNS 错误率
  • etcd 延迟与空间使用率
  • 镜像拉取失败次数

十四、写在最后

Kubernetes 的问题之所以让人觉得“复杂”,很多时候并不是因为它真的无从下手,而是因为故障表象和真实根因之间隔了几层。

一个 Pod 起不来,可能是资源问题;
一个 Service 不通,可能是 DNS、selector、探针,甚至网络策略;
一次 API 超时,背后也可能不是 apiserver 本身,而是 etcd 已经开始出问题。

所以,排障最怕的不是问题复杂,而是没顺序。
只要记住这条主线:

先看状态,再看 Events;先缩小范围,再查日志;最后回到配置。

大部分生产环境里的常见故障,基本都能更快收敛。

如果你也在维护 Kubernetes 集群,建议把这篇文章先收藏起来。
很多问题平时看着不常见,但真到线上出故障的时候,能不能第一时间找到排查路径,差别会非常大。

你在生产环境里踩过最离谱的 Kubernetes 坑是什么?欢迎留言聊聊。


(版权归原作者所有,侵删)


免责声明:本文内容来源于网络,所载内容仅供参考。转载仅为学习和交流之目的,如无意中侵犯您的合法权益,请及时联系Docker中文社区!



建议收藏:Kubernetes 生产环境 10 大高频故障排查实战  第2张


本文地址:https://docker.top/?id=460
温馨提示:文章内容系作者个人观点,不代表Docker中文对观点赞同或支持。
版权声明:本文为转载文章,来源于 互联网 ,版权归原作者所有,欢迎分享本文,转载请保留出处!

 发表评论


表情

还没有留言,还不快点抢沙发?