重要信息启用此功能并在群集中运行Docker容器会带来安全隐患。考虑到Docker与许多强大的内核功能的集成,管理员必须在启用此功能之前了解Docker安全性。
Docker将Linux容器的易于使用的界面与这些容器的易于构建的映像文件结合在一起。简而言之,Docker使用户能够将应用程序与其首选的执行环境捆绑在一起,以在目标计算机上执行。有关Docker的更多信息,请参阅其文档。
Linux容器执行器(LCE)允许YARN NodeManager启动YARN容器以直接在主机上或Docker容器内部运行。请求资源的应用程序可以为每个容器指定应如何执行它。LCE还提供增强的安全性,并且在部署安全群集时需要使用LCE。当LCE启动YARN容器以在Docker容器中执行时,应用程序可以指定要使用的Docker映像。
Docker容器提供了一个自定义执行环境,应用程序的代码在其中运行,与NodeManager和其他应用程序的执行环境隔离。这些容器可以包括应用程序所需的特殊库,并且它们可以具有本机工具和库的不同版本,包括Perl,Python和Java。Docker容器甚至可以运行与NodeManager上不同的Linux版本。
Docker for YARN提供一致性(所有YARN容器将具有相同的软件环境)和隔离(不干扰物理机上安装的任何组件)。
LCE要求容器执行者二进制文件由root:hadoop拥有,并具有6050权限。为了启动Docker容器,Docker守护程序必须在将要启动Docker容器的所有NodeManager主机上运行。Docker客户端还必须安装在将启动Docker容器并能够启动Docker容器的所有NodeManager主机上。
为了防止在启动作业时超时,应用程序要使用的所有大型Docker映像都应该已经加载到NodeManager主机上的Docker守护程序的缓存中。加载映像的一种简单方法是发出Docker Pull请求。例如:
sudo docker pull库/ openjdk:8
应该在yarn-site.xml中设置以下属性:
<配置> <属性> <name> yarn.nodemanager.container-executor.class </ name> <value> org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor </ value> <说明> 这是容器执行程序设置,可确保所有应用程序 从LinuxContainerExecutor开始。 </ description> </ property> <属性> <name> yarn.nodemanager.linux-container-executor.group </ name> <value> hadoop </ value> <说明> NodeManager的POSIX组。它应该与中的设置匹配 “ container-executor.cfg”。验证需要此配置 容器执行程序二进制文件的安全访问。 </ description> </ property> <属性> <name> yarn.nodemanager.linux-container-executor.nonsecure-mode.limit-users </ name> <value> false </ value> <说明> 是否所有应用程序都应作为NodeManager进程的所有者运行。 如果为false,则以应用程序所有者的身份启动应用程序。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.allowed-runtimes </ name> <value>默认值,docker </ value> <说明> 使用时允许使用逗号分隔的运行时列表 LinuxContainerExecutor。允许的值为default,docker和 javasandbox。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.type </ name> <value> </ value> <说明> 可选的。设置要使用的默认容器运行时。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.image-name </ name> <value> </ value> <说明> 可选的。当Docker运行时为时使用的默认Docker映像 已选择。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.allowed-container-networks </ name> <value>主机,无,桥接</ value> <说明> 可选的。启动时允许使用逗号分隔的一组网络 容器。有效值由可从以下位置获得的Docker网络确定 `docker network ls` </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.default-container-network </ name> <value>主机</ value> <说明> 否时启动Docker容器时使用的网络 在请求中指定了网络。该网络必须是 (可配置)一组允许的容器网络。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.host-pid-namespace.allowed </ name> <value> false </ value> <说明> 可选的。是否允许容器使用主机PID名称空间。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.privileged-containers.allowed </ name> <value> false </ value> <说明> 可选的。是否允许应用程序以特权运行 容器。特权容器被授予完整的 功能,不受设备的限制 cgroup控制器。换句话说,特权容器几乎可以 主机可以做的一切。使用时要格外小心。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.delayed-removal.allowed </ name> <value> false </ value> <说明> 可选的。是否允许用户请求该Docker 容器遵守调试删除延迟。这对于 对Docker容器相关的启动失败进行故障排除。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.stop.grace-period </ name> <value> 10 </ value> <说明> 可选的。可传递给Docker Stop命令的可配置值。这个 值定义docker stop命令发送之间的秒数 SIGTERM和SIGKILL。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.privileged-containers.acl </ name> <value> </ value> <说明> 可选的。允许请求的用户的逗号分隔列表 特权容器(如果允许特权容器)。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.capabilities </ name> <value> CHOWN,DAC_OVERRIDE,FSETID,FOWNER,MKNOD,NET_RAW,SETGID,SETUID,SETFCAP,SETPCAP,NET_BIND_SERVICE,SYS_CHROOT,KILL,AUDIT_WRITE </ value> <说明> 可选的。此配置设置确定功能 在启动时分配给Docker容器。虽然这些可能不会 从docker的角度区分大小写,最好保留这些 大写。要在没有任何功能的情况下运行,请将此值设置为 “无”或“无” </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.enable-userremapping.allowed </ name> <value> true </ value> <说明> 可选的。是否以Docker容器的UID和GID运行Docker容器 呼叫用户。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.userremapping-uid-threshold </ name> <value> 1 </ value> <说明> 可选的。重新映射的用户的最小可接受UID。具有UID的用户 低于此值的用户将无法启动容器 重新映射已启用。 </ description> </ property> <属性> <name> yarn.nodemanager.runtime.linux.docker.userremapping-gid-threshold </ name> <value> 1 </ value> <说明> 可选的。重新映射的用户的最小可接受GID。用户所属 GID低于此值的任何组将不允许 启用用户重新映射后启动容器。 </ description> </ property> </ configuration>
此外,container-executer.cfg文件必须存在并且包含容器执行程序的设置。该文件必须由具有0400权限的root用户拥有。该文件的格式为标准Java属性文件格式,例如
键=值
要启用Docker支持,需要以下属性:
配置名称 | 描述 |
---|---|
yarn.nodemanager.linux-container-executor.group | NodeManager的Unix组。它应与yarn-site.xml文件中的yarn.nodemanager.linux-container-executor.group相匹配。 |
container-executor.cfg必须包含一个部分来确定允许容器的功能。它包含以下属性:
配置名称 | 描述 |
---|---|
启用模块 | 必须为“ true”或“ false”才能分别启用或禁用启动Docker容器。预设值为0。 |
docker.binary | 用于启动Docker容器的二进制文件。/ usr / bin / docker默认情况下。 |
docker.allowed.capabilities | 允许容器添加逗号分隔的功能。默认情况下,不允许添加任何功能。 |
docker.allowed.devices | 逗号分隔的允许容器安装的设备。默认情况下,不允许添加任何设备。 |
docker.allowed.networks | 允许容器使用逗号分隔的网络。如果在启动容器时未指定网络,则将使用默认的Docker网络。 |
docker.allowed.ro-mounts | 逗号分隔的目录,允许容器以只读模式挂载。默认情况下,不允许挂载任何目录。 |
docker.allowed.rw-mounts | 逗号分隔的目录,允许容器以读写模式挂载。默认情况下,不允许挂载任何目录。 |
docker.allowed.volume-drivers | 逗号分隔的允许使用的卷驱动程序列表。默认情况下,不允许使用任何卷驱动程序。 |
docker.host-pid-namespace.enabled | 设置为“ true”或“ false”以使用主机的PID名称空间启用或禁用。默认值为“ false”。 |
docker.privileged-containers.enabled | 设置为“ true”或“ false”以启用或禁用启动特权容器。默认值为“ false”。 |
docker.trusted.registries | 以逗号分隔的列表,用于运行受信任的特权Docker容器的受信任的Docker注册表。默认情况下,没有定义注册表。 |
docker.inspect.max.retries | 用于检查Docker容器准备情况的整数值。每次检查均设置为延迟3秒。默认值10将在标记为容器失败之前等待30秒以使Docker容器准备就绪。 |
docker.no-new-privileges.enabled | 启用/禁用docker run的no-new-privileges标志。设置为“ true”以启用,默认情况下禁用。 |
docker.allowed.runtimes | 允许容器使用逗号分隔的运行时。默认情况下,不允许添加任何运行时。 |
请注意,如果您希望运行需要访问YARN本地目录的Docker容器,则必须将它们添加到docker.allowed.rw-mounts列表中。
另外,不允许容器以读写模式挂载container-executor.cfg目录的任何父目录。
以下属性是可选的:
配置名称 | 描述 |
---|---|
最小用户ID | 允许启动应用程序的最小UID。默认值是没有最小值 |
被禁止的用户 | 以逗号分隔的用户名列表,不应允许其启动应用程序。默认设置为:yarn,mapred,hdfs和bin。 |
allowed.system.users | 以逗号分隔的用户名列表,即使用户名的UID低于配置的最小值,也应允许这些用户名启动应用程序。如果用户出现在allowed.system.users和banned.users中,则该用户将被视为被禁止。 |
feature.tc.enabled | 必须为“ true”或“ false”。“ false”表示禁用流量控制命令。“ true”表示允许流量控制命令。 |
下面是允许启动Docker容器的container-executor.cfg的一部分:
yarn.nodemanager.linux-container-executor.group =纱线 [码头工人] module.enabled = true docker.privileged-containers.enabled = true docker.trusted.registries = centos docker.allowed.capabilities = SYS_CHROOT,MKNOD,SETFCAP,SETPCAP,FSETID,CHOWN,AUDIT_WRITE,SETGID,NET_RAW,FOWNER,SETUID,DAC_OVERRIDE,KILL,NET_BIND_SERVICE docker.allowed.networks =网桥,主机,无 docker.allowed.ro-mounts = / sys / fs / cgroup docker.allowed.rw-mounts = / var / hadoop / yarn / local-dir,/ var / hadoop / yarn / log-dir
为了使用YARN,对Docker映像有两个要求。
首先,将以应用程序所有者作为容器用户显式启动Docker容器。如果应用程序所有者不是Docker映像中的有效用户,则该应用程序将失败。容器用户由用户的UID指定。如果NodeManager主机和Docker映像之间的用户UID不同,则该容器可能以错误的用户身份启动,或者由于UID不存在而无法启动。有关更多详细信息,请参见“ Docker容器中的用户管理”部分。
其次,Docker映像必须具有应用程序期望的任何内容才能执行。对于Hadoop(MapReduce或Spark),Docker映像必须包含JRE和Hadoop库,并设置了必要的环境变量:JAVA_HOME,HADOOP_COMMON_PATH,HADOOP_HDFS_HOME,HADOOP_MAPRED_HOME,HADOOP_YARN_HOME和HADOOP_CONF_DIR。请注意,Docker映像中可用的Java和Hadoop组件版本必须与群集以及用于同一任务的其他任务的任何其他Docker映像中安装的版本兼容。否则,在Docker容器中启动的Hadoop组件可能无法与外部Hadoop组件进行通信。
如果Docker映像设置了命令,则行为将取决于YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE是否设置为true。如果是这样,当LCE使用YARN的容器启动脚本启动映像时,该命令将被覆盖。
如果Docker映像设置了入口点并且YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE设置为true,则launch_command将作为Docker中的CMD参数传递到ENTRYPOINT程序。launch_command的格式如下:param1,param2,这在Docker中转换为CMD [“ param1”,“ param2”]。
如果应用程序请求尚未在其执行主机上的Docker守护程序加载的Docker映像,则Docker守护程序将隐式执行Docker pull命令。MapReduce和Spark都假设报告进度超过10分钟的任务已停止,因此指定较大的Docker映像可能会导致应用程序失败。
在尝试启动Docker容器之前,请确保LCE配置适用于请求常规YARN容器的应用程序。如果启用LCE后一个或多个NodeManager无法启动,则原因很可能是容器执行器二进制文件的所有权和/或权限不正确。检查日志以确认。
为了在Docker容器中运行应用程序,请在应用程序的环境中设置以下环境变量:
环境变量名称 | 描述 |
---|---|
YARN_CONTAINER_RUNTIME_TYPE | 确定是否在Docker容器中启动应用程序。如果值为“ docker”,则将在Docker容器中启动应用程序。否则,将使用常规的过程树容器。 |
YARN_CONTAINER_RUNTIME_DOCKER_IMAGE | 命名将用于启动Docker容器的图像。可以使用可以传递给Docker客户端的run命令的任何映像名称。图像名称可以包含一个回购前缀。 |
YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE | 控制是否覆盖Docker容器的默认命令。设置为true时,Docker容器的命令将为“ bash path_to_launch_script ”。取消设置或设置为false时,将使用Docker容器的默认命令。 |
YARN_CONTAINER_RUNTIME_DOCKER_CONTAINER_NETWORK | 设置Docker容器要使用的网络类型。它必须是由yarn.nodemanager.runtime.linux.docker.allowed-container-networks属性确定的有效值。 |
YARN_CONTAINER_RUNTIME_DOCKER_PORTS_MAPPING | 允许用户为网桥Docker容器指定端口映射。环境变量的值应为端口映射的逗号分隔列表。Docker run命令的“ -p”选项相同。如果该值为空,则将添加“ -P”。 |
YARN_CONTAINER_RUNTIME_DOCKER_CONTAINER_PID_NAMESPACE | 控制Docker容器将使用哪个PID名称空间。默认情况下,每个Docker容器都有其自己的PID名称空间。要共享主机的名称空间,必须将yarn.nodemanager.runtime.linux.docker.host-pid-namespace.allowed属性设置为true。如果允许主机PID名称空间,并且此环境变量设置为host,则Docker容器将共享主机的PID名称空间。不允许其他值。 |
YARN_CONTAINER_RUNTIME_DOCKER_RUN_PRIVILEGED_CONTAINER | 控制Docker容器是否为特权容器。为了使用特权容器,必须将yarn.nodemanager.runtime.linux.docker.privileged-containers.allowed属性设置为true,并且应用程序所有者必须出现在yarn.nodemanager.runtime.linux.docker的值中.privileged-containers.acl属性。如果将此环境变量设置为true,则如果允许,将使用特权Docker容器。不允许使用其他值,因此应将环境变量保留为未设置状态,而不是将其设置为false。 |
YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS | 将其他卷安装添加到Docker容器。环境变量的值应为以逗号分隔的安装列表。所有此类安装必须以source:dest [:mode]给出,且模式必须为“ ro”(只读)或“ rw”(读写)以指定请求的访问类型。如果两者均未指定,则假定为可读写。该模式可以包括绑定传播选项。在那种情况下,模式应该采用[option],rw + [option]或ro + [option]的形式。有效的绑定传播选项是共享,rshared,slave,rslave,private和rprivate。容器执行器将根据container-executor.cfg中为docker.allowed.ro-mounts设置的值来验证请求的安装和docker.allowed.rw-mounts。 |
YARN_CONTAINER_RUNTIME_DOCKER_TMPFS_MOUNTS | 将其他tmpfs挂载添加到Docker容器。环境变量的值应为容器内绝对安装点的逗号分隔列表。 |
YARN_CONTAINER_RUNTIME_DOCKER_DELAYED_REMOVAL | 允许用户基于每个容器请求延迟删除Docker容器。如果为true,则只有在yarn.nodemanager.delete.debug-delay-sec定义的持续时间过去之后,才会删除Docker容器。管理员可以通过纱线站点属性yarn.nodemanager.runtime.linux.docker.delayed-removal.allowed禁用此功能。默认情况下禁用此功能。禁用此功能或将其设置为false时,容器将在退出后立即被移除。 |
前两个是必需的。其余的可以根据需要设置。虽然通过环境变量控制容器类型有些不理想,但是它允许不了解YARN的Docker支持的应用程序(例如MapReduce和Spark)通过支持配置应用程序环境来利用它。
一旦提交了要在Docker容器中启动的应用程序,该应用程序的行为将与任何其他YARN应用程序完全相同。日志将被汇总并存储在相关的历史服务器中。应用程序的生命周期将与非Docker应用程序的生命周期相同。
警告启用此功能时应格外小心。不建议启用对目录(例如但不限于/,/ etc,/ run或/ home)的访问,这可能会导致容器对主机产生负面影响或泄露敏感信息。警告
从主机文件和目录通常需要Docker容器,其中通过泊坞内提供卷。示例包括本地化资源,Apache Hadoop二进制文件和套接字。为满足此需求,YARN-6623新增了管理员可设置主机目录白名单的功能,这些主机目录允许作为卷绑定安装到容器中。YARN-5534添加了用户的功能,如果管理白名单允许,则用户可以提供将要安装到容器中的安装列表。
为了使用此功能,必须配置以下内容。
管理员提供的白名单定义为逗号分隔的目录列表,允许将目录挂载到容器中。用户提供的源目录必须匹配或为指定目录的子目录。
用户提供的安装列表被定义为以逗号分隔的列表,格式为source:destination或source:destination:mode。源是主机上的文件或目录。目标是容器中绑定源的路径。该模式定义了用户期望的安装模式,可以是ro(只读)或rw(读写)。如果未指定,则假定为rw。该模式还可以包括绑定传播选项(共享,rshared,从属,rslave,私有或rprivate)。在这种情况下,模式应为option,rw + option或ro + option形式。
以下示例概述了如何使用此功能将常用的/ sys / fs / cgroup目录挂载到在YARN上运行的容器中。
管理员将container-executor.cfg中的docker.allowed.ro-mounts设置为“ / sys / fs / cgroup”。应用程序现在可以请求以只读模式将“ / sys / fs / cgroup”从主机安装到容器中。
在提交应用程序时,可以将YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS环境变量设置为请求此安装。在此示例中,环境变量将设置为“ / sys / fs / cgroup:/ sys / fs / cgroup:ro”。目标路径不受限制,考虑到示例管理员白名单,“ / sys / fs / cgroup:/ cgroup:ro”也将有效。
YARN的Docker容器支持使用在NodeManager主机上定义的用户的uid:gid身份启动容器进程。NodeManager主机和容器之间的用户名和组名不匹配会导致权限问题,容器启动失败甚至安全漏洞。集中管理主机和容器的用户和组,大大降低了这些风险。在YARN上运行容器化应用程序时,有必要了解将使用哪个uid:gid对启动容器的进程。
作为uid:gid对的含义的示例,请考虑以下内容。默认情况下,在非安全模式下,YARN将以没有用户的用户身份启动进程(有关如何在非安全模式下确定以用户身份运行的信息,请参见“ 将CGroups与YARN一起使用 ”底部的表)。在基于CentOS的系统上,noun用户的uid为99,noun组为99。其结果是,纱会叫搬运工人运行与--user 99:99。如果nobody用户的容器中没有uid 99,则启动可能会失败或产生意外结果。
该规则的一个例外是使用特权Docker容器。启动容器时,特权容器将不会设置uid:gid对,并将尊重Dockerfile中的USER或GROUP条目。这允许特权容器像任何具有安全隐患的用户一样运行。在启用Privileged Docker容器之前,请了解这些含义。
有许多解决用户和组管理的方法。默认情况下,Docker将针对容器内的/ etc / passwd(和/ etc / shadow)对用户进行身份验证。使用Docker映像中提供的默认/ etc / passwd不太可能包含适当的用户条目,并且会导致启动失败。强烈建议集中管理用户和组。下面概述了几种用户和组管理方法。
管理用户和组的最基本方法是在Docker映像中修改用户和组。此方法仅在非安全模式下可行,在该模式下所有容器进程将以单个已知用户(例如,没人)启动。在这种情况下,唯一的要求是,nobody用户和组的uid:gid对必须在主机和容器之间匹配。在基于CentOS的系统上,这意味着容器中的Nono用户需要UID 99,而容器中的Noone组则需要GID 99。
更改UID和GID的一种方法是利用usermod和groupmod。以下为无人用户/组设置正确的UID和GID。
usermod -u 99没有人 groupmod -g 99没有人
考虑到添加用户的灵活性,不建议在测试后再使用此方法。
当组织已经具有在每个系统上创建本地用户的自动化功能时,将挂载/ etc / passwd和/ etc / group绑定到容器中可能是适当的,这是直接修改容器映像的替代方法。为了使能力绑定安装的/ etc / passwd和/ etc /组,更新docker.allowed.ro-安装在容器executor.cfg包括那些路径。提交申请时,YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS将需要包含/ etc / passwd:/ etc / passwd:ro和/ etc / group:/ etc / group:ro。
这种绑定安装方法存在一些挑战,需要考虑。
考虑到修改运行中的容器的灵活性,建议不要在测试后再使用此方法。
SSSD是允许集中管理用户和组的另一种方法。系统安全服务守护程序(SSSD)提供对不同身份和身份验证提供程序(例如LDAP或Active Directory)的访问。
Linux身份验证的传统架构如下:
应用程序-> libpam-> pam_authenticate-> pam_unix.so-> / etc / passwd
如果我们使用SSSD进行用户查找,它将变为:
应用程序-> libpam-> pam_authenticate-> pam_sss.so-> SSSD-> pam_unix.so-> / etc / passwd
我们可以将SSSD通信的UNIX套接字绑定安装到容器中。这将允许SSSD客户端库针对主机上运行的SSSD进行身份验证。结果,用户信息不需要存在于docker映像的/ etc / passwd中,而是由SSSD提供服务。
主机和容器的分步配置:
#yum -y install sssd-common sssd-proxy
#猫/etc/pam.d/sss_proxy 需要验证pam_unix.so 需要帐户pam_unix.so 需要密码pam_unix.so 所需的会话pam_unix.so
#猫/ etc / sssd / sssd / conf [sssd] 服务= nss,pam config_file_version = 2 域=代理 [nss] [帕姆] [域/代理] id_provider =代理 proxy_lib_name =文件 proxy_pam_target = sss_proxy
#systemctl启动sssd
#getent passwd -s sss localuser
将/ var / lib / sss / pipes目录从主机绑定挂载到容器很重要,因为SSSD UNIX套接字位于该容器中。
-v / var / lib / sss / pipes:/ var / lib / sss / pipes:rw
以下所有步骤应在容器本身上执行。
仅安装SSSS客户端库
#yum -y install sssd-client
确保为passwd和group数据库配置了sss
/etc/nsswitch.conf
配置应用程序用来调用SSSD的PAM服务
#猫/etc/pam.d/system-auth #%PAM-1.0 #此文件是自动生成的。 #用户更改将在下次运行authconfig时销毁。 需要验证pam_env.so 验证足够的pam_unix.so try_first_pass nullok 验证足够的pam_sss.so forward_pass 需要验证pam_deny.so 需要帐户pam_unix.so 帐户[默认=成功失败=确定user_unknown =忽略] pam_sss.so 需要帐户pam_permit.so 密码必填pam_pwquality.so try_first_pass local_users_only retry = 3 authtok_type = 密码足够pam_unix.so try_first_pass use_authtok nullok sha512阴影 密码足够pam_sss.so use_authtok 需要密码pam_deny.so 会话可选pam_keyinit.so吊销 所需的会话pam_limits.so -session可选pam_systemd.so 会话[success = 1 default = ignore] pam_succeed_if.so服务在crond安静use_uid 所需的会话pam_unix.so 会话可选pam_sss.so
保存docker映像,并将docker映像用作应用程序的基础映像。
测试在YARN环境中启动的Docker映像。
$ id uid = 5000(本地用户)gid = 5000(本地用户)组= 5000(本地用户),1337(hadoop)
特权Docker容器可以与主机系统设备进行交互。如果不小心,可能会对主机操作系统造成损害。为了减轻允许特权容器在Hadoop集群上运行的风险,我们实施了一个受控流程,以对未经授权的特权Docker映像进行沙箱处理。
默认行为是禁止任何特权的Docker容器。当将docker.privileged-containers.enabled设置为enabled时,docker镜像可以在docker容器中以root特权运行,但是禁用了对主机级设备的访问。这使开发人员和测试人员可以从互联网运行docker映像,而不会损害主机操作系统。
当Docker映像已被开发人员和测试人员认证为可信赖时。可以将受信任的映像提升为受信任的Docker注册表。系统管理员可以定义docker.trusted.registries,并设置私有Docker Registry服务器以提升可信映像。
允许可信映像通过NFS网关或主机级Hadoop配置挂载外部设备,例如HDFS。如果系统管理员允许使用docker.allow.rw-mounts指令写入外部卷,则特权Docker容器可以完全控制预定义卷中的主机级文件。
对于YARN Service HTTPD示例,container-executor.cfg必须定义可信任的centos docker注册表才能运行该示例。
重新启动后,作为NodeManager恢复过程的一部分,NodeManager将通过检查/ proc文件系统中是否存在容器的PID目录来验证容器是否仍在运行。为了安全起见,操作系统管理员可以启用/ proc文件系统的hidepid挂载选项。如果启用了hidepid选项,则必须通过设置如下所示的gid安装标志将纱线用户的主要组列入白名单。如果不将yarn用户的主要组列入白名单,则容器重新获取将失败,并且容器将在NodeManager重新启动时被杀死。
proc / proc proc nosuid,nodev,noexec,hidepid = 2,gid = yarn 0 0
Docker客户端命令将从默认位置(NodeManager主机上的$ HOME / .docker / config.json)绘制其配置。Docker配置是存储安全存储库凭据的位置,因此,不建议使用此方法将LCE与安全Docker存储库一起使用。
YARN-5428为分布式外壳程序添加了支持,以安全地提供Docker客户端配置。有关用法,请参见分布式Shell帮助。计划支持其他框架。
解决方法是,您可以使用Docker登录命令将每个NodeManager主机上的Docker守护进程手动登录到安全存储库中:
码头工人登录[选项] [服务器] 如果未指定服务器,请注册或登录Docker注册表服务器 默认为“ https://index.docker.io/v1/”。 -e,--email =“”电子邮件 -p,--password =“”密码 -u,--username =“”用户名
请注意,这种方法意味着所有用户都可以访问安全存储库。
本示例假定Hadoop已安装到/ usr / local / hadoop。
此外,docker.allowed.ro-安装在容器executor.cfg已经更新以包括目录:在/ usr /本地/ hadoop的,/ etc / passwd中,/ etc / group中。
要提交pi作业以在Docker容器中运行,请运行以下命令:
HADOOP_HOME = / usr / local / hadoop YARN_EXAMPLES_JAR = $ HADOOP_HOME / share / hadoop / mapreduce / hadoop-mapreduce-examples-*。jar MOUNTS =“ $ HADOOP_HOME:$ HADOOP_HOME:ro,/ etc / passwd:/ etc / passwd:ro,/ etc / group:/ etc / group:ro” IMAGE_ID =“ library / openjdk:8” 出口YARN_CONTAINER_RUNTIME_TYPE =泊坞窗 出口YARN_CONTAINER_RUNTIME_DOCKER_IMAGE = $ IMAGE_ID 出口YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS = $ MOUNTS 纱罐$ YARN_EXAMPLES_JAR pi \ -Dmapreduce.map.env.YARN_CONTAINER_RUNTIME_TYPE =泊坞窗\ -Dmapreduce.map.env.YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS = $ MOUNTS \ -Dmapreduce.map.env.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE = $ IMAGE_ID \ -Dmapreduce.reduce.env.YARN_CONTAINER_RUNTIME_TYPE =泊坞窗\ -Dmapreduce.reduce.env.YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS = $ MOUNTS \ -Dmapreduce.reduce.env.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE = $ IMAGE_ID \ 1 40000
请注意,应用程序主,映射任务和归约任务是独立配置的。在此示例中,我们对所有三个图像都使用openjdk:8图像。
本示例假定Hadoop已安装到/ usr / local / hadoop,Spark已安装到/ usr / local / spark。
此外,docker.allowed.ro-安装在容器executor.cfg已经更新以包括目录:在/ usr /本地/ hadoop的,/ etc / passwd中,/ etc / group中。
要在Docker容器中运行Spark Shell,请运行以下命令:
HADOOP_HOME = / usr / local / hadoop SPARK_HOME = / usr / local / spark MOUNTS =“ $ HADOOP_HOME:$ HADOOP_HOME:ro,/ etc / passwd:/ etc / passwd:ro,/ etc / group:/ etc / group:ro” IMAGE_ID =“ library / openjdk:8” $ SPARK_HOME / bin / spark-shell-主纱 --conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE = docker \ --conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE = $ IMAGE_ID \ --conf spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS = $ MOUNTS \ --conf spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE = docker \ --conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE = $ IMAGE_ID \ --conf spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS = $ MOUNTS
请注意,应用程序主服务器和执行程序是独立配置的。在此示例中,我们都使用openjdk:8图像。
在Hadoop 2.x中引入Docker支持时,该平台旨在在Docker容器中运行现有的Hadoop程序。日志重定向和环境设置与Node Manager集成在一起。在Hadoop 3.x中,对Hadoop Docker的支持不仅限于运行Hadoop工作负载,而且还使用来自dockerfile的ENTRYPOINT以Docker本机形式支持Docker容器。通过定义YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE环境变量,应用程序可以决定默认支持YARN模式还是默认支持Docker模式。系统管理员还可以将群集设置为默认设置,以使ENTRY_POINT成为默认操作模式。
在yarn-site.xml中,将YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE添加到节点管理器环境白名单:
<属性> <name> yarn.nodemanager.env-whitelist </ name> <值> JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME,YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE </ value> </ property>
在yarn-env.sh中,定义:
导出YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE = true