基于本文回答

播面 播面

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

YARN 是如何为 Application 启动第一个 Container(即 ApplicationMaster 所在的容器)的?

知识点图片

在 YARN(Yet Another Resource Negotiator)中,启动应用程序的第一个 Container(即运行 ApplicationMaster (AM) 的 Container)是整个作业生命周期中最关键的一步。也就是所谓的“鸡生蛋,蛋生鸡”的问题中的“第一只鸡”。

这个过程由 Client(客户端)ResourceManager (RM)NodeManager (NM) 协同完成。以下是 YARN 为 Application 启动第一个 Container 的详细步骤:


第一阶段:客户端提交应用程序 (Client Submission)

  1. 申请 Application ID
    客户端(例如提交 Spark 或 MapReduce 任务的机器)首先向 ResourceManager (RM) 发送 RPC 请求(getNewApplication),要求分配一个新的 Application ID。
  2. 构建上下文 (Context)
    客户端在本地准备应用程序的启动信息,最核心的是构建 ApplicationSubmissionContext。其中包含了启动第一个 Container 所需的所有“配方”,这个配方叫做 ContainerLaunchContext (CLC)
    CLC 包含了:
    • Local Resources(本地资源):需要下载到运行节点的 JAR 包、配置文件等。
    • Environment Variables(环境变量):AM 运行所需的环境变量。
    • Commands(启动命令):实际启动 AM 进程的命令行(例如 java -Xmx1024m org.apache.spark.deploy.yarn.ApplicationMaster ...)。
    • Resource 需求:AM 需要的 CPU 和内存大小。
  3. 正式提交
    客户端向 RM 发送 submitApplication 请求,将上述 Context 提交给 RM。

第二阶段:ResourceManager 分配资源 (RM Allocation)

  1. 接收与校验
    RM 接收到请求后,会进行权限校验、配额检查,并将该 Application 放入状态机中(状态变为 NEW -> SUBMITTED -> ACCEPTED)。
  2. 调度器分配资源
    RM 内部的 Scheduler(调度器,如 Capacity / Fair Scheduler) 会将该应用加入到指定的队列中等待。
    当集群中有足够的资源时,调度器会为这个 Application 分配第一个 Container,并选定一台 NodeManager 节点来运行它。
  3. 准备启动 AM
    RM 内部有一个名为 ApplicationMasterLauncher 的服务。当调度器分配好资源后,ApplicationMasterLauncher 会接管任务,准备与被选中的那个 NodeManager 通信。
    RM 会生成一个 ContainerToken(安全令牌)和一个 AMRMToken(用于后续 AM 和 RM 通信的凭证),连同客户端最初提供的 ContainerLaunchContext 一起打包。

第三阶段:NodeManager 启动第一个 Container (NM Launch)

  1. RM 通知 NM 启动
    RM 的 ApplicationMasterLauncher 作为客户端,通过 ContainerManagementProtocol 协议,直接向选定的 NodeManager 发送 startContainers RPC 请求。
  2. 资源本地化 (Localization)
    NodeManager 接收到请求并验证 Token 通过后,第一件事是资源本地化。它会从 HDFS 下载 ContainerLaunchContext 中指定的 JAR 包、配置文件等,存放到该节点本地磁盘的特定目录下。
  3. 创建隔离环境
    NodeManager 根据资源需求(CPU、内存),通过底层的隔离机制(如 Linux Cgroups)为该 Container 创建一个隔离的运行环境。
  4. 执行启动命令
    NodeManager 解析出 ContainerLaunchContext 中的启动命令(Commands),在准备好的目录和隔离环境中执行该脚本/命令。
    至此,ApplicationMaster 的进程被成功拉起,第一个 Container 正式运行!

第四阶段:ApplicationMaster 初始化与注册 (AM Registration)

  1. AM 进程启动
    ApplicationMaster 进程启动后,它做的第一件事是初始化自身的服务。

  2. 向 RM 注册
    AM 通过 ApplicationMasterProtocol 协议向 ResourceManager 发送 registerApplicationMaster 请求。

    • 这一步非常重要!AM 会把自己的 RPC 端口、Tracking URL(提供给用户看日志的 Web UI 地址)告诉 RM。
    • RM 收到注册后,Application 的状态会从 ACCEPTED 变为 RUNNING
  3. 后续工作(接管控制权)
    注册成功后,AM 就正式接管了该应用程序。接下来,AM 会计算应用还需要多少资源(多少个 Map/Reduce task 或者 Spark Executor),并自己向 RM 申请后续的 Container,然后亲自去对应的 NM 上启动它们。


总结流程图

可以把这个过程简单想象成以下对话:

  • Client -> RM: "我要跑个任务,这是运行总控程序(AM)需要的内存、JAR包和命令行,请帮我找台机器启动它。"
  • RM (Scheduler): "排队中... 好的,NodeManager-A 资源够用,决定是你了。"
  • RM -> NM-A: "这是启动配置和令牌,立刻在你那里启动这个 AM 容器!"
  • NM-A: "收到,正在下载 JAR 包,限制好内存,执行 java -jar AM.jar... 启动成功!"
  • AM (在 NM-A 上) -> RM: "老大我活了!这是我的地址,接下来申请其他干活的 Container 就由我来跟你交涉了。"

核心区别提示

  • 第一个 Container(AM 所在的 Container) 是由 ResourceManager 主动要求 NodeManager 启动的。
  • 后续的所有 Container(实际干活的 Task/Executor) 都是由 ApplicationMaster 申请资源后,由 AM 去要求 NodeManager 启动的。
00:00
00:00