跳到主要内容
约 10 分钟4 张卡

Pod:生命周期、探针与资源

Pod 是 Kubernetes 调度和运行的最小单位。日常运维中最常见的问题都落在 Pod 上:一直 Pending、反复 CrashLoopBackOff、被 OOMKilled、探针配置不当导致服务被反复重启。本文讲 Pod 的组成、状态与排查方法、三种探针、资源请求与限制,以及调度约束和弹性伸缩。

1. 面试核心​

先记住这几条,再读正文
  • Pod 是一组共享网络和存储的容器:同一个 Pod 内的容器共用 IP 和端口空间,可以通过 localhost 通信,可以挂载相同的卷。需要紧密协作、同生共死的进程(业务容器加日志、代理 sidecar)放进同一个 Pod。卡 · Pod 的组成
  • 排查 Pod 异常先看 kubectl describe pod 的事件和 kubectl logs --previous。Pending 多是调度失败(资源不足、亲和性、污点、存储未绑定);CrashLoopBackOff 是容器反复退出(程序报错、配置缺失、存活探针失败、OOMKilled)。卡 · 状态与排查
  • 存活探针失败会重启容器,就绪探针失败会把 Pod 从 Service 后端摘除,启动探针用于启动慢的应用,在它成功前不执行其他两种探针。存活探针不要检查下游依赖,否则依赖故障会引发全部实例重启。卡 · 探针
  • requests 用于调度,limits 由 cgroup 强制执行:CPU 超限被限流,内存超限被 OOMKilled。三者的关系决定 QoS 等级,节点资源紧张时按等级驱逐。
  • 调度约束用节点选择器和亲和性指定“应该去哪”,用污点和容忍控制“谁能来”,用反亲和与拓扑分布把副本分散;HPA 根据指标自动调整副本数。卡 · 资源请求、限制与 QoS

2. Pod 的组成​

每个 Pod 先启动一个 pause 容器(Pod 沙箱),它持有网络、IPC 等 Namespace,其他容器加入这些 Namespace。因此:

  • Pod 内所有容器共享一个 IP,端口不能冲突,可以用 localhost 互相访问。
  • 可以通过同一个卷共享文件,例如业务容器写日志、sidecar 读取并上报。
  • 调度以 Pod 为单位,Pod 内的容器总是在同一个节点上。

init 容器按顺序在业务容器之前运行,全部成功后才启动业务容器,用于等待依赖、初始化配置或数据。sidecar 与业务容器一起长期运行,提供日志收集、代理、证书刷新等辅助功能;新版本中 sidecar 可以声明为 restartPolicy: Always 的 init 容器,保证它先于业务容器启动、后于业务容器退出。

3. 状态与排查​

Pod 阶段(phase):

阶段含义
Pending已创建,但还有容器没有运行:未调度、正在拉取镜像或创建中
Running已绑定节点,至少一个容器在运行
Succeeded所有容器成功退出,不再重启(Job 常见)
Failed所有容器已退出,至少一个失败
Unknown无法获取状态,通常是节点失联

kubectl get pod 的 STATUS 列显示的往往是更具体的容器原因:

显示常见原因查看
Pending(未调度)资源不足、节点选择器或亲和性不满足、污点、PVC 未绑定describe 中的 FailedScheduling 事件
ContainerCreating拉取镜像慢、卷挂载失败、CNI 分配 IP 失败describe 的事件
ImagePullBackOff镜像名或标签错误、仓库认证失败、网络不通事件中的拉取错误
CrashLoopBackOff容器启动后反复退出,重启间隔按指数增长logs --previous 看上一次的输出,describe 看退出码
OOMKilled内存超过 limit退出码 137,调大 limit 或排查内存使用
Terminating 卡住finalizer 未完成、节点失联检查 finalizer 和节点状态

CrashLoopBackOff 的常见根因:启动命令或参数错误、缺少配置文件或环境变量、依赖的 Secret 不存在、连接不上数据库后程序直接退出、存活探针配置过严导致刚启动就被杀、内存不足被 OOMKilled。退出码 1 通常是程序错误,137 是被 SIGKILL(OOM 或探针失败后被杀),143 是收到 SIGTERM。

排查顺序:kubectl describe pod 看事件 → kubectl logs <pod> -c <容器> --previous 看崩溃前的日志 → kubectl get events --sort-by=.lastTimestamp 看命名空间内的事件 → 必要时 kubectl debug 启动临时容器进入排查。

4. 探针​

探针失败后用途
livenessProbe(存活)重启容器发现死锁、卡死等无法自愈的状态
readinessProbe(就绪)从 Service 后端摘除,不重启启动预热、暂时过载、依赖暂时不可用时停止接收流量
startupProbe(启动)超过阈值后重启容器启动慢的应用;成功之前不执行另外两种探针

检查方式有 HTTP GET(2xx、3xx 为成功)、TCP 连接、在容器内执行命令(退出码 0 为成功)和 gRPC。关键参数:initialDelaySeconds、periodSeconds、timeoutSeconds、failureThreshold。

startupProbe:
httpGet: {path: /healthz, port: 8080}
periodSeconds: 5
failureThreshold: 30 # 最多等待 150 秒启动
livenessProbe:
httpGet: {path: /healthz, port: 8080}
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet: {path: /ready, port: 8080}
periodSeconds: 5

设计原则:存活检查只判断进程本身是否还能工作,不检查数据库等下游,否则下游故障时所有实例同时重启,问题被放大;就绪检查可以包含必需的依赖。节点的健康由 kubelet 上报给控制平面,与 Pod 的探针是两回事。

5. 资源请求、限制与 QoS​

resources:
requests: {cpu: 500m, memory: 512Mi} # 调度时按此预留
limits: {cpu: "1", memory: 1Gi} # 运行时上限
资源超过 limit 的后果
CPU被 cgroup 限流,变慢但不会被杀
内存被 OOM Killer 杀掉,状态 OOMKilled
QoS 等级条件节点压力下的驱逐顺序
Guaranteed每个容器的 CPU 和内存都设置了 requests 且等于 limits最后
Burstable至少一个容器设置了 requests 或 limits,但不满足 Guaranteed中间,用量超过 requests 越多越先被驱逐
BestEffort都没有设置最先

驱逐:节点可用内存、磁盘或 inode 低于阈值时,kubelet 主动驱逐 Pod 来回收资源(节点压力驱逐)。kubectl drain 维护节点时通过 Eviction API 驱逐,会遵守 PodDisruptionBudget,保证同时下线的副本不超过设定值。

6. 调度约束与弹性伸缩​

机制作用例子
nodeSelector / 节点亲和性让 Pod 去特定节点;required 为硬性条件,preferred 为偏好只调度到有 GPU 的节点
污点与容忍节点拒绝没有对应容忍的 Pod。效果有 NoSchedule(不调度)、PreferNoSchedule(尽量不调度)、NoExecute(不调度并驱逐已有的)专用节点、控制平面节点、故障节点
Pod 亲和与反亲和根据其他 Pod 的位置决定去留,topologyKey 指定范围(节点、可用区)同一服务的副本分散到不同节点
拓扑分布约束限制副本在各拓扑域之间的数量差每个可用区副本数相差不超过 1

HPA:Horizontal Pod Autoscaler 周期性读取指标(CPU、内存来自 metrics-server,自定义指标来自 Prometheus 适配器等),按 期望副本数 = ceil(当前副本数 × 当前指标 / 目标指标) 调整副本。CPU 利用率是相对 requests 计算的,没有设置 requests 就无法按 CPU 伸缩。缩容默认有稳定窗口,避免频繁抖动。VPA 调整单个 Pod 的 requests;Cluster Autoscaler 在 Pod 因资源不足无法调度时增加节点。

7 · 面试题卡片​

7.1 为什么 Kubernetes 的最小调度单位是 Pod 而不是容器?Pod 和容器是什么关系?​

出现公司:京东、矩阵起源

考察重点

  • Pod 内容器共享的网络和存储;pause 容器的作用。
  • 需要紧密协作的进程为什么要作为整体调度。

相关内容:Pod 的组成。

参考回答

Pod 是一组共享网络和存储、总是一起调度到同一节点的容器。每个 Pod 先启动一个 pause 容器持有网络等 Namespace,其余容器加入进来,所以它们共用一个 IP,可以通过 localhost 通信,也可以挂载同一个卷交换文件。

很多应用需要几个进程紧密配合,例如业务程序加一个收集日志或代理流量的 sidecar。如果以容器为调度单位,这些容器可能被分到不同节点,无法共享网络和文件,也很难保证同时启动和停止。Pod 把它们作为一个整体调度和管理,同时仍然保持“一个容器一个进程”的镜像设计。Deployment 不是 Pod 的替代,它是管理一组相同 Pod 副本的控制器。

7.2 Pod 有哪些状态?一个 Pod 一直 Pending 或反复 CrashLoopBackOff,你怎样排查?​

出现公司:虾皮、旷视科技、塔斯汀

考察重点

  • Pod 阶段与容器状态原因的区别。
  • 按 Pending、拉镜像、崩溃分类的排查命令和常见根因;退出码。

相关内容:状态与排查。

参考回答

Pod 的阶段有 Pending、Running、Succeeded、Failed、Unknown。kubectl get pod 看到的 ContainerCreating、ImagePullBackOff、CrashLoopBackOff、OOMKilled 是容器层面的具体原因。

Pending 先用 kubectl describe pod 看事件:如果是 FailedScheduling,事件会写明原因,常见的有 CPU 或内存的 requests 超过节点剩余可分配量、节点选择器或亲和性没有匹配的节点、节点有不能容忍的污点、PVC 没有绑定到 PV。已经调度但停在 ContainerCreating,通常是拉镜像慢、卷挂载失败或 CNI 分配 IP 失败;ImagePullBackOff 是镜像名错误或仓库认证失败。

CrashLoopBackOff 表示容器启动后反复退出。先用 kubectl logs --previous 看上一次崩溃前的输出,再用 describe 看退出码和最近事件:退出码 1 一般是程序错误,例如配置或环境变量缺失、依赖连不上就退出;137 是被 SIGKILL,看 Last State 是否为 OOMKilled,或者存活探针在启动完成前就判定失败;配置错误可以对比最近的发布变更。定位后修正配置、调整资源或探针参数,必要时用 kubectl debug 进入临时容器排查。

7.3 Kubernetes 有哪三种探针?分别起什么作用,配置时要注意什么?​

出现公司:嘉银科技、影石、共济科技

考察重点

  • 三种探针失败后的不同动作。
  • 存活探针不检查下游;启动探针保护慢启动应用;探针与节点健康的区别。

相关内容:探针。

参考回答

存活探针判断容器是否还能工作,连续失败达到阈值后 kubelet 重启容器,用于发现死锁、卡死;就绪探针判断容器能否接收流量,失败时把 Pod 从 Service 的后端摘除,但不重启,用于启动预热、暂时过载;启动探针用于启动慢的应用,它成功之前不执行另外两种探针,超时后才重启。检查方式可以是 HTTP、TCP、执行命令或 gRPC。

配置要点:存活探针只检查进程自身,不能依赖数据库等下游,否则下游一故障所有实例被同时重启,故障扩大;就绪探针可以包含必需的依赖。启动慢的应用用启动探针,而不是把存活探针的初始延迟设得很长。超时和失败阈值要留余量,避免 GC 停顿等短暂抖动触发重启。节点是否健康由 kubelet 心跳反映,和 Pod 探针是两件事。

7.4 资源的 requests 和 limits 有什么区别?什么情况下 Pod 会被驱逐?污点、亲和性和 HPA 怎样使用?​

出现公司:字节跳动、虾皮、虎牙、京东

考察重点

  • requests 用于调度、limits 强制执行;CPU 与内存超限的不同后果;QoS 与驱逐顺序。
  • 污点的三种效果、反亲和的用途;HPA 的计算方式和前提。

相关内容:资源请求、限制与 QoS、调度约束与弹性伸缩。

参考回答

requests 是调度时预留的资源,调度器只把 Pod 放到剩余可分配量足够的节点;limits 是运行时上限,由 cgroup 执行。CPU 超过 limit 会被限流变慢,内存超过 limit 会被 OOM 杀掉。根据设置情况,Pod 分为 Guaranteed(requests 等于 limits)、Burstable 和 BestEffort(都没设)三个 QoS 等级。

节点可用内存、磁盘或 inode 低于阈值时,kubelet 会驱逐 Pod 回收资源,顺序是 BestEffort 先、然后是用量超过 requests 最多的 Burstable、最后是 Guaranteed。维护节点时 kubectl drain 也会驱逐 Pod,此时会遵守 PodDisruptionBudget。

污点设置在节点上,效果有 NoSchedule、PreferNoSchedule 和 NoExecute(还会驱逐已有的 Pod),只有带对应容忍的 Pod 才能调度上去,常用于专用节点和故障节点。反亲和让同一服务的副本避开彼此所在的节点或可用区,提高可用性。HPA 按指标调整副本数,期望副本数等于当前副本数乘以当前指标与目标的比值再向上取整;按 CPU 伸缩时利用率是相对 requests 计算的,所以必须设置 requests。节点资源不够时再配合 Cluster Autoscaler 扩充节点。

8. 参考资料​