Appearance
Pod 生命周期
Pod 是 Kubernetes 最小调度单元。排查 K8s 服务时,Pod 生命周期是最常看的部分:是否被调度、是否拉动镜像、是否挂载成功、容器是否启动、探针是否通过、退出后是否重启。
Pod 从创建到运行
常见阶段:
| 阶段 | 说明 | 常见问题 |
|---|---|---|
| Pending | 尚未完成调度或依赖准备 | 资源不足、污点、PVC 未绑定 |
| ContainerCreating | 节点正在创建容器 | 拉镜像、挂载卷、CNI 分配 IP |
| Running | 至少一个容器运行中 | 应用不一定 Ready |
| Succeeded | 所有容器正常结束 | Job 常见 |
| Failed | 容器异常结束且不再重启 | Job 或 restartPolicy 相关 |
Running 只是容器层状态,不等于业务可用。Service 是否接流量主要看 readiness probe。
initContainer
initContainer 在业务容器之前执行,全部成功后才会启动普通容器:
yaml
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
initContainers:
- name: wait-db
image: busybox:1.36
command: ["sh", "-c", "until nc -z mysql 3306; do sleep 2; done"]
# 等待数据库端口可连,只适合做粗略依赖检查
containers:
- name: app
image: nginx:1.26initContainer 常用于初始化目录、等待依赖、生成配置、迁移简单文件。数据库 schema 迁移这类操作要谨慎——失败重试和并发执行都要设计清楚,initContainer 只保证顺序,不保证幂等。
重启策略
Pod 级别有 restartPolicy:
| 策略 | 含义 |
|---|---|
Always | 容器退出后总是重启——Deployment 默认 |
OnFailure | 非 0 退出码才重启——Job 常见 |
Never | 退出后不重启 |
Deployment 里的 Pod 通常是 Always。Job 更常用 OnFailure 或 Never,否则任务失败后的行为难以判断。
三种探针
| 探针 | 作用 | 典型用法 |
|---|---|---|
| startupProbe | 判断应用是否启动完成 | 启动慢的服务用它保护,等启动完成后再让 livenessProbe 接管 |
| readinessProbe | 判断是否可以接流量 | 失败后从 Service 后端摘除,不影响容器进程 |
| livenessProbe | 判断是否需要重启容器 | 失败后 kubelet 重启容器——是修复手段,不要因为外部依赖挂了就杀容器 |
yaml
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30 # 最多等 30 × 2 秒
periodSeconds: 2
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
failureThreshold: 3没有 startupProbe 时,启动慢的应用可能被 livenessProbe 反复重启——应用还在初始化,liveness 已经判定失败。startupProbe 的作用就是覆盖启动窗口。
readinessProbe 决定了 Service 是否把流量发给这个 Pod。没有 readinessProbe 时,容器进程一启动就可能被认为可接流量——Java 服务、需要加载缓存的服务、启动后要连外部依赖的服务容易出现"Pod Running 但请求失败"。
容器状态
bash
kubectl get pod <pod-name> -n <namespace> -o wide
kubectl describe pod <pod-name> -n <namespace>
kubectl get pod <pod-name> -n <namespace> \
-o jsonpath='{.status.containerStatuses[*].state}{"\n"}'常见状态:
| 状态 | 说明 |
|---|---|
| Waiting | 等待中——拉镜像、创建容器、退避重启 |
| Running | 容器进程运行中 |
| Terminated | 容器已退出,有 exitCode 和 reason |
查看上一次退出信息:
bash
kubectl get pod <pod-name> -n <namespace> \
-o jsonpath='{.status.containerStatuses[0].lastState.terminated}{"\n"}'日志和事件
bash
kubectl logs <pod-name> -n <namespace> # 当前容器日志
kubectl logs <pod-name> -n <namespace> --previous # 上一次崩溃前的日志
kubectl logs <pod-name> -n <namespace> -c <container-name> # 多容器 Pod 指定容器
kubectl get events -n <namespace> --sort-by=.lastTimestamp事件偏平台动作(调度、拉镜像、挂载卷),日志偏应用进程。ImagePullBackOff、FailedMount、FailedScheduling 这类问题,事件比应用日志更有用。平台还没把容器启动起来时,应用日志经常是空的。
常见状态处理
| 状态 | 常见原因 | 查看方向 |
|---|---|---|
Pending | 调度失败、PVC 未绑定 | describe pod、节点资源、PVC |
ImagePullBackOff | 镜像名写错、仓库认证、网络不通 | Events、节点 crictl pull |
ContainerCreating | CNI 分配 IP、挂载卷、运行时创建 sandbox | Events、kubelet 日志 |
CrashLoopBackOff | 程序启动后退出 | logs --previous、exitCode |
OOMKilled | 内存超过 limit | 容器 lastState、资源配置 |
排查 Pod 时先看 Events 再查日志。如果 Events 显示还在 ContainerCreating,应用日志肯定还没有——从平台层开始,一层一层往里看。