基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

YARN 底层是如何实现 CPU 和内存资源的物理隔离的?

知识点图片

YARN(Yet Another Resource Negotiator)在底层实现 CPU 和内存资源的物理隔离,核心是依赖于 Linux 操作系统的内核特性:Cgroups(Control Groups)

如果不启用 Cgroups,YARN 默认只能做到“逻辑隔离”(基于轮询监控的软限制),而无法做到真正的物理隔离。为了实现真正的物理隔离,YARN 必须配合 LinuxContainerExecutor(LCE)来调用底层系统的 Cgroups。

以下是 YARN 底层实现 CPU 和内存物理隔离的详细机制:


一、 核心基础:Linux Cgroups 与 LCE

要理解底层隔离,首先需要知道两个关键组件:

  1. Cgroups (Control Groups):Linux 内核提供的一种机制,可以限制、记录、隔离进程组(process groups)所使用的物理资源(CPU、内存、I/O 等)。
  2. LinuxContainerExecutor (LCE):YARN NodeManager 中的一个执行器。YARN 默认使用 DefaultContainerExecutor,它无法做到真正的资源隔离。只有配置为 LCE 时,NodeManager 才会通过一个底层的 C 语言编写的特权程序(container-executor)去操作系统层面创建 Cgroups 目录,并将 Container 的进程 PID 放入对应的 Cgroup 中。

二、 内存资源的隔离实现

内存的隔离在 YARN 中分为“逻辑监控”和“物理隔离”两层防御。

1. 物理隔离(基于 Cgroups)

当开启 Cgroups 的内存隔离后,底层实现如下:

  • 资源分配:NodeManager 启动一个 Container 时,LCE 会在 Linux 的 /sys/fs/cgroup/memory/hadoop-yarn/ 目录下为该 Container 创建一个专属的子目录。
  • 参数设置:YARN 会将该 Container 申请的内存大小(例如 1GB)写入到该目录下的 memory.limit_in_bytes 文件中。
  • 物理限制:一旦该 Container 内的进程(包括其产生的子进程)使用的物理内存(RSS)超过了 limit_in_bytes 的值,Linux 内核的 OOM (Out Of Memory) Killer 会直接在操作系统底层将该进程杀掉。
  • 表现:YARN 会捕获到进程非正常退出,通常退出码为 137(128 + 9 SIGKILL),并在此 Container 日志中记录超用内存被杀。

2. 逻辑监控(基于 NodeManager 轮询 - 默认机制)

即使开启了 Cgroups,YARN 依然保留了默认的轮询监控机制作为补充:

  • NodeManager 中有一个 ContainersMonitorImpl 线程。
  • 它会定期(默认 3 秒)读取 Linux 的 /proc/<pid>/stat/proc/<pid>/statm 文件,计算出一棵进程树(Process Tree)的总物理内存(RSS)和虚拟内存(Vmem)。
  • 如果发现超限,NodeManager 会主动向该进程树发送 SIGTERM 然后发送 SIGKILL 杀死容器。
  • 区别:这种方式有滞后性(3秒窗口期),容易导致短时间内内存暴增冲垮 Node 节点,因此生产环境强依赖 Cgroups 进行物理兜底。

三、 CPU 资源的隔离实现

CPU 资源的隔离比内存更复杂,因为 CPU 是可压缩资源(超出限制通常是降速而不是杀进程)。YARN 底层通过 Cgroups 的 CPU 子系统 实现,主要分为两种模式:弹性共享(Soft Limit)严格限制(Hard Limit)

1. 弹性共享隔离(基于 CPU Shares - 默认 Cgroups 行为)

  • 底层机制:通过 Cgroups 的 cpu.shares 参数实现。
  • 实现过程:如果一个 Container 申请了 1 个 vCore,YARN 会根据节点的总 CPU 能力计算出一个相对权重值,写入该 Container 对应 Cgroups 目录的 cpu.shares 文件中(默认 1 vCore = 1024 shares)。
  • 物理效果
    • 当节点 CPU 繁忙时,Linux 内核的 CFS(完全公平调度器)会严格按照 cpu.shares 的比例来分配 CPU 时间片,保证 Container 获得其应有的 CPU 资源。
    • 弹性:当节点上有其他空闲 CPU 时,该 Container 可以突破自身的配额,占用空闲的 CPU 资源。这提高了集群的整体资源利用率。

2. 严格限制隔离(基于 CPU CFS Quota - 需特殊配置)

在多租户或者对 SLA 要求极高的场景下,用户不希望 Container 抢占空闲 CPU(防止相互干扰),YARN 提供了严格模式(yarn.nodemanager.linux-container-executor.cgroups.strict-resource-usage 设置为 true)。

  • 底层机制:通过 Cgroups 的 cpu.cfs_period_uscpu.cfs_quota_us 参数实现。
  • 实现过程
    • cpu.cfs_period_us:定义一个调度周期(通常是 100000 微秒,即 100 毫秒)。
    • cpu.cfs_quota_us:定义在一个周期内,该 Container 最多能使用的 CPU 时间。
    • 如果 Container 申请了 2 个 vCore,YARN 会将 cpu.cfs_quota_us 设置为 2 * cpu.cfs_period_us
  • 物理效果:无论 Node 节点是否空闲,Container 使用的 CPU 一旦达到 quota 限制,Linux 内核就会挂起该进程的执行,直到下一个周期开始。绝对不允许超用

3. CPU 绑核(NUMA 架构优化)

在更高阶的隔离中,YARN 支持基于 cpuset Cgroups 子系统的绑核策略。

  • 它可以将特定的 Container 进程强制绑定到特定的物理 CPU 核心上运行。
  • 这样可以避免 CPU Context Switch(上下文切换)的开销,并且在 NUMA 架构下,保证进程优先使用离特定 CPU 最近的物理内存,实现最高级别的物理隔离。

四、 总结与工作流示例

当你在 YARN 提交一个任务,要求 2 vCores, 2GB 内存 时,底层发生的物理隔离动作如下:

  1. NodeManager 接收到启动请求。
  2. 调用 LinuxContainerExecutor 的 C 语言二进制程序。
  3. C 程序以 root 权限在操作系统创建:
    • /sys/fs/cgroup/memory/hadoop-yarn/container_xxx/
    • /sys/fs/cgroup/cpu/hadoop-yarn/container_xxx/
  4. 写入参数:
    • 2 * 1024 * 1024 * 1024 (2GB) 写入 memory.limit_in_bytes
    • 2 * 1024 写入 cpu.shares(假设非严格模式)。
  5. C 程序将任务进程的 PID 写入上述两个 Cgroups 的 taskscgroup.procs 文件中。
  6. 切换为提交任务的用户(如 alice),启动 JVM / 实际计算进程。
  7. 从此,该进程的 CPU 和内存完全受到 Linux 内核级别的物理管控。
00:00
00:00