前言
前面已经整理了不少对象:Pod、Deployment、Service、ConfigMap、Secret、Volume、Namespace、Ingress。对象多了之后,另一个问题会变得很现实:
出问题时,我到底先看哪里?
刚开始很容易看到一个 Pod 不正常,就直接冲到日志里找异常。日志当然重要,但 Kubernetes 的问题不一定都在应用日志里。
例如:
1 | Pod 没启动 |
所以我现在更倾向先分层看:
1 | 对象状态 |
这篇就整理一个基础排障思路。
先看资源整体状态
排障第一步,我通常先看对象现在处于什么状态。
1 | kubectl get pods |
带上 Namespace:
1 | kubectl get pods -n demo-prod |
看 Pod 时,几个状态比较常见:
1 | Pending |
这里的状态只是入口,不是最终原因。
1 | 看到 ImagePullBackOff |
describe:看事件和详细状态
kubectl describe 是我排查时最常用的命令之一。
1 | kubectl describe pod <pod-name> |
它会展示:
- Pod 基本信息;
- 所在节点;
- 容器状态;
- 最近一次退出原因;
- 探针失败信息;
- 事件 Events。
事件很关键,因为它记录的是 Kubernetes 组件在处理这个对象时发生了什么。
例如:
1 | Failed to pull image |
这些信息不一定出现在应用日志里。
我会把 describe 理解成“对象病历”:应用日志是病人自己说哪里疼,事件是系统记录检查和处理过程。
logs:看容器输出
如果容器已经启动过,就可以看日志:
1 | kubectl logs <pod-name> |
如果 Pod 里有多个容器,需要指定容器名:
1 | kubectl logs <pod-name> -c demo-api |
如果容器重启过,想看上一次容器的日志:
1 | kubectl logs <pod-name> --previous |
这对 CrashLoopBackOff 很有用。
1 | 容器启动 |
查看实时日志:
1 | kubectl logs -f <pod-name> |
Deployment 多副本时,可以按标签看:
1 | kubectl logs -l app=demo-api --tail=100 |
但日志量大时不要盲目全量拉,先缩小范围。
events:看集群发生过什么
事件可以单独查看:
1 | kubectl get events |
按 Namespace:
1 | kubectl get events -n demo-prod --sort-by=.lastTimestamp |
事件适合看这类问题:
- 调度失败;
- 镜像拉取失败;
- 探针失败;
- Volume 挂载失败;
- Pod 被驱逐;
- 控制器创建或删除资源。
例如 Pod Pending,可以看事件里是否有:
1 | 0/3 nodes are available: insufficient cpu |
这说明不是应用代码问题,而是调度层资源不足。
1 | Pod Pending |
按对象层次排查
我现在会把排障按对象层次拆开。
Deployment 层
先看:
1 | kubectl get deployment demo-api |
关注:
- 期望副本数;
- 可用副本数;
- 是否正在发布;
- 是否超过发布期限;
- 新旧 ReplicaSet 状态。
如果 Deployment 没达到期望状态,就往下看 ReplicaSet 和 Pod。
1 | Deployment 未就绪 |
Pod 层
看:
1 | kubectl get pods -l app=demo-api |
关注:
- Pod 是否调度到节点;
- 容器是否启动;
- 是否重启;
- 退出原因;
- 探针是否失败;
- 镜像是否拉取成功。
Service 层
看:
1 | kubectl describe service demo-api |
关注:
- selector 是否匹配 Pod labels;
- EndpointSlice 是否有地址;
- 端口和 targetPort 是否正确;
- Pod 是否 Ready。
Service 不通时,我不会先怀疑网络,而是先看后端列表有没有。
Ingress 层
看:
1 | kubectl describe ingress demo-ingress |
关注:
- host/path 是否匹配;
- IngressClass 是否正确;
- backend Service 是否存在;
- Service 后端是否可用;
- Ingress Controller 是否运行。
常见问题一:ImagePullBackOff
看到:
1 | ImagePullBackOff |
排查线:
1 | 镜像名是否正确? |
命令:
1 | kubectl describe pod <pod-name> |
事件里通常会告诉你更具体原因,比如认证失败、镜像不存在、连接超时。
这类问题通常发生在容器启动前,所以应用日志里可能什么都没有。
常见问题二:CrashLoopBackOff
CrashLoopBackOff 表示容器反复启动失败,Kubernetes 在退避重试。
排查线:
1 | 看当前日志 |
命令:
1 | kubectl logs <pod-name> |
常见原因:
- 启动命令写错;
- 配置缺失;
- Secret 或 ConfigMap key 不存在;
- 应用连接依赖失败后直接退出;
- 内存超过 limit 被 OOMKilled。
如果看到:
1 | Reason: OOMKilled |
就要回到资源限制那篇的思路,看内存 limit 和应用内存使用。
常见问题三:Pod 一直 Pending
Pod Pending 不一定是容器问题,因为容器可能根本还没启动。
排查线:
1 | 调度失败? |
命令:
1 | kubectl describe pod <pod-name> |
事件里可能看到:
1 | FailedScheduling |
这些都属于调度或依赖资源问题,不是应用日志能解释的。
常见问题四:Service 有但访问不通
排查线:
1 | Service selector |
命令:
1 | kubectl describe service demo-api |
常见原因:
- selector 和 labels 不匹配;
- Pod 没有 Ready;
- targetPort 写错;
- 应用只监听了
127.0.0.1; - Service 和 Pod 不在预期 Namespace。
这里我会特别注意 Namespace。有时 service 在 dev,Pod 在 default,名字看起来一样,但根本不是一组对象。
常见问题五:发布卡住
排查线:
1 | rollout status |
命令:
1 | kubectl rollout status deployment/demo-api |
发布卡住常见原因:
- 新镜像拉取失败;
- 新 Pod readiness 一直失败;
- 新 Pod CrashLoopBackOff;
- 资源不足无法调度;
- maxUnavailable/maxSurge 配置太保守或不合适。
发布问题本质上还是 Pod 问题,只是被 Deployment 包了一层流程。
不要只看最后一层
Kubernetes 排障最容易急的是:看到接口不通,就直接看应用日志;看到 Pod 不正常,就直接改 YAML。
我现在会先把链路画出来:
1 | 用户请求 |
每次只确认一层:
1 | 入口规则对不对? |
这样排查速度反而更快,因为不会在错误层面停太久。
小结
这一篇整理下来,我对 Kubernetes 基础排障的理解可以概括成几句话:
kubectl get先看整体状态;kubectl describe看对象详情和事件;kubectl logs看容器日志;--previous适合查看上一次崩溃前日志;- Events 能解释很多调度、拉镜像、挂载和探针问题;
- Deployment 问题要继续往 ReplicaSet 和 Pod 看;
- Service 不通先看 selector、EndpointSlice、Pod Ready 和端口;
- Pending、ImagePullBackOff、CrashLoopBackOff 指向不同排查方向;
- 排障时按链路逐层确认,比直接猜原因更可靠。
下一批准备进入安全和更高级的工作负载对象:ServiceAccount、RBAC、SecurityContext、NetworkPolicy,以及 DaemonSet、Job、CronJob、StatefulSet。
参考资料
- Debug Applications:https://kubernetes.io/docs/tasks/debug/debug-application/
- Debug Pods:https://kubernetes.io/docs/tasks/debug/debug-application/debug-pods/
- kubectl logs:https://kubernetes.io/docs/reference/kubectl/generated/kubectl_logs/
- kubectl describe:https://kubernetes.io/docs/reference/kubectl/generated/kubectl_describe/
- Troubleshooting Applications:https://kubernetes.io/docs/tasks/debug/debug-application/