CrashLoopBackOff,观察重启间隔逐步拉长。--previous 日志、lastState 和 Events 判断容器为什么退出。安装 Docker、kind 和 kubectl。使用独立集群,避免影响已有工作负载。
kind create cluster --name lab-crash
kubectl get nodes
kubectl create namespace lab-crash
kubectl config set-context --current --namespace=lab-crash
创建一个启动后打印一行日志并 exit 1 的 Deployment:
kubectl apply -f - <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: crash-lab
spec:
replicas: 1
selector:
matchLabels:
app: crash-lab
template:
metadata:
labels:
app: crash-lab
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "echo starting; exit 1"]
EOF
kubectl get pods -l app=crash-lab
sleep 20
kubectl get pods -l app=crash-lab
kubectl describe pod -l app=crash-lab | sed -n '/State:/,/Events:/p'
kubectl logs -l app=crash-lab --previous
kubectl get pod -l app=crash-lab \
-o jsonpath='{.items[0].status.containerStatuses[0].lastState.terminated.exitCode}{"\n"}'
kubectl get events --sort-by=.lastTimestamp | tail -20
预期 Pod 先短暂 Running,随后变成 Error,最后显示 CrashLoopBackOff;RESTARTS 从 0 递增,重启间隔按 10 秒、20 秒、40 秒拉长;describe 的 Last State 显示 Terminated、Exit Code: 1;--previous 日志能看到 starting。
1 通常是应用错误;137 常见于 OOMKilled 或 SIGKILL;126/127 是命令不可执行或找不到;143 是收到 SIGTERM。kubectl logs --previous,当前容器可能还没产生日志,上一次容器的日志才有价值。describe 的 Last State、Reason 和 Events:OOMKilled 要查内存 limit,Error 要查应用日志,探针失败会显示 Liveness probe failed。restartPolicy: Always,容器正常结束也会被重启,最终同样显示 CrashLoopBackOff。把命令改成长期运行的进程,模拟修复应用启动逻辑:
kubectl patch deployment crash-lab --type=json \
-p '[{"op":"replace","path":"/spec/template/spec/containers/0/command","value":["sh","-c","echo fixed; sleep 3600"]}]'
kubectl rollout status deployment/crash-lab --timeout=120s
kubectl get pods -l app=crash-lab
kubectl logs -l app=crash-lab
Pod 应保持 Running 且重启次数不再增长。真实修复要针对退出码处理:补齐环境变量和 Secret、修应用启动异常、调大内存 limit、放宽 startupProbe,或修正镜像入口命令。
kubectl delete deployment crash-lab --ignore-not-found
kubectl delete namespace lab-crash --ignore-not-found
kind delete cluster --name lab-crash
如果使用现有集群,只删除 crash-lab Deployment 和 lab-crash 命名空间即可。
restartPolicy: Always 也会循环重启,这是很容易忽略的边界情况。--previous 日志?restartPolicy: Always,即使容器正常结束,kubelet 也会重启它,反复循环后进入退避状态。