YARN——Container启动上下文

【概述】


在YARN中,不管是ApplicationMaster(后面均简称AM),还是一般的container(例如MR中的map任务、reduce任务;Spark中的executor或者Flink中的TaskManager),都有各自的启动上下文(ContainerLaunchContext)。

上下文中包含了任务启动所依赖的资源(包括jar,资源文件等)、环境变量、启动参数等。

那么启动上下文具体是怎样传递给yarn,yarn是否进行了处理,进行了怎样的处理,本文就来聊聊这些相关内容。

【参数传递流程】


对于AM而言,客户端向ResourceManager(RM)提交任务,提交的任务请求中就包含了上下文信息,RM收到请求后进行调度,最后通过NodeManager(NM)的心跳告知NM启动AM,在这个过程中将上下文信息传递给NM,NM拿到上下文信息构造出AM的启动脚本,并启动AM。

对于一般container,是由AM直接向NM发起请求,要求启动container,请求中同样携带了上下文信息。同样,NM根据这个上下文信息,构造出对应的启动脚本,然后启动container。

【示例】


先来看个实际的例子:

上图是客户端向RM提交MR任务时的抓包情况,结合protobuf文件与源码中上下文的数据结构,可以整理出,上下文信息包含了四个资源文件:

  • job.split、

  • job.xml、

  • job.splitmetainfo

  • job.jar

上下文中还指定了环境变量HADOOP_CLASSPATH,以及AM的启动参数。

该任务最终对应的启动脚本是这样的:

#!/bin/bash


export HADOOP_CONF_DIR="/opt/service/hadoop/etc/hadoop"
export MAX_APP_ATTEMPTS="2"
export JAVA_HOME="/usr/java/jdk1.8.0_231"
export APP_SUBMIT_TIME_ENV="1617090350054"
export NM_HOST="172.19.6.60"
export HADOOP_CLASSPATH="$PWD:job.jar/job.jar:job.jar/classes/:job.jar/lib/*:$PWD/*:/opt/service/hadoop/contrib/capacity-scheduler/*.jar"
export LD_LIBRARY_PATH="$PWD:$HADOOP_COMMON_HOME/lib/native"
export HADOOP_HDFS_HOME="/opt/service/hadoop-2.8.5"
export LOGNAME="root"
export JVM_PID="$$"
export PWD="/opt/data/hadoop/yarn/nodemanager/local/user/cache/root/appcache/application_1616833932566_0011/container_e21_1616833932566_0011_01_000001"
export HADOOP_COMMON_HOME="opt/service/hadoop"
export LOCAL_DIRS="/opt/data/hadoop/yarn/nodemanager/local/usercache/root/appcache/application_1616833932566_0011"
export APPLICATION_WEB_PROXY_BASE="/proxy/application_1616833932566_0011"
export SHELL="/bin/bash"
export NM_HTTP_PORT="8042"
export LOG_DIRS="/opt/data/hadoop/yarn/nodemanager/log/application_1616833932566_0011/container_e21_1616833932566_0011_01_000001"
export NM_AUX_SERVICE_mapreduce_shuffle="AAAAO+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
export NM_PORT="9100"
export USER="root"
export HADOOP_YARN_HOME="/opt/service/hadoop-2.8.5"
export CLASSPATH="$PWD:$HADOOP_CONF_DIR:$HADOOP_COMMON_HOME/share/hadoop/common/*:$HADOOP_COMMON_HOME/share/hadoop/common/lib/*:$HADOOP_HDFS_HOME/share/hadoop/hdfs/*:$HADOOP_HDFS_HOME/share/hadoop/hdfs/lib/*:$HADOOP_YARN_HOME/share/hadoop/yarn/*:$HADOOP_YARN_HOME/share/hadoop/yarn/lib/*:$HADOOP_MAPRED_HOME/share/hadoop/mapreduce/*:$HADOOP_MAPRED_HOME/share/hadoop/mapreduce/lib/*:job.jar/job.jar:job.jar/classes/:job.jar/lib/*:$PWD/*"
export HADOOP_TOKEN_FILE_LOCATION="/opt/data/hadoop/yarn/nodemanager/local/usercache/root/appcache/application_1616833932566_0011/container_e21_1616833932566_0011_01_000001/container_tokens"
export HOME="/home/"
export CONTAINER_ID="container_e21_1616833932566_0011_01_000001"
export MALLOC_ARENA_MAX="4"
ln -sf "/opt/data/hadoop/yarn/nodemanager/local/usercache/root/appcache/application_1616833932566_0011/filecache/11/job.jar" "job.jar"
hadoop_shell_errorcode=$?
if [ $hadoop_shell_errorcode -ne 0 ]
then
    exit $hadoop_shell_errorcode
fi
mkdir -p jobSubmitDir
hadoop_shell_errorcode=$?
if [ $hadoop_shell_errorcode -ne 0 ]
then
    exit $hadoop_shell_errorcode
fi
ln -sf "/opt/data/hadoop/yarn/nodemanager/local/usercache/root/appcache/application_1616833932566_0011/filecache/12/job.split" "jobSubmitDir/job.split"
hadoop_shell_errorcode=$?
if [ $hadoop_shell_errorcode -ne 0 ]
then
    exit $hadoop_shell_errorcode
fi
ln -sf "/opt/data/hadoop/yarn/nodemanager/local/usercache/root/appcache/application_1616833932566_0011/filecache/13/job.xml" "job.xml"
hadoop_shell_errorcode=$?
if [ $hadoop_shell_errorcode -ne 0 ]
then
    exit $hadoop_shell_errorcode
fi
mkdir -p jobSubmitDir
hadoop_shell_errorcode=$?
if [ $hadoop_shell_errorcode -ne 0 ]
then
    exit $hadoop_shell_errorcode
fi
ln -sf "/opt/data/hadoop/yarn/nodemanager/local/usercache/root/appcache/application_1616833932566_0011/filecache/10/job.splitmetainfo" "jobSubmitDir/job.splitmetainfo"
hadoop_shell_errorcode=$?
if [ $hadoop_shell_errorcode -ne 0 ]
then
    exit $hadoop_shell_errorcode
fi
exec /bin/bash -c "$JAVA_HOME/bin/java -Djava.io.tmpdir=$PWD/tmp -Dlog4j.configuration=container-log4j.properties -Dyarn.app.container.log.dir=/opt/data/hadoop/yarn/nodemanager/log/application_1616833932566_0011/container_e21_1616833932566_0011_01_000001 -Dyarn.app.container.log.filesize=0 -Dhadoop.root.logger=INFO,CLA -Dhadoop.root.logfile=syslog -Xmx1024m org.apache.hadoop.mapreduce.v2.app.MRAppMaster 1>/opt/data/hadoop/yarn/nodemanager/log/application_1616833932566_0011/container_e21_1616833932566_0011_01_000001/stdout 2>/opt/data/hadoop/yarn/nodemanager/log/application_1616833932566_0011/container_e21_1616833932566_0011_01_000001/stderr "
hadoop_shell_errorcode=$?
if [ $hadoop_shell_errorcode -ne 0 ]
then
    exit $hadoop_shell_errorcode
fi

【上下文的处理】


从上面的实例中可以看到,客户端请求中的上下文仅描述了资源名称与位置,环境变量以及具体启动的参数,那么NM是如何处理这个上下文并最终构造出启动脚本的呢?

通过源码分析,NM在启动任务前,根据上下文信息,转换成具体的启动脚本,具体处理包括:

  • 创建脚本构造器

    根据不同的平台(windows或unix)创建不同的脚本构建器,然后写入脚本的头,例如unix中的"#!/bin/bash"。

  • 变量替换

    变量替换指的是对上下文中环境变量、启动参数中的变量进行替换,主要替换的是日志的路径。

    可以仔细观察下上图中客户端传递的上下文启动参数中,标准输出和错误输出指向的路径均为<LOG_DIR>。

    这其实是代码中的一个公共常量。

    MR、Flink、Spark任务提交时,均使用了该值作为日志的输出路径。

    在NM中则根据实际配置文件中配置的路径进行替换。

  • 添加额外的环境变量

    除了客户端上下文中所携带的环境变量外,NM还会额外添加一些环境变量,包括

    CONTAINER_ID

    NM_PORT

    NM_HOST

    NM_HTTP_PORT

    LOCAL_DIRS

    LOG_DIRS

    USER

    LOGNAME

    HOME

    PWD

    HADOOP_CONF_DIR

    JVM_PID

    另外,对于AM而言,RM在处理的过程中还额外添加了三个环境变量:

    APPLICATION_WEB_PROXY_BASE

    MAX_APP_ATTEMPTS

    APP_SUBMIT_TIME_ENV

  • 环境变量写入脚本

    所有环境变量都存放在一个map中,然后遍历该map表,逐个转换成下面的格式:

    export KEY="VALUE"
    
  • 资源文件的处理

    环境变量写完后,对所有资源文件按需创建目录,并建立软链接。

    注意:每个资源文件建立软链接后,均会进行错误检查。

  • 写入启动参数

    最后将上下文中的启动参数写入脚本中。

整个流程下来就构成了完整的启动脚本,随后真正启动对应进程。

【总结】


本文简单总结了container启动上下文包括哪些内容,如何传递的,yarn是如何进行处理的。

这里留个引子,前面示例中客户端提交任务的上下文中,其资源文件指定的是HDFS的路径,那么这些资源文件最终是如何下载的本地的?

从NM构造的启动脚本中看到对这些资源文件都做了软链接,那么软链接的路径又是如何决定的?

这些资源文件能否给其他任务使用?资源文件什么时候删除。。。

所有这些问题都涉及NM中的资源管理,下篇文章,我们就来分析下NM中的资源管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值