K8s 故障排查最佳实践:从入门到专家
写在前面:这篇文章源于今晚(2026-03-10)的真实战斗。从 21:00 到 23:00,我们经历了 Pod Pending、ImagePullBackOff、ConfigMap 缺失、权限不足等 5 个典型问题。这是完整的排查过程和解决方案。
一、故障排查的核心思维
1.1 我的排查哲学
核心原则:
1 2 3 4
| 1. 从外到内 - 先看现象,再查原因 2. 从简到繁 - 先查常见问题,再查复杂问题 3. 从新到旧 - 先查最近变更,再查历史配置 4. 大胆假设,小心验证 - 提出假设,立即验证
|
排查流程:
1
| 现象观察 → 信息收集 → 假设提出 → 验证假设 → 定位根因 → 解决问题 → 总结复盘
|
1.2 5 步诊断法(我总结的)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| kubectl get pods -n <namespace>
kubectl describe pod <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace>
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
kubectl top pods -n <namespace> kubectl top nodes
|
90% 的问题在这 5 步内定位!
二、常见问题速查表
2.1 Pod 状态问题
| 状态 |
可能原因 |
排查命令 |
解决方案 |
| Pending |
资源不足、PVC 调度失败 |
kubectl describe pod |
扩容节点、检查 StorageClass |
| ContainerCreating |
镜像拉取失败、网络问题 |
kubectl describe pod |
检查镜像、网络策略 |
| CrashLoopBackOff |
应用崩溃、配置错误 |
kubectl logs --previous |
修复代码、检查配置 |
| OOMKilled |
内存不足 |
kubectl describe pod |
增加内存限制 |
| Evicted |
节点资源压力 |
kubectl describe pod |
清理节点、调整 Pod 优先级 |
2.2 镜像问题
| 错误 |
原因 |
解决方案 |
| ImagePullBackOff |
镜像不存在、认证失败 |
检查镜像名称、配置 Secret |
| ErrImagePull |
网络超时、仓库不可达 |
检查网络、使用镜像加速 |
| ErrImageNeverPull |
镜像策略限制 |
修改 imagePullPolicy |
2.3 配置问题
| 错误 |
原因 |
解决方案 |
| ConfigMap not found |
ConfigMap 不存在 |
创建 ConfigMap |
| Secret not found |
Secret 不存在 |
创建 Secret |
| Volume mount failed |
PVC 未绑定 |
检查 PVC 状态 |
三、实战案例:今晚的真实战斗
3.1 案例 1:Pod Pending - 资源不足
现象:
1 2 3
| kubectl get pods -n openclaw
|
排查过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| kubectl describe pod openclaw-gateway-xxx -n openclaw
kubectl top nodes
kubectl describe node node-83 | grep -A 5 "Allocated resources"
|
根因:
- node-81 和 node-82 资源已满
- node-83 剩余资源不足(Pod 请求 2 CPU + 4Gi 内存)
解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13
| kubectl set resources deployment openclaw-gateway \ -c openclaw \ --requests=cpu=500m,memory=1Gi \ --limits=cpu=1000m,memory=2Gi \ -n openclaw
kubectl drain node-81 --ignore-daemonsets --delete-emptydir-data kubectl cordon node-81
|
教训:
资源规划要提前,不要等到部署时才发现资源不足。建议预留 30% 资源缓冲。
3.2 案例 2:ImagePullBackOff - 镜像认证失败
现象:
1 2 3 4 5 6 7 8 9 10 11 12
| kubectl get pods -n openclaw
kubectl describe pod openclaw-gateway-xxx -n openclaw
|
排查过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| docker pull hb.test/crystalforge/openclaw-cn-base:1.0.3-feishu
docker login hb.test
docker pull hb.test/crystalforge/openclaw-cn-base:1.0.3-feishu
kubectl get deployment openclaw-gateway -n openclaw -o yaml | grep -A 5 imagePullSecrets
|
根因:
- Harbor 是私有仓库,需要认证
- Deployment 没有配置 imagePullSecrets
解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| kubectl create secret docker-registry harbor-secret \ --docker-server=hb.test \ --docker-username=crystalcreator \ --docker-password='glpat-FxE8Ka5HaApPLHnAQDtz' \ --docker-email=admin@example.com \ -n openclaw
kubectl patch deployment openclaw-gateway -n openclaw \ --type='json' \ -p='[{"op": "add", "path": "/spec/template/spec/imagePullSecrets", "value": [{"name": "harbor-secret"}]}]'
kubectl rollout restart deployment openclaw-gateway -n openclaw
kubectl get pods -n openclaw
|
教训:
私有镜像仓库必须配置 imagePullSecrets。这是基础知识点,但我今晚还是忘了。
3.3 案例 3:CrashLoopBackOff - ConfigMap 缺失
现象:
1 2 3 4 5 6 7
| kubectl get pods -n openclaw
kubectl logs openclaw-gateway-xxx -n openclaw
|
排查过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| kubectl describe pod openclaw-gateway-xxx -n openclaw
kubectl get configmap openclaw-config -n openclaw
kubectl get configmaps -n openclaw
|
根因:
- Deployment 引用了 ConfigMap
openclaw-config
- 但 ConfigMap 不存在
解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| kubectl create configmap openclaw-config \ --from-file=/home/johnzok/.openclaw/workspace/openclaw3-final-config.json=openclaw.json \ -n openclaw
kubectl create configmap openclaw-config \ --from-literal=openclaw.json='{"models":{"default":"bailian/qwen3.5-plus"}}' \ -n openclaw
kubectl patch deployment openclaw-gateway -n openclaw \ --type='json' \ -p='[{"op": "remove", "path": "/spec/template/spec/volumes/5"}]'
kubectl rollout restart deployment openclaw-gateway -n openclaw
kubectl get pods -n openclaw
|
教训:
ConfigMap 必须在 Deployment 之前创建。使用 Helm 或 Kustomize 可以管理依赖顺序。
3.4 案例 4:OOMKilled - 内存不足
现象:
1 2 3 4 5 6 7 8 9 10 11 12 13
| kubectl get pods -n openclaw
kubectl describe pod openclaw-gateway-xxx -n openclaw
|
排查过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| kubectl top pods -n openclaw --containers
kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/openclaw/pods | jq
kubectl exec -it openclaw-gateway-xxx -n openclaw -- ps aux | grep python
|
根因:
- OpenClaw 启动后内存使用约 1.8-2.2Gi
- 限制设置为 2Gi,导致 OOM
解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| kubectl set resources deployment openclaw-gateway \ -c openclaw \ --requests=cpu=500m,memory=2Gi \ --limits=cpu=2000m,memory=4Gi \ -n openclaw
kubectl rollout restart deployment openclaw-gateway -n openclaw kubectl get pods -n openclaw
kubectl top pods -n openclaw
|
教训:
内存限制要留足余量。建议:限制 = 峰值使用 * 1.5。OpenClaw 实际测试需要 2.5Gi,所以设置为 4Gi。
3.5 案例 5:权限不足 - RBAC 问题
现象:
1 2 3
| kubectl auth can-i create configmaps -n openclaw --as=system:serviceaccount:openclaw:openclaw-sa
|
排查过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| kubectl get sa openclaw-sa -n openclaw
kubectl get rolebinding -n openclaw
kubectl get role openclaw-role -n openclaw -o yaml
kubectl auth can-i create configmaps -n openclaw \ --as=system:serviceaccount:openclaw:openclaw-sa
|
根因:
- Role 中缺少 configmaps 权限
- OpenClaw 无法创建 ConfigMap
解决方案:
1 2 3 4 5 6 7 8 9 10 11 12
| kubectl patch role openclaw-role -n openclaw \ --type='json' \ -p='[{"op": "add", "path": "/rules/0/resources/-", "value": "configmaps"}]'
kubectl auth can-i create configmaps -n openclaw \ --as=system:serviceaccount:openclaw:openclaw-sa
kubectl rollout restart deployment openclaw-gateway -n openclaw
|
教训:
RBAC 权限要遵循最小权限原则,但也要确保应用所需权限完整。使用 kubectl auth can-i 验证权限。
四、专家级排查技巧
4.1 使用 k9s 提升效率
k9s 是什么?
- TUI(文本用户界面)K8s 管理工具
- 比 kubectl 更直观、更高效
安装:
1 2 3
| wget https://github.com/derailed/k9s/releases/latest/download/k9s_Linux_x86_64.tar.gz tar -xzf k9s_Linux_x86_64.tar.gz sudo mv k9s /usr/local/bin/
|
使用:
1 2 3 4 5 6 7 8 9 10 11
| k9s
k9s -n openclaw
k9s → 选择 Pod → 按 'l'
k9s → 选择 Pod → 按 'd'
|
效率提升:
- ✅ 无需记忆复杂命令
- ✅ 实时刷新状态
- ✅ 一键查看日志/事件
4.2 使用 stern 查看多 Pod 日志
问题:
1 2 3 4
| kubectl logs pod-1 kubectl logs pod-2 kubectl logs pod-3
|
解决:
1 2 3 4 5 6 7 8 9 10 11 12
| wget https://github.com/stern/stern/releases/latest/download/stern_1.24.0_linux_amd64.tar.gz tar -xzf stern_1.24.0_linux_amd64.tar.gz sudo mv stern /usr/local/bin/
stern -n openclaw openclaw-gateway
|
4.3 使用 jq 解析 JSON
问题:
1 2
| kubectl get pod openclaw-gateway-xxx -n openclaw -o json
|
解决:
1 2 3 4 5 6 7 8 9 10 11
| kubectl get pod openclaw-gateway-xxx -n openclaw -o json | \ jq '.status.phase'
kubectl get pod openclaw-gateway-xxx -n openclaw -o json | \ jq '.status.containerStatuses[] | {name: .name, ready: .ready, state: .state}'
kubectl get events -n openclaw -o json | \ jq '.items[] | select(.involvedObject.kind=="Pod") | {reason: .reason, message: .message}'
|
4.4 使用 diff 对比配置
问题:
1 2
| kubectl edit deployment openclaw-gateway -n openclaw
|
解决:
1 2 3 4 5 6 7 8 9 10 11
| kubectl get deployment openclaw-gateway -n openclaw -o yaml > before.yaml
kubectl edit deployment openclaw-gateway -n openclaw
kubectl get deployment openclaw-gateway -n openclaw -o yaml > after.yaml
diff before.yaml after.yaml
|
五、排查工具箱
5.1 必备命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| kubectl get pods -n <namespace> kubectl get deployments -n <namespace> kubectl get services -n <namespace>
kubectl describe pod <pod-name> -n <namespace> kubectl describe deployment <deploy-name> -n <namespace>
kubectl logs <pod-name> -n <namespace> kubectl logs <pod-name> -n <namespace> --previous kubectl logs -f <pod-name> -n <namespace>
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
kubectl top pods -n <namespace> kubectl top nodes
kubectl exec -it <pod-name> -n <namespace> -- /bin/bash
kubectl port-forward <pod-name> -n <namespace> 8080:80
|
5.2 排查脚本
一键诊断脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #!/bin/bash
NAMESPACE="${1:-default}" POD_NAME="${2:-}"
echo "🔍 K8s 故障诊断" echo "命名空间:$NAMESPACE" echo "Pod: ${POD_NAME:-全部}" echo ""
echo "1️⃣ Pod 状态:" kubectl get pods -n $NAMESPACE ${POD_NAME:+"$POD_NAME"}
if [ -n "$POD_NAME" ]; then echo "" echo "2️⃣ Pod 详情:" kubectl describe pod $POD_NAME -n $NAMESPACE | grep -A 10 "Events:" fi
if [ -n "$POD_NAME" ]; then echo "" echo "3️⃣ 最近日志:" kubectl logs $POD_NAME -n $NAMESPACE --tail=20 fi
echo "" echo "4️⃣ 资源使用:" kubectl top pods -n $NAMESPACE 2>/dev/null || echo "Metrics 不可用"
echo "" echo "💡 建议:" echo "- 查看日志:kubectl logs -n $NAMESPACE <pod-name>" echo "- 查看详情:kubectl describe pod -n $NAMESPACE <pod-name>" echo "- 查看事件:kubectl get events -n $NAMESPACE --sort-by='.lastTimestamp'"
|
六、总结
6.1 核心要点
- 5 步诊断法:状态 → 详情 → 日志 → 事件 → 资源
- 常见问题速查:Pending、ImagePullBackOff、CrashLoopBackOff、OOMKilled
- 工具提升效率:k9s、stern、jq
- 实战经验:5 个真实案例,每个都是血泪教训
6.2 专家建议
✅ 推荐做法:
- 使用 k9s 提升排查效率
- 编写排查脚本,自动化诊断
- 记录排查过程,形成知识库
- 定期复盘,总结常见问题
❌ 避免做法:
- 不要盲目重启 Pod(先查原因)
- 不要忽略事件信息(通常包含根因)
- 不要只看日志不看资源(可能是资源问题)
- 不要跳过基础检查(网络、权限、配置)
6.3 后续学习
推荐资源:
进阶主题:
- 网络故障排查(CNI、NetworkPolicy)
- 存储故障排查(PVC、PV、StorageClass)
- 性能故障排查(CPU、内存、IO)
- 安全故障排查(RBAC、NetworkPolicy、PodSecurityPolicy)
作者:John,高级技术架构师,CrystalForge 项目负责人
时间:2026-03-11 01:30
地点:深圳
项目:OpenClaw K8s 部署实战