Kubernetes Pod 调度与故障排查实战

Pod 是怎么被调度和运行的

理解 Kubernetes 排错,先要理解 Pod 的生命周期:Pending → ContainerCreating → Running → Succeeded/Failed。任何一个阶段卡住都会在 kubectl get pods 里看到对应的异常状态。本文按”卡在哪、怎么查、怎么修”来讲。

一、调度相关:Pod 一直 Pending

Pending 通常是调度器找不到合适的节点。常见原因:

  • 资源请求超过节点剩余(CPU/Memory request 太大)
  • 节点有 taint,Pod 没有对应 toleration
  • nodeSelector / affinity 条件过严,没有节点满足
kubectl describe pod my-pod
# 看 Events 段,通常直接写着 "0/3 nodes are available: ..."

用 nodeSelector / affinity 控制调度

spec:
  nodeSelector:
    disktype: ssd
  tolerations:
  - key: "gpu"
    operator: "Equal"
    value: "true"
    effect: "NoSchedule"

二、镜像相关:ImagePullBackOff

镜像拉不下来,九成是这几种:

  • 镜像名/Tag 写错
  • 私有仓库没配 imagePullSecrets
  • 节点网络访问不了镜像仓库(尤其国内拉 docker.io)
kubectl describe pod my-pod | grep -A5 Events
# 若看到 "pull access denied" 或 "manifest unknown" 即上述原因

三、启动相关:CrashLoopBackOff

容器起来又崩,循环重启。排查顺序:

# 1. 看容器日志(加 --previous 看上一次崩溃的日志)
kubectl logs my-pod --previous

# 2. 看具体事件
kubectl describe pod my-pod

# 3. 如果是配置/依赖问题,可临时进容器调试
kubectl exec -it my-pod -- sh

常见根因:应用启动依赖的数据库没就绪、配置文件路径错误、内存超限被 OOMKilled(看 Events 里有没有 OOMKilled)。

四、就绪与存活探针

很多”服务起来了但访问 503″的问题,是就绪探针没配对:

livenessProbe:
  httpGet: { path: /health, port: 8080 }
  initialDelaySeconds: 30
  periodSeconds: 10
readinessProbe:
  httpGet: { path: /ready, port: 8080 }
  periodSeconds: 5

liveness 失败会重启容器,readiness 失败会把 Pod 从 Service 后端摘掉但不重启。两者别用同一个路径,否则会误杀。

五、资源限制别忘了

resources:
  requests: { cpu: "100m", memory: "256Mi" }
  limits:   { cpu: "500m", memory: "512Mi" }

不设 limits 容易被邻居”吵醒”或自己把节点内存吃满。设了 memory limit 又超限就会 OOMKilled,要结合日志判断是调大还是修内存泄漏。

小结

K8s 排错的核心心法是:先用 describe 看 Events,再用 logs --previous 看崩溃原因,最后用 exec 进容器确认。绝大多数 Pod 异常都逃不出 Pending / ImagePull / CrashLoop 这三类,照着上面的清单逐一排除即可。

上一篇 SQL Server 执行计划解读与索引优化实战
下一篇 AI Agent 开发实战:从 Function Calling 到工具调用