OOM Killer(Out-of-Memory Killer)在 Kubernetes 中决定是否终止 Pod 的核心基准是内存资源的超额使用,其决策和执行流程涉及多个组件的协同工作。以下是完整的基准和流程说明:
⚖️ 一、决策基准:工作集内存(Working Set Memory)
OOM Killer 主要依据 container_memory_working_set_bytes
指标判断是否终止 Pod。
该指标表示容器活跃使用的物理内存页(无法被内核回收的内存),包括:
- 堆内存(Heap):应用程序运行时直接分配的内存。
- 栈内存(Stack):线程执行所需的临时内存。
- 内核数据结构:如进程页表、套接字缓冲区等。
💡 为何不用
container_memory_usage_bytes
?后者包含缓存(如文件系统缓存),这些内存在压力下可被回收,不能反映真实的内存压力。
⚙️ 二、完整流程:从监控到终止
1. 内存监控与上报
- 容器运行时(如 Docker) :持续收集容器的内存使用数据(通过 Cgroups 接口
/sys/fs/cgroup/memory/
)。 - cAdvisor :集成在 kubelet 中,将容器的
working_set
指标暴露给 Kubernetes。
2. 阈值检测与触发
-
kubelet 比较容器内存使用量与预设的
limits.memory
:- 若
working_set
≥limits.memory
,触发 OOM 事件。
- 若
-
Linux 内核的 OOM Killer:收到 kubelet 的终止请求后,按优先级选择进程终止(通常选择内存超额最多的容器)。
3. Pod 终止与状态更新
-
终止动作 :内核发送
SIGKILL
信号(Exit Code 137)强制结束容器。 -
Kubernetes 状态更新 :Pod 状态变更为
OOMKilled
,并记录事件:yamlkubectl describe pod <pod-name> # 输出示例 Last State: Terminated Reason: OOMKilled Exit Code: 137
4. 后续行为
- 重启策略 :若 Pod 配置了
restartPolicy: Always/OnFailure
,kubelet 会自动重启容器。 - CrashLoopBackOff:若反复 OOM,Kubernetes 会指数级延迟重启,避免雪崩。
⚠️ 三、两类 OOMKilled 场景
-
宿主机级 OOM
- 原因:Pod 未设内存限制,耗尽节点物理内存。
- 特征 :内核日志(
/var/log/messages
)显示Out of memory: Kill process
。
-
Cgroups 级 OOM
- 原因 :Pod 内存使用超过
limits.memory
。 - 特征 :Pod 事件明确标记
OOMKilled
。
- 原因 :Pod 内存使用超过
🔍 四、调试建议
-
实时监控:
bashkubectl top pods # 查看 Pod 内存使用
-
分析工作集内存:
通过容器内文件
/sys/fs/cgroup/memory/memory.stat
检查working_set
明细。 -
调整资源限制:
在 YAML 中合理设置
requests
和limits
,避免低估堆外内存(如 JVM 的 Native 内存)。
💎 总结
OOM Killer 的决策基准是 工作集内存是否突破限制 ,流程涵盖监控→阈值检测→内核终止→状态更新。理解 working_set
的构成和 Cgroups 机制,是定位内存问题的关键。
附录
1. container_memory_working_set_bytes指标来源:Cgroup 内存子系统
该指标的数据来源于 Linux Cgroup 的 内存控制组(Memory Subsystem),具体文件路径为:
/sys/fs/cgroup/memory/<cgroup_path>/memory.stat
和 memory.usage_in_bytes
关键字段包括:
-
memory.usage_in_bytes
:容器当前总内存使用量(含缓存、RSS、Swap等)。 -
total_inactive_file
:可回收的非活跃文件缓存(如未使用的文件页缓存)。
计算公式:
ini
container_memory_working_set_bytes=memory.usageinbytes−totalinactivefile
2. 指标采集流程:cAdvisor 与 Kubelet
2.1 cAdvisor 采集数据
-
cAdvisor(Container Advisor)作为 Kubelet 的内置组件,定期(默认10秒)扫描容器的 Cgroup 目录,读取
memory.stat
和memory.usage_in_bytes
文件 -
根据公式计算
working_set
值,并生成指标container_memory_working_set_bytes
2.2 指标暴露与聚合
- cAdvisor 通过 Kubelet 的
/metrics/cadvisor
接口暴露指标(如container_memory_working_set_bytes{container="xxx"}
) - 监控系统(如 Prometheus)通过 Service Discovery 发现 Kubelet 目标,定期拉取指标