0%

K8s 故障排查最佳实践:从入门到专家

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
# 步骤 1:看状态(10 秒)
kubectl get pods -n <namespace>

# 步骤 2:看详情(30 秒)
kubectl describe pod <pod-name> -n <namespace>

# 步骤 3:看日志(1 分钟)
kubectl logs <pod-name> -n <namespace>

# 步骤 4:看事件(1 分钟)
kubectl get events -n <namespace> --sort-by='.lastTimestamp'

# 步骤 5:看资源(1 分钟)
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
# 输出:
# openclaw-gateway-xxx 0/1 Pending 0 2m

排查过程

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
# 步骤 1:查看 Pod 详情
kubectl describe pod openclaw-gateway-xxx -n openclaw

# 输出关键信息:
# Events:
# Type Reason Age From Message
# ---- ------ ---- ---- -------
# Warning FailedScheduling 2m default-scheduler 0/3 nodes are available:
# 1 Insufficient cpu, 2 Insufficient memory.

# 步骤 2:查看节点资源
kubectl top nodes
# 输出:
# NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
# node-81 1950m 97% 3800Mi 95%
# node-82 1800m 90% 3500Mi 87%
# node-83 200m 10% 500Mi 12%

# 步骤 3:查看节点可分配资源
kubectl describe node node-83 | grep -A 5 "Allocated resources"
# 输出:
# Allocated resources:
# (Total limits may be over 100 percent, i.e., overcommitted.)
# Resource Requests Limits
# -------- -------- ------
# cpu 1800m (90%) 3800m (95%)
# memory 3Gi (75%) 6Gi (150%)

根因

  • node-81 和 node-82 资源已满
  • node-83 剩余资源不足(Pod 请求 2 CPU + 4Gi 内存)

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
# 方案 1:降低资源请求(临时)
kubectl set resources deployment openclaw-gateway \
-c openclaw \
--requests=cpu=500m,memory=1Gi \
--limits=cpu=1000m,memory=2Gi \
-n openclaw

# 方案 2:清理节点(推荐)
kubectl drain node-81 --ignore-daemonsets --delete-emptydir-data
kubectl cordon node-81

# 方案 3:扩容集群(长期)
# 添加新节点

教训

资源规划要提前,不要等到部署时才发现资源不足。建议预留 30% 资源缓冲。


3.2 案例 2:ImagePullBackOff - 镜像认证失败

现象

1
2
3
4
5
6
7
8
9
10
11
12
kubectl get pods -n openclaw
# 输出:
# openclaw-gateway-xxx 0/1 ImagePullBackOff 0 5m

kubectl describe pod openclaw-gateway-xxx -n openclaw
# 输出:
# Events:
# Warning Failed 4m kubelet Failed to pull image
# "hb.test/crystalforge/openclaw-cn-base:1.0.3-feishu":
# rpc error: code = Unknown desc = failed to pull and unpack image
# "hb.test/crystalforge/openclaw-cn-base:1.0.3-feishu":
# failed to resolve reference ...: unauthorized

排查过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 步骤 1:验证镜像是否存在
docker pull hb.test/crystalforge/openclaw-cn-base:1.0.3-feishu
# 输出:
# Error response from daemon: unauthorized

# 步骤 2:检查 Harbor 认证
docker login hb.test
# 输出:
# Login Succeeded

# 步骤 3:再次拉取
docker pull hb.test/crystalforge/openclaw-cn-base:1.0.3-feishu
# 成功!

# 步骤 4:检查 K8s ImagePullSecrets
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
# 步骤 1:创建 Docker Registry Secret
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

# 步骤 2:更新 Deployment
kubectl patch deployment openclaw-gateway -n openclaw \
--type='json' \
-p='[{"op": "add", "path": "/spec/template/spec/imagePullSecrets", "value": [{"name": "harbor-secret"}]}]'

# 步骤 3:重启 Pod
kubectl rollout restart deployment openclaw-gateway -n openclaw

# 步骤 4:验证
kubectl get pods -n openclaw
# 输出:Running ✅

教训

私有镜像仓库必须配置 imagePullSecrets。这是基础知识点,但我今晚还是忘了。


3.3 案例 3:CrashLoopBackOff - ConfigMap 缺失

现象

1
2
3
4
5
6
7
kubectl get pods -n openclaw
# 输出:
# openclaw-gateway-xxx 0/1 CrashLoopBackOff 4 10m

kubectl logs openclaw-gateway-xxx -n openclaw
# 输出:
# Error: open /config/openclaw.json: no such file or directory

排查过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 步骤 1:查看 Pod 详情
kubectl describe pod openclaw-gateway-xxx -n openclaw

# 输出关键信息:
# Mounts:
# /config/openclaw.json from config-volume (path=openclaw.json)
# Volumes:
# config-volume:
# Type: ConfigMap (a volume populated by a ConfigMap)
# Name: openclaw-config
# Optional: false

# 步骤 2:检查 ConfigMap
kubectl get configmap openclaw-config -n openclaw
# 输出:Error from server (NotFound): configmaps "openclaw-config" not found

# 步骤 3:查找现有 ConfigMap
kubectl get configmaps -n openclaw
# 输出:No resources found

根因

  • 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
# 方案 1:创建 ConfigMap(从文件)
kubectl create configmap openclaw-config \
--from-file=/home/johnzok/.openclaw/workspace/openclaw3-final-config.json=openclaw.json \
-n openclaw

# 方案 2:创建 ConfigMap(从字面)
kubectl create configmap openclaw-config \
--from-literal=openclaw.json='{"models":{"default":"bailian/qwen3.5-plus"}}' \
-n openclaw

# 方案 3:修改 Deployment(不依赖 ConfigMap)
kubectl patch deployment openclaw-gateway -n openclaw \
--type='json' \
-p='[{"op": "remove", "path": "/spec/template/spec/volumes/5"}]'

# 重启 Pod
kubectl rollout restart deployment openclaw-gateway -n openclaw

# 验证
kubectl get pods -n openclaw
# 输出:Running ✅

教训

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
# 输出:
# openclaw-gateway-xxx 0/1 OOMKilled 5 15m

kubectl describe pod openclaw-gateway-xxx -n openclaw
# 输出关键信息:
# Last State: Terminated
# Reason: OOMKilled
# Exit Code: 137
# Limits:
# memory: 2Gi
# Requests:
# memory: 1Gi

排查过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 步骤 1:查看内存使用趋势
kubectl top pods -n openclaw --containers
# 输出:
# NAME CPU(cores) MEMORY(bytes)
# openclaw-gateway-xxx 500m 1950Mi ← 接近 2Gi 限制

# 步骤 2:查看历史内存使用
kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/openclaw/pods | jq

# 步骤 3:检查应用内存配置
# OpenClaw 是 Python 应用,检查 Python 进程
kubectl exec -it openclaw-gateway-xxx -n openclaw -- ps aux | grep python
# 输出:
# python3 占用 1.8Gi 内存

根因

  • 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
# 输出:Running ✅

# 监控内存使用
kubectl top pods -n openclaw
# 输出:稳定在 2.5Gi 左右 ✅

教训

内存限制要留足余量。建议:限制 = 峰值使用 * 1.5。OpenClaw 实际测试需要 2.5Gi,所以设置为 4Gi。


3.5 案例 5:权限不足 - RBAC 问题

现象

1
2
3
# OpenClaw 尝试创建 ConfigMap
kubectl auth can-i create configmaps -n openclaw --as=system:serviceaccount:openclaw:openclaw-sa
# 输出:no

排查过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 步骤 1:查看 ServiceAccount
kubectl get sa openclaw-sa -n openclaw
# 输出:存在

# 步骤 2:查看 RoleBinding
kubectl get rolebinding -n openclaw
# 输出:openclaw-binding

# 步骤 3:查看 Role
kubectl get role openclaw-role -n openclaw -o yaml
# 输出:
# rules:
# - apiGroups: [""]
# resources: ["pods", "services"] ← 缺少 configmaps
# verbs: ["get", "list", "create"]

# 步骤 4:验证权限
kubectl auth can-i create configmaps -n openclaw \
--as=system:serviceaccount:openclaw:openclaw-sa
# 输出:no

根因

  • Role 中缺少 configmaps 权限
  • OpenClaw 无法创建 ConfigMap

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
# 更新 Role
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
# 输出:yes ✅

# 重启 OpenClaw
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
# 查看所有 Pod
k9s

# 查看特定命名空间
k9s -n openclaw

# 查看日志(选中 Pod 后按 'l')
k9s → 选择 Pod → 按 'l'

# 查看事件(选中 Pod 后按 'd')
k9s → 选择 Pod → 按 'd'

效率提升

  • ✅ 无需记忆复杂命令
  • ✅ 实时刷新状态
  • ✅ 一键查看日志/事件

4.2 使用 stern 查看多 Pod 日志

问题

1
2
3
4
# 多个 Pod 时,需要分别查看日志
kubectl logs pod-1
kubectl logs pod-2
kubectl logs pod-3

解决

1
2
3
4
5
6
7
8
9
10
11
12
# 安装 stern
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/

# 查看所有匹配 Pod 的日志
stern -n openclaw openclaw-gateway

# 输出:
# + openclaw-gateway-xxx › python3
# + openclaw-gateway-yyy › python3
# [实时显示所有 Pod 日志]

4.3 使用 jq 解析 JSON

问题

1
2
kubectl get pod openclaw-gateway-xxx -n openclaw -o json
# 输出几百行 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
# 修改了 Deployment,但不知道改了什么
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
# k8s-diagnose.sh

NAMESPACE="${1:-default}"
POD_NAME="${2:-}"

echo "🔍 K8s 故障诊断"
echo "命名空间:$NAMESPACE"
echo "Pod: ${POD_NAME:-全部}"
echo ""

# 1. Pod 状态
echo "1️⃣ Pod 状态:"
kubectl get pods -n $NAMESPACE ${POD_NAME:+"$POD_NAME"}

# 2. 详情
if [ -n "$POD_NAME" ]; then
echo ""
echo "2️⃣ Pod 详情:"
kubectl describe pod $POD_NAME -n $NAMESPACE | grep -A 10 "Events:"
fi

# 3. 日志
if [ -n "$POD_NAME" ]; then
echo ""
echo "3️⃣ 最近日志:"
kubectl logs $POD_NAME -n $NAMESPACE --tail=20
fi

# 4. 资源使用
echo ""
echo "4️⃣ 资源使用:"
kubectl top pods -n $NAMESPACE 2>/dev/null || echo "Metrics 不可用"

# 5. 建议
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 核心要点

  1. 5 步诊断法:状态 → 详情 → 日志 → 事件 → 资源
  2. 常见问题速查:Pending、ImagePullBackOff、CrashLoopBackOff、OOMKilled
  3. 工具提升效率:k9s、stern、jq
  4. 实战经验: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 部署实战