Kubernetes 故障排查
排查顺序:自上而下 / 由外向内 / 先看事件、再查日志、最后进容器。
- 资源状态 -> kubectl get
- 事件记录 -> kubectl describe
- Pod 日志 -> kubectl logs
- Node 状态 -> kubectl get nodes
- Kubelet 日志 -> systemctl / journalctl
- 容器运行时 -> crictl
- CNI 网络 -> Calico / iptables / routes
- 存储 -> PV / PVC / StorageClass
原因分类
| 类型 | 典型事件 | 解决办法 |
|---|---|---|
| 没节点可调度 | 0/3 nodes available | 检查 taint、资源、污点 |
| PVC 绑定失败 | no persistent volumes found | 修 storageClass |
| NodeSelector 不匹配 | node(s) didn’t match node selector | 改 selector |
核心排查命令
kubectl describe pod <pod>
kubectl get nodes -owide
kubectl describe node <node>
排查命令
kubectl describe pod <pod> | grep -i image
常见原因
| 原因 | 检查点 |
|---|---|
| 镜像不存在 | image 名字拼错 |
| tag 不存在 | latest 不可控 |
| registry 认证失败 | secret 不对 |
| proxy 拦截 | 网络防火墙 |
解决
kubectl create secret docker-registry mysecret ...
kubectl set image deploy/myapp myapp=repo/image:v1
排查命令
kubectl logs <pod> -p
查看上一个容器的日志(CrashLoop 必须看 -p)。 如果还看不到 -> 启动命令错误。
重点检查
- entrypoint / command 写错
- 程序启动后立即退出
- configs / secrets 挂载失败
- readinessProbe / livenessProbe 强杀
kubectl describe pod <pod> | grep -i oom
原因:
- 容器内存爆了,被 kubelet cgroup 杀掉
解决:
- 提高 resources.limits.memory
- 优化应用内存
kubectl describe pod <pod> | grep -i evict
kubectl get nodes -owide
原因:
- 节点磁盘满了(最常见)
- 节点内存压力
- 节点 PID 不够
解决:
df -h
du -sh /var/lib/containerd
journalctl --vacuum-size=500M
检查 probe:
kubectl describe pod <pod> | grep -A5 -i probe
排查顺序:
kubectl get pods -owide
ip route
calicoctl get nodes
calicoctl get ipPool
ls /etc/cni/net.d/
检查 kube-proxy:
kubectl get pods -n kube-system -l k8s-app=kube-proxy
kubectl logs -n kube-system kube-proxy-xxxxx
检查 ipvs:
ipvsadm -Ln
看 service 端口是否存在。
Checklist:
- 服务 listen 端口是否存在
- kube-proxy ipvs 是否有记录
- 节点防火墙是否允许端口
- Pod 是否 ready
验证:
curl -v http://node-ip:<nodeport>
核查 CoreDNS 状态
kubectl -n kube-system get pods -l k8s-app=kube-dns
kubectl logs -n kube-system coredns-xxxx
常见报错:
- SERVFAIL -> 上游 DNS 不通
- loop detected -> nodeLocalDNS 配置错误
- connection refused -> Pod 无 network
kubectl describe node <node>
常见原因:
- kubelet 挂了
- containerd 挂了
- CNI 目录丢失
- 磁盘满
检查 systemd:
systemctl status kubelet
journalctl -u kubelet -f
检查 containerd:
systemctl status containerd
crictl ps
journalctl -u kubelet | grep cgroup
解决:kubelet 和 containerd 都要用 systemd
kubectl get pvc
kubectl describe pvc <pvc>
kubectl get sc
原因:
- 没有默认 storageClass
- 卷插件不可用
kubectl describe pod <pod> | grep -i mount
典型问题:
- NFS 服务不通
- Ceph keyring 错误
- 主机路径权限不对
Ingress 访问失败
检查 ingress pod:
kubectl get pods -n ingress-nginx
kubectl logs -n ingress-nginx ingress-nginx-controller-xxxxx
检查 ingress 规则:
kubectl describe ingress my-ing
检查 backend:
kubectl get endpoints
如果 endpoints 为空 -> Service selector 错误。
journalctl -u kube-apiserver -f
常见原因
- apiserver 证书过期
- apiserver 进程OOM
- etcd 不可用
检查证书:
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -enddate
systemctl status etcd
journalctl -u etcd -f
ETCDCTL_API=3 etcdctl --endpoints=https://IP:2379 endpoint health
etcdctl alarm list
清理:
etcdctl alarm disarm
etcdctl defrag
crictl ps -a
crictl logs <container-id>
crictl images
crictl rmi $(crictl images | awk '/<none>/{print $3}')
kubectl get events --sort-by=.metadata.creationTimestamp
kubectl describe pod <pod>
kubectl logs <pod> -p
kubectl get endpoints
kubectl exec -it <pod> -- sh
kubectl get nodes -owide
kubectl describe node <node>
ipvsadm -Ln
ip route
systemctl status kubelet
journalctl -u kubelet -f
crictl ps -a
crictl logs <id>
df -h
dmesg | tail