发现服务异常,第一步是直接访问Pod IP。如果异常,说明问题出在Pod自身;如果正常,问题可能出在Service或DNS。
Pod 排查流水线:
- 看状态:
kubectl get pods -n <namespace_name>。STATUS:Pending / Running / CrashLoopBackOff / ImagePullBackOff / Error 等。 READY:1/1 表示容器都就绪;0/1 常见为容器刚启动还没就绪,或就绪探针失败。 - 看事件:
kubectl describe pod <pod_name> -n <namespace_name>。 - 看日志:
kubectl logs <pod_name>。 - 必要时进容器:
kubectl exec -it <POD-NAME> -c <CONTAINER-NAME> -- <COMMAND>。或者使用临时容器。
-c ${CONTAINER_NAME} 是可选择的。如果 Pod 中仅包含一个容器,就可以忽略它。
不加-n <namespace_name>会查看default命名空间的pod
Service 排查流水线:
- 查看Pod是否Running、Ready:
kubectl get pods -n <namespace_name> - 查看Service是否存在:
kubectl get sc -n <namespace_name> - Endpoints是否有IP:
- Pod内DNS能否解析Service
- 通过ClusterIP能否访问Service
- 检测kube-proxy或网络策略
Pod状态异常
调试 Pod 的第一步是查看 Pod 信息。用如下命令查看 Pod 的当前状态和最近的事件
|
|
Pod停滞在 Pending 状态
如果一个 Pod 停滞在 Pending 状态,表示 Pod 没有被调度到节点上。常见原因有:
- 集群资源不足(CPU/内存)。可能集群上所有的CPU或内存已耗尽。此时需要删除 Pod、调整资源请求或者为集群添加节点。
- 节点选择器 / 亲和性 / 污点容忍没匹配到节点。此时需要调整 Pod 的 nodeSelector / affinity / tolerations
- 使用了 hostPort,但可用节点数不足。如果绑定Pod到hostPort,那么集群中节点的个数就是所能创建的 Pod 的数量上限。解决方法是改用 Service 对外暴露,或保证节点数 ≥ Pod 数。
查看详情和事件,输出最后一段Events里通常有FailedScheduling之类的事件。例如:
|
|
Pod停滞在 Waiting 状态
如果 Pod 停滞在 Waiting 状态,则表示 Pod 已经被调度到某工作节点,但是无法在该节点上运行。Waiting 状态的最常见原因是拉取镜像失败。要检查的有三个方面:
- 确保镜像名字拼写正确。
- 确保镜像已被推送到镜像仓库。
- 尝试手动是否能拉取镜像。
sudo crictl pull <image_name>
详情和事件里输出的Events里通常有Failed to pull image,非常容易排查。
解决方法就是使用正确的镜像名字,如果k8s官方仓库拉不来下,
- 配置阿里云镜像源(国内只有阿里云宣布支持新版的k8s仓库)
- 配置私有仓库
- 在一个能拉取镜像的机器上手动拉取(可能docker仓库有,可以查看一下),然后保存
save为tar包, 导出tar包上传到k8s集群上再导入镜像sudo ctr -n k8s.io images import <image_tar_name>。 如果有需要,可以修改导入到k8s集群上的镜像的标签tag。
Pod一直CrashLoopBackOff / Error
如果Pod一直CrashLoopBackOff/Error,表明容器反复启动后退出。此时 Pod 已经被调度,重点看日志:
|
|
结合 describe 里的退出码,在 Containers 下的 Last State 可以看到退出码和原因, 例如Exit Code 137 通常表示被 SIGKILL(OOM 或人为杀掉),Exit Code 1、Exit Code 0 等需要看应用日志具体含义。
|
|
日志里常见问题:配置错误(连不上数据库、参数写错)。启动脚本错误。资源限制导致被 OOM Killed
Pod优雅终止(Graceful Termination)
Pod优雅终止能确保高可用,避免请求丢失。当执行kubectl delete Pod或节点维护触发驱逐时:
- kube-server将Pod状态设置为Terminating,同时通知EndpointSlice控制器。
- EndpointSlice检测到Pod处于Terminating状态,立刻将该Pod的IP从所有关联的Service的EndpointSlice对象中删除。避免请求打到已终止的Pod。
- kubelet向Pod的主进程(PID 1)发送SIGTERM信号。应用接受到信号后停止接受新请求,完成正在处理的请求,释放资源(数据库连接、文件句柄等)。
- 等待优雅期(Termination Grace PeriodSeconds),默认等待30s,如果应用在超时前退出,则终止成功。
- 如果应用未在优雅期退出,kubelet发送
SIGKILL强制要求杀死容器。
Pod停滞在terminating 状态
如果Pod停滞在Terminating状态,表示已发出删除Pod的请求,但控制平面无法删除该 Pod 对象。
如果Pod拥有Finalizer并且集群中安装了准入Webhook,可能会导致控制平面无法移除 Finalizer,从而导致Pod出现此问题。
要确认这种情况,请检查你的集群中是否有ValidatingWebhookConfiguration或MutatingWebhookConfiguration处理pods资源的UPDATE操作。
如果 Webhook 是由第三方提供的:
- 确保你使用的是最新版。
- 禁用处理 UPDATE 操作的 Webhook。
- 向相关供应商报告问题。
如果你是 Webhook 的作者:
- 对于变更性质的 Webhook,请确保在处理 UPDATE 操作时不要更改不可变字段。 例如,一般不允许更改 containers。
- 对于验证性质的 Webhook,请确保你的验证策略仅被应用于新的更改之上。换句话说, 你应该允许存在违规的现有 Pod 通过验证。这样可以确保在安装验证性质的 Webhook 之前创建的 Pod 可以继续运行
Pod Running 但不符合预期
容器在跑,但行为不正常。这种一般是业务逻辑问题。
|
|
进阶:临时容器(Ephemeral Container)
当容器镜像没有 shell,或者容器刚启动就崩,kubectl exec 用不了,可以用 kubectl debug 挂一个临时容器进去
|
|
这会在同一个 Pod 里跑一个 busybox 容器,并共享进程命名空间,可以 ps 看到原容器的进程,做网络调试等。
排查小结
| 现象 | 关键命令 | 重点关注 |
|---|---|---|
| 一直 Pending | kubectl describe pod | Events 里的调度失败原因 |
| 一直 Waiting / ImagePullBackOff | kubectl describe pod + 在节点手动拉镜像 | 镜像名 / 私有仓库凭证 |
| CrashLoopBackOff / Error | kubectl logs / kubectl logs –previous | 应用日志、退出码 |
| Running 但行为异常 | kubectl exec / kubectl debug | 容器内网络/进程/配置 |
Service状态异常
|
|
|
|
- 先确认Pod本身没问题
|
|
- 检查Service是否存在
|
|
- 检查EndpointSlices,正常应该看到3个Pod IP(副本是3)。
如果 ENDPOINTS
,说明 Service 没选中 Pod,通常是标签选择器不匹配,Deployment / Pod 的标签和 Service 的 selector 不一致。
|
|
- 从 Pod内部测试DNS解析
|
|
如果短名 hostnames 不行,但 hostnames.default.svc.cluster.local 可以,通常是 search 域或 ndots 配置问题。 如果完全解析不了,确认 CoreDNS / kube-dns 是否正常。
|
|
- 通过ClusterIP直接访问Service
|
|
如果 ClusterIP 能访问,说明 Service 代理正常。 如果 ClusterIP 不通,再检查 kube-proxy 日志和 iptables/ipvs 规则。 6. kube-proxy或者网络策略问题 如果Pod正常、Service有Endpoints、DNS解析正常但是ClusterIP仍然不通;那就要怀疑kube-proxy或网络策略。
|
|
如果使用了 NetworkPolicy,还要检查是否允许 Pod 间访问或从某命名空间访问