K8s Lab 把当前仓库文档整理成一个可阅读的网页站点

Repository Reading Site

故障排查实验室 — 面试最实战的能力

面对任何 K8s 故障,按这个顺序排查: --- 容器进程退出(exit code 非 0)→ kubelet 按 `restartPolicy` 重启 → 又退出 → 退避重启(间隔 10s, 20s, 40s, 80s, 160s, 最大 300s) **常见原因:** 配置错误、依赖服务不可达、缺少环境变量、启动命令错误 **面试答法:** "看 de

Markdownphase-4/01-troubleshooting-lab.md2026年4月9日 13:36

故障排查实验室 — 面试最实战的能力

排查方法论

面对任何 K8s 故障,按这个顺序排查:

1. kubectl get pods -o wide        → 看状态、哪个节点
2. kubectl describe pod <name>     → 看 Events、Conditions
3. kubectl logs <pod>              → 看应用日志
4. kubectl logs <pod> --previous   → 看上一次崩溃的日志
5. kubectl get events --sort-by=.lastTimestamp  → 看集群事件
6. kubectl exec -it <pod> -- sh   → 进容器排查
7. kubectl top pods/nodes          → 看资源使用
8. journalctl -u kubelet           → 看节点级日志

场景 1: CrashLoopBackOff

制造故障

spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh", "-c", "echo starting; exit 1"]   # 启动即退出

现象

NAME         READY   STATUS             RESTARTS      AGE
crash-demo   0/1     CrashLoopBackOff   1 (10s ago)   16s

排查

# describe 看到:Exit Code: 1,Restart Count 持续增加
kubectl describe pod crash-demo | grep -A5 "Last State"
    Last State:  Terminated
      Reason:    Error
      Exit Code: 1

# logs 看到应用输出
kubectl logs crash-demo
starting

# --previous 看上一次崩溃的日志(如果容器重启太快来不及看)
kubectl logs crash-demo --previous

原因分析

容器进程退出(exit code 非 0)→ kubelet 按 restartPolicy 重启 → 又退出 → 退避重启(间隔 10s, 20s, 40s, 80s, 160s, 最大 300s)

常见原因: 配置错误、依赖服务不可达、缺少环境变量、启动命令错误

面试答法: "看 describe 的 Exit Code 和 Reason,看 logs 的应用错误信息。Exit Code 137 = OOMKilled,Exit Code 1 = 应用错误,Exit Code 0 但还是 CrashLoop = 主进程退出了(不是长驻进程)。"


场景 2: ImagePullBackOff

制造故障

image: nginx:99.99.99-nonexistent   # 不存在的 tag

排查

kubectl describe pod bad-image | grep Events -A5
  Warning  Failed  10s  kubelet  Failed to pull image "nginx:99.99.99-nonexistent": not found

常见原因

Events 信息 原因
not found 镜像或 tag 不存在
unauthorized 没有 imagePullSecret
i/o timeout 网络不通或 registry 被墙
manifest unknown tag 存在但平台不匹配(如 arm64 镜像在 amd64 节点)

场景 3: Pending(资源不足)

制造故障

resources:
  requests:
    memory: 100Gi    # 没有节点有 100G 内存

排查

kubectl describe pod greedy-pod | grep Events -A3
  Warning  FailedScheduling  default-scheduler
    0/5 nodes are available:
    1 node(s) had untolerated taint {control-plane},
    4 Insufficient memory.

关键: Scheduler 的 FailedScheduling 事件会精确告诉你为什么调度不上去。

常见 Pending 原因

事件信息 原因 解决
Insufficient cpu/memory 资源不够 降低 requests 或加节点
no nodes match nodeSelector 没有匹配标签的节点 检查标签
untolerated taint 节点有 taint 加 toleration
PVC not bound 存储没就绪 检查 StorageClass/PV

场景 4: Service 不通(Endpoints 为空)

制造故障

# Service 的 selector 和 Pod 的 label 不匹配
spec:
  selector:
    app: WRONG-LABEL    # Pod 实际标签是 app: web-test

排查

# 关键:检查 Endpoints
$ kubectl get endpoints broken-svc
NAME         ENDPOINTS
broken-svc   <none>       ← 空!没有后端 Pod

# 对比 selector 和 labels
$ kubectl get svc broken-svc -o jsonpath="{.spec.selector}"
{"app":"WRONG-LABEL"}

$ kubectl get pods --show-labels | grep web-test
web-test-xxx   app=web-test    ← 不匹配!

面试答法: "Service 不通第一步看 Endpoints。Endpoints 为空说明 selector 没匹配到 Pod。对比 Service 的 selector 和 Pod 的 labels。"


场景 5: Node NotReady

制造故障

ssh root@<node> "systemctl stop kubelet"

现象(约 80 秒后)

hk652699382121    NotReady   <none>   3h   v1.30.14

排查

kubectl describe node hk652699382121 | grep Conditions -A10
  Ready   False   KubeletNotReady   container runtime network not ready

常见原因

原因 检查方法
kubelet 挂了 systemctl status kubelet
容器运行时挂了 systemctl status containerd
磁盘满了 df -h(kubelet 有磁盘压力阈值)
内存不足 free -m
网络断了 ping <master-ip>

场景 6: OOMKilled

制造故障

resources:
  limits:
    memory: 10Mi    # 给极小的内存
command: ["tail", "/dev/zero"]    # 占满内存

排查

kubectl describe pod oom-demo | grep "Last State"
    Last State: Terminated
      Reason:   OOMKilled        ← Linux OOM Killer 杀掉了
      Exit Code: 137             ← 128 + 9 (SIGKILL)

面试重点: "CPU 超过 limits 会被节流(throttle),进程变慢但不会被杀。Memory 超过 limits 会被 OOMKill,进程直接终止。所以 CPU limits 可以设高一点(允许 burst),Memory limits 要精确。"


场景 7: 滚动更新卡住

制造故障

kubectl set image deployment/nginx nginx=nginx:999-broken

排查

$ kubectl rollout status deployment/nginx --timeout=3s
Waiting for deployment rollout to finish: 1 out of 3 new replicas have been updated...
error: timed out

$ kubectl get pods -l app=nginx
nginx-7b97df8d44-xxx   nginx:1.25         Running   true    ← 旧 Pod 还在
nginx-dcd499979-xxx    nginx:999-broken   Pending   false   ← 新 Pod 起不来

解决

kubectl rollout undo deployment/nginx    # 秒级回滚

原理: maxUnavailable=25% 保证至少 75% 的 Pod 保持运行。新 Pod 起不来时,旧 Pod 不会被杀,业务不中断。这就是滚动更新的安全网。


排查必备命令速查

# Pod 级别
kubectl get pods -o wide                          # 状态、节点、IP
kubectl describe pod <name>                       # 事件、条件
kubectl logs <pod> [-c container] [--previous]   # 日志
kubectl exec -it <pod> -- sh                      # 进容器
kubectl top pods                                  # CPU/内存

# 节点级别
kubectl get nodes                                 # 状态
kubectl describe node <name>                      # 条件、资源
kubectl top nodes                                 # 资源使用
kubectl drain <node> --ignore-daemonsets          # 维护排空

# 集群级别
kubectl get events --sort-by=.lastTimestamp -A    # 全局事件
kubectl get componentstatuses                     # 控制面状态

# 网络排查
kubectl get endpoints <svc>                       # Service 后端
kubectl exec <pod> -- nslookup <svc>             # DNS
kubectl exec <pod> -- curl <url>                  # 连通性

# 节点上(SSH 进去)
journalctl -u kubelet -f                          # kubelet 日志
crictl ps -a                                      # 容器状态
crictl logs <container-id>                        # 容器日志

02-interview-guide.md