Pod 卡住的状态本身就是 诊断信号。Pending 是调度器在喊冤,CrashLoopBackOff 是容器在求救,ImagePullBackOff 是 kubelet 在敲门没人应。读懂状态码,比盲目重启高效十倍。
kubectl get pod 显示 STATUS 为 Pending,READY 为 0/1FailedScheduling 事件# 1. 看调度失败的具体原因(最关键的一步) kubectl describe pod <pod-name> | grep -A 10 Events # 2. 看节点资源使用情况 kubectl top nodes kubectl describe node <node-name> | grep -A 5 "Allocated resources" # 3. 看节点污点 kubectl describe node <node-name> | grep Taint # 4. 看 PVC 是否绑定成功 kubectl get pvc kubectl describe pvc <pvc-name>
requests,运行时杀进程看的是 limits。requests 设过高会调度失败,limits 设过低会 OOMKilled。
# 资源不足:扩节点 或 降低 Pod requests kubectl edit deployment <name> # 修改 spec.template.spec.containers[].resources.requests # 节点污点不匹配:加 toleration 或 去掉污点 kubectl taint nodes <node> key=value:NoSchedule- # 末尾减号是删除 # 节点被 cordon:解除调度禁用 kubectl uncordon <node-name>
# 1. 看 events 里的具体卡点 kubectl describe pod <pod> | tail -30 # 2. 登录所在节点看 kubelet 日志 ssh <node> journalctl -u kubelet -f --since "5 min ago" # 3. 检查 CNI 插件 Pod 状态 kubectl -n kube-system get pod -o wide | grep -E "calico|flannel|cni" # 4. 容器运行时是否健康 systemctl status containerd crictl ps -a # containerd 用这个查容器
FailedCreatePodSandBox → 99% 是 CNI 问题;MountVolume.SetUp failed → 卷的问题;啥都没有 → 看节点 kubelet 日志。
# 1. 看具体报错信息 kubectl describe pod <pod> | grep -A 5 "Failed" # 2. 节点直接拉镜像,定位是 K8s 问题还是节点问题 crictl pull <image:tag> # 或 docker 环境 docker pull <image:tag> # 3. 检查私有仓库 secret kubectl get secret <secret-name> -o yaml kubectl get secret <secret> -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d
# 创建 docker-registry 类型 secret kubectl create secret docker-registry regcred \ --docker-server=harbor.example.com \ --docker-username=admin \ --docker-password='Harbor12345' \ --docker-email=a@b.com
# Pod / Deployment 中引用 spec: imagePullSecrets: - name: regcred containers: - name: app image: harbor.example.com/proj/app:v1
/etc/containerd/config.toml 配置 insecure registry,改完 systemctl restart containerd。docker 改 /etc/docker/daemon.json 的 insecure-registries。
# 1. 看当前日志 kubectl logs <pod> # 2. 看上一次崩溃的日志(最重要!当前已经被新容器替换) kubectl logs <pod> --previous # 3. 看退出码和原因 kubectl describe pod <pod> | grep -A 5 "Last State"
| 退出码 | 含义 | 常见场景 |
|---|---|---|
0 | 正常退出 | 没有前台进程,容器跑完就结束 |
1 | 应用错误 | 代码异常、配置文件解析失败 |
125 | 容器命令调用失败 | docker run 参数错误 |
126 | 命令不可执行 | 权限不足,文件不是可执行文件 |
127 | 命令未找到 | command 拼错、镜像里没这个二进制 |
137 | SIGKILL | OOM 被杀,或 liveness 探针失败强杀 |
139 | SIGSEGV 段错误 | 程序崩溃 |
143 | SIGTERM | 正常停机信号(Pod 删除) |
command: ["sleep","3600"] 然后 kubectl exec -it 进去手动跑启动命令,看实际报错。
# 1. 确认是不是 OOM kubectl describe pod <pod> | grep -E "OOMKilled|137|Last State" # 2. 看节点 dmesg(节点级 OOM 才有) ssh <node> "dmesg -T | grep -i 'killed process'" # 3. 看 Pod 实际内存使用 kubectl top pod <pod> --containers
# 方案 A:调高 limits(如果应用确实需要) resources: requests: memory: "512Mi" limits: memory: "1Gi" # 之前是 512Mi 不够,翻倍 # 方案 B:优化应用(JVM 应用必看) env: - name: JAVA_OPTS value: "-Xmx768m -XX:MaxRAMPercentage=75" # 容器内 JVM 默认按宿主机内存算,会爆;必须显式设置
# 1. 看所有被驱逐的 Pod kubectl get pod -A | grep Evicted # 2. 看驱逐原因 kubectl describe pod <pod> | grep -A 3 "Status:" # 3. 看节点磁盘和内存 ssh <node> df -h df -i # 看 inode free -h # 4. 一键清理所有 Evicted 状态的 Pod kubectl get pod -A | grep Evicted | awk '{print $1, $2}' | \ xargs -n 2 kubectl delete pod -n
crictl rmi --prune (containerd) 或 docker system prune -af。
# 1. 优雅删除(给 0 秒宽限期) kubectl delete pod <pod> --grace-period=0 --force # 2. 如果还卡着,移除 finalizers(谨慎使用) kubectl patch pod <pod> -p '{"metadata":{"finalizers":null}}' # 3. 节点失联导致的,等 5 分钟会自动清理 # 或者直接删节点对象,Pod 会被一起清 kubectl delete node <dead-node> # 4. PVC 卡 Terminating kubectl patch pvc <pvc> -p '{"metadata":{"finalizers":null}}'
crictl ps 检查实际情况。
| 探针 | 失败后果 | 用途 |
|---|---|---|
startupProbe | 失败重启容器 | 慢启动应用,通过后才开始 liveness |
livenessProbe | 失败重启容器 | 判断"活着没",死了就重启 |
readinessProbe | 从 Service 摘除 | 判断"能接流量没",失败不重启 |
# 推荐配置(Java 应用为例) startupProbe: # 启动慢的应用必加 httpGet: path: /actuator/health port: 8080 failureThreshold: 30 # 30 * 10s = 5 分钟启动窗口 periodSeconds: 10 livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 periodSeconds: 20 # 不要太频繁,20-30s 即可 failureThreshold: 3 # 连续 3 次失败才重启 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 periodSeconds: 5 failureThreshold: 3