Dockerコンテナを使用したアプリケーションの起動

セキュリティに関する警告

重要 この機能を有効にしてクラスタでDockerコンテナを実行すると、セキュリティ上の影響があります。Dockerは多くの強力なカーネル機能と統合されているため、管理者はこの機能を有効にする前にDockerのセキュリティを理解することが不可欠です。

概要

Dockerは、Linuxコンテナへの使いやすいインターフェースと、それらのコンテナ用の簡単に作成できるイメージファイルを組み合わせたものです。簡単に言えば、Dockerを使用すると、ユーザーはアプリケーションとその優先実行環境をバンドルして、ターゲットマシンで実行できます。Dockerの詳細については、ドキュメントを参照してください。

Linuxコンテナエグゼキュータ(LCE)により、YARN NodeManagerは、ホストマシン上で直接実行するか、Dockerコンテナ内で実行するYARNコンテナを起動できます。リソースを要求するアプリケーションは、各コンテナの実行方法を指定できます。LCEはセキュリティも強化し、セキュアクラスタを展開する場合に必要です。LCEがDockerコンテナで実行するYARNコンテナを起動する場合、アプリケーションは使用するDockerイメージを指定できます。

Dockerコンテナは、アプリケーションコードが実行されるカスタム実行環境を提供し、NodeManagerやその他のアプリケーションの実行環境から分離されます。これらのコンテナには、アプリケーションに必要な特別なライブラリを含めることができ、Perl、Python、Javaなど、ネイティブツールやライブラリの異なるバージョンを持つことができます。Dockerコンテナは、NodeManagerで実行されているものとは異なるバージョンのLinuxを実行することもできます。

YARN向けのDockerは、一貫性(すべてのYARNコンテナは同じソフトウェア環境を持つ)と分離(物理マシンにインストールされているものとの干渉がない)の両方を提供します。

クラスタ設定

LCEでは、container-executorバイナリがroot:hadoopが所有し、6050のアクセス許可を持っている必要があります。Dockerコンテナを起動するには、Dockerコンテナを起動するすべてのNodeManagerホストでDockerデーモンが実行されている必要があります。また、Dockerコンテナを起動するすべてのNodeManagerホストにDockerクライアントがインストールされており、Dockerコンテナを起動できる必要があります。

ジョブの開始時のタイムアウトを防ぐために、アプリケーションで使用される大規模なDockerイメージは、NodeManagerホストのDockerデーモンのキャッシュに既にロードされている必要があります。イメージをロードする簡単な方法は、Docker pullリクエストを発行することです。例えば

    sudo docker pull library/openjdk:8

次のプロパティをyarn-site.xmlに設定する必要があります。

<configuration>
  <property>
    <name>yarn.nodemanager.container-executor.class</name>
    <value>org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor</value>
    <description>
      This is the container executor setting that ensures that all applications
      are started with the LinuxContainerExecutor.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.linux-container-executor.group</name>
    <value>hadoop</value>
    <description>
      The POSIX group of the NodeManager. It should match the setting in
      "container-executor.cfg". This configuration is required for validating
      the secure access of the container-executor binary.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.linux-container-executor.nonsecure-mode.limit-users</name>
    <value>false</value>
    <description>
      Whether all applications should be run as the NodeManager process' owner.
      When false, applications are launched instead as the application owner.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.allowed-runtimes</name>
    <value>default,docker</value>
    <description>
      Comma separated list of runtimes that are allowed when using
      LinuxContainerExecutor. The allowed values are default, docker, and
      javasandbox.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.type</name>
    <value></value>
    <description>
      Optional. Sets the default container runtime to use.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.image-name</name>
    <value></value>
    <description>
      Optional. Default docker image to be used when the docker runtime is
      selected.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.image-update</name>
    <value>false</value>
    <description>
      Optional. Default option to decide whether to pull the latest image
      or not.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.allowed-container-networks</name>
    <value>host,none,bridge</value>
    <description>
      Optional. A comma-separated set of networks allowed when launching
      containers. Valid values are determined by Docker networks available from
      `docker network ls`
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.default-container-network</name>
    <value>host</value>
    <description>
      The network used when launching Docker containers when no
      network is specified in the request. This network must be one of the
      (configurable) set of allowed container networks.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.host-pid-namespace.allowed</name>
    <value>false</value>
    <description>
      Optional. Whether containers are allowed to use the host PID namespace.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.privileged-containers.allowed</name>
    <value>false</value>
    <description>
      Optional. Whether applications are allowed to run in privileged
      containers. Privileged containers are granted the complete set of
      capabilities and are not subject to the limitations imposed by the device
      cgroup controller. In other words, privileged containers can do almost
      everything that the host can do. Use with extreme care.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.delayed-removal.allowed</name>
    <value>false</value>
    <description>
      Optional. Whether or not users are allowed to request that Docker
      containers honor the debug deletion delay. This is useful for
      troubleshooting Docker container related launch failures.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.stop.grace-period</name>
    <value>10</value>
    <description>
      Optional. A configurable value to pass to the Docker Stop command. This
      value defines the number of seconds between the docker stop command sending
      a SIGTERM and a SIGKILL.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.privileged-containers.acl</name>
    <value></value>
    <description>
      Optional. A comma-separated list of users who are allowed to request
      privileged containers if privileged containers are allowed.
    </description>
  </property>

  <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>
    <description>
      Optional. This configuration setting determines the capabilities
      assigned to docker containers when they are launched. While these may not
      be case-sensitive from a docker perspective, it is best to keep these
      uppercase. To run without any capabilites, set this value to
      "none" or "NONE"
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.enable-userremapping.allowed</name>
    <value>true</value>
    <description>
      Optional. Whether docker containers are run with the UID and GID of the
      calling user.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.userremapping-uid-threshold</name>
    <value>1</value>
    <description>
      Optional. The minimum acceptable UID for a remapped user. Users with UIDs
      lower than this value will not be allowed to launch containers when user
      remapping is enabled.
    </description>
  </property>

  <property>
    <name>yarn.nodemanager.runtime.linux.docker.userremapping-gid-threshold</name>
    <value>1</value>
    <description>
      Optional. The minimum acceptable GID for a remapped user. Users belonging
      to any group with a GID lower than this value will not be allowed to
      launch containers when user remapping is enabled.
    </description>
  </property>

</configuration>

さらに、container-executor.cfgファイルが存在し、コンテナエグゼキュータの設定が含まれている必要があります。このファイルは、rootが所有し、0400のアクセス許可を持っている必要があります。ファイルの形式は、標準的なJavaプロパティファイル形式です。例えば

`key=value`

Dockerサポートを有効にするには、次のプロパティが必要です。

設定名 説明
yarn.nodemanager.linux-container-executor.group NodeManagerのUnixグループ。yarn-site.xmlファイルのyarn.nodemanager.linux-container-executor.groupと一致する必要があります。

container-executor.cfgには、コンテナに許可される機能を決定するセクションが含まれている必要があります。次のプロパティが含まれています。

設定名 説明
module.enabled Dockerコンテナの起動を有効または無効にするには、「true」または「false」にする必要があります。デフォルト値は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 ホストのPID名前空間の使用を有効または無効にするには、「true」または「false」に設定します。デフォルト値は「false」です。
docker.privileged-containers.enabled 特権コンテナの起動を有効または無効にするには、「true」または「false」に設定します。デフォルト値は「false」です。
docker.privileged-containers.registries 特権のあるDockerコンテナを実行するための特権Dockerレジストリのコンマ区切りリスト。デフォルトでは、レジストリは定義されていません。
docker.trusted.registries 信頼できる特権Dockerコンテナを実行するための信頼できるDockerレジストリのコンマ区切りリスト。デフォルトでは、レジストリは定義されていません。
docker.inspect.max.retries Dockerコンテナの準備状況を確認するための整数値。各検査は3秒の遅延で設定されます。デフォルト値の10は、コンテナが失敗したとマークされる前に、Dockerコンテナの準備が完了するまで30秒待機します。
docker.no-new-privileges.enabled docker runのno-new-privilegesフラグを有効/無効にします。「true」に設定して有効にし、デフォルトでは無効です。
docker.allowed.runtimes コンテナが使用できるランタイムをコンマ区切りで指定します。デフォルトでは、ランタイムを追加することは許可されていません。
docker.service-mode.enabled Dockerコンテナサービスモードを有効または無効にするには、「true」または「false」に設定します。デフォルト値は「false」です。

YARNローカルディレクトリへのアクセスが必要なDockerコンテナを実行する場合は、それらをdocker.allowed.rw-mountsリストに追加する必要があることに注意してください。

さらに、コンテナは、container-executor.cfg ディレクトリの親ディレクトリをリードライトモードでマウントすることは許可されていません。

以下のプロパティはオプションです。

設定名 説明
min.user.id アプリケーションの起動を許可される最小UID。デフォルトは最小値なしです。
banned.users アプリケーションの起動を許可されないユーザー名のカンマ区切りリスト。デフォルト設定は、yarn、mapred、hdfs、およびbinです。
allowed.system.users 設定された最小値を下回るUIDであっても、アプリケーションの起動を許可されるユーザー名のカンマ区切りリスト。allowed.system.usersとbanned.usersの両方にユーザーが表示されている場合、そのユーザーは禁止されます。
feature.tc.enabled 「true」または「false」である必要があります。「false」はトラフィック制御コマンドが無効になっていることを意味します。「true」はトラフィック制御コマンドが許可されていることを意味します。
feature.yarn.sysfs.enabled 「true」または「false」である必要があります。詳細はYARN sysfsのサポートを参照してください。デフォルト設定は無効です。

Dockerコンテナの起動を許可するcontainer-executor.cfgの一部を以下に示します。

yarn.nodemanager.linux-container-executor.group=yarn
[docker]
  module.enabled=true
  docker.privileged-containers.enabled=true
  docker.privileged-containers.registries=local
  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=bridge,host,none
  docker.allowed.ro-mounts=/sys/fs/cgroup
  docker.allowed.rw-mounts=/var/hadoop/yarn/local-dir,/var/hadoop/yarn/log-dir

Dockerイメージの要件

YARNで動作させるには、Dockerイメージに2つの要件があります。

まず、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はCMDパラメータとしてENTRYPOINTプログラムに渡されます。launch_commandの形式はparam1,param2のようになり、これはDockerではCMD [ “param1”,“param2” ]に変換されます。

アプリケーションが、実行するホストのDockerデーモンによってまだロードされていないDockerイメージを要求した場合、Dockerデーモンは暗黙的にDocker pullコマンドを実行します。MapReduceとSparkの両方で、進捗状況の報告に10分以上かかるタスクは停止していると想定されるため、大きなDockerイメージを指定すると、アプリケーションが失敗する可能性があります。

cgroups構成の要件

Dockerプラグインはcgroupsを使用して、個々のコンテナのリソース使用量を制限します。起動されたコンテナはYARNに属するため、コマンドラインオプション--cgroup-parentを使用して適切な制御グループを定義します。

Dockerは、cgroupfssystemdの2つの異なるcgroupsドライバをサポートしています。cgroupfsのみがサポートされていることに注意してください。systemdを使用してDockerコンテナを起動しようとすると、次のような同様のエラーメッセージが表示されます。

Container id: container_1561638268473_0006_01_000002
Exit code: 7
Exception message: Launch container failed
Shell error output: /usr/bin/docker-current: Error response from daemon: cgroup-parent for systemd cgroup should be a valid slice named as "xxx.slice".
See '/usr/bin/docker-current run --help'.
Shell output: main : command provided 4

これは、systemdドライバが使用されている各ホストでDockerデーモンを再構成する必要があることを意味します。

Hadoopが実行されているOSに応じて、再構成には異なる手順が必要になる場合があります。ただし、cgroupsドライバにsystemdが選択されている場合、システムでsystemctlコマンドが使用できる可能性が高いです。

DockerデーモンのExecStartプロパティを確認してください。

~$ systemctl show --no-pager --property=ExecStart docker.service
ExecStart={ path=/usr/bin/dockerd-current ; argv[]=/usr/bin/dockerd-current --add-runtime
docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd
--userland-proxy-path=/usr/libexec/docker/docker-proxy-current
--init-path=/usr/libexec/docker/docker-init-current
--seccomp-profile=/etc/docker/seccomp.json
$OPTIONS $DOCKER_STORAGE_OPTIONS $DOCKER_NETWORK_OPTIONS $ADD_REGISTRY $BLOCK_REGISTRY $INSECURE_REGISTRY $REGISTRIES ;
ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }

この例は、native.cgroupdriversystemdであることを示しています。デーモンのユニットファイルでそれを変更する必要があります。

~$ sudo systemctl edit --full docker.service

これにより、編集のための構成全体が表示されます。systemd文字列をcgroupfsに置き換えるだけです。変更を保存し、systemdとDockerデーモンの両方を再起動します。

~$ sudo systemctl daemon-reload
~$ sudo systemctl restart docker.service

アプリケーションの提出

Dockerコンテナの起動を試みる前に、通常のYARNコンテナを要求するアプリケーションに対してLCE構成が機能していることを確認してください。LCEを有効にした後、1つ以上の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]の形式のいずれかである必要があります。有効なバインドプロパゲーションオプションは、shared、rshared、slave、rslave、private、およびrprivateです。要求されたマウントは、docker.allowed.ro-mountsdocker.allowed.rw-mountsに設定された値に基づいて、container-executorによって検証されます。
YARN_CONTAINER_RUNTIME_DOCKER_TMPFS_MOUNTS Dockerコンテナに追加のtmpfsマウントを追加します。環境変数の値は、コンテナ内の絶対マウントポイントのカンマ区切りリストである必要があります。
YARN_CONTAINER_RUNTIME_DOCKER_DELAYED_REMOVAL コンテナごとにDockerコンテナの削除を遅延させることを要求できるようにします。trueの場合、Dockerコンテナは、yarn.nodemanager.delete.debug-delay-secで定義された期間が経過するまで削除されません。管理者は、yarn-siteプロパティyarn.nodemanager.runtime.linux.docker.delayed-removal.allowedを使用してこの機能を無効にできます。この機能はデフォルトで無効になっています。この機能が無効になっているかfalseに設定されている場合、コンテナは終了するとすぐに削除されます。
YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE コンテナ作業ディレクトリのsysfsサブディレクトリのDockerコンテナ/hadoop/yarn/sysfsへのマウントを有効にします。これは、クラスタ情報をコンテナに設定するのに役立ちます。
YARN_CONTAINER_RUNTIME_DOCKER_SERVICE_MODE イメージで定義されているようにDockerコンテナを実行しますが、ユーザー(–userおよび–group-add)を設定しないサービスモードを有効にします。

最初の2つは必須です。残りは必要に応じて設定できます。環境変数を使用してコンテナの種類を制御することは、それほど理想的ではありませんが、YARNのDockerサポートを認識していないアプリケーション(MapReduceやSparkなど)でも、アプリケーション環境の構成をサポートすることで、それを利用できます。

Dockerコンテナで起動されるようにアプリケーションが提出されると、そのアプリケーションは他のYARNアプリケーションと同じように動作します。ログは集約され、関連する履歴サーバーに保存されます。アプリケーションライフサイクルは、Docker以外のアプリケーションと同じです。

Dockerバインドマウントボリュームの使用

警告 この機能を有効にする際には注意が必要です。/, /etc, /run, /homeなど、ただしこれらに限定されないディレクトリへのアクセスを有効にすることはお勧めできません。コンテナがホストに悪影響を与えたり、機密情報を漏洩する可能性があります。警告

ホストのファイルとディレクトリは、Dockerコンテナ内で一般的に必要であり、Dockerはボリュームを介して提供します。これには、ローカライズされたリソース、Apache Hadoopバイナリ、およびソケットが含まれます。このニーズに対応するために、YARN-6623では、コンテナにボリュームとしてバインドマウントすることを許可されているホストディレクトリのホワイトリストを設定する機能が管理者に追加されました。YARN-5534では、ユーザーがコンテナにマウントされるマウントのリストを提供する機能が追加されました(管理者のホワイトリストで許可されている場合)。

この機能を使用するには、次のものを構成する必要があります。

  • 管理者は、docker.allowed.ro-mountsdocker.allowed.rw-mountsをマウントを許可されている親ディレクトリのリストに設定することにより、container-executor.cfgでボリュームホワイトリストを定義する必要があります。
  • アプリケーション提出者は、YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS環境変数を使用して、アプリケーション提出時に必要なボリュームを要求します。

管理者によって提供されたホワイトリストは、コンテナにマウントすることを許可されているディレクトリのカンマ区切りリストとして定義されます。ユーザーによって提供されたソースディレクトリは、指定されたディレクトリと一致するか、その子である必要があります。

ユーザーが指定したマウントリストは、ソース:デスティネーション または ソース:デスティネーション:モード の形式で、コンマ区切りのリストとして定義されます。ソースはホスト上のファイルまたはディレクトリです。デスティネーションは、ソースがバインドマウントされるコンテナ内のパスです。モードは、ユーザーがマウントに期待するモードを定義し、ro(読み取り専用)またはrw(読み書き)のいずれかになります。指定されていない場合は、rwが想定されます。モードには、バインドプロパゲーションオプション(shared、rshared、slave、rslave、private、またはrprivate)を含めることもできます。その場合、モードはオプション、rw+オプション、またはro+オプション の形式にする必要があります。

次の例は、この機能を使用して、YARN上で実行されているコンテナに一般的に必要な/sys/fs/cgroupディレクトリをマウントする方法を示しています。

管理者は、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" も有効です。

Dockerコンテナでのユーザー管理

YARNのDockerコンテナサポートは、NodeManagerホストで定義されているユーザーのuid:gid IDを使用してコンテナプロセスを起動します。NodeManagerホストとコンテナ間のユーザー名とグループ名の不一致は、パーミッションの問題、コンテナ起動の失敗、さらにはセキュリティホールにつながる可能性があります。ホストとコンテナの両方でユーザーとグループの管理を一元化することで、これらのリスクを大幅に軽減できます。YARNでコンテナ化されたアプリケーションを実行する際には、コンテナのプロセスを起動するために使用されるuid:gidペアを理解する必要があります。

uid:gidペアの意味の例として、次のことを考えてみましょう。デフォルトでは、安全でないモードでは、YARNはユーザーnobodyとしてプロセスを起動します(ユーザーの実行方法については、YARNでのCGroupsの使用の一番下の表を参照してください)。CentOSベースのシステムでは、nobodyユーザーのuidは99nobodyグループは99です。その結果、YARNは--user 99:99を使用してdocker runを呼び出します。コンテナ内にuid 99を持つnobodyユーザーが存在しない場合、起動が失敗したり、予期しない結果になる可能性があります。

この規則の例外は、特権Dockerコンテナの使用です。特権コンテナは、コンテナの起動時にuid:gidペアを設定せず、DockerfileのUSERまたはGROUPエントリを尊重します。これにより、セキュリティ上の影響を伴う任意のユーザーとして特権コンテナを実行できます。特権Dockerコンテナを有効にする前に、これらの影響を理解してください。

ユーザーとグループの管理に対処するには多くの方法があります。Dockerはデフォルトで、コンテナ内の/etc/passwd(および/etc/shadow)に対してユーザーを認証します。Dockerイメージに提供されているデフォルトの/etc/passwdには、適切なユーザーエントリが含まれていない可能性が高く、起動エラーが発生します。ユーザーとグループの管理を一元化することを強くお勧めします。以下に、ユーザーとグループの管理に関するいくつかのアプローチの概要を示します。

静的ユーザー管理

ユーザーとグループを管理する最も基本的な方法は、Dockerイメージ内のユーザーとグループを変更することです。このアプローチは、すべてのコンテナプロセスが単一の既知のユーザー(たとえばnobody)として起動される安全でないモードでのみ実行可能です。この場合、唯一の要件は、nobodyユーザーとグループのuid:gidペアがホストとコンテナ間で一致することです。CentOSベースのシステムでは、これはコンテナ内のnobodyユーザーにUID 99、nobodyグループにGID 99が必要であることを意味します。

UIDとGIDを変更する1つの方法は、usermodgroupmodを利用することです。以下は、nobodyユーザー/グループに正しいUIDとGIDを設定します。

usermod -u 99 nobody
groupmod -g 99 nobody

このアプローチは、ユーザーを追加する柔軟性に欠けるため、テスト以外では推奨されません。

バインドマウント

組織がすでに各システムにローカルユーザーを作成するための自動化を導入している場合、コンテナイメージを直接変更する代わりに、/etc/passwdと/etc/groupをコンテナにバインドマウントすることが適切な場合があります。/etc/passwdと/etc/groupのバインドマウントを有効にするには、container-executor.cfgでdocker.allowed.ro-mountsを更新して、これらのパスを含めます。アプリケーションを送信する際、YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS/etc/passwd:/etc/passwd:ro/etc/group:/etc/group:roを含める必要があります。

このバインドマウントアプローチには、考慮すべきいくつかの課題があります。

  1. イメージで定義されているユーザーとグループは、ホストのユーザーとグループによって上書きされます。
  2. コンテナが起動した後、ユーザーとグループを追加することはできません。/etc/passwdと/etc/groupはコンテナ内で不変であるためです。ホストを動作不能にする可能性があるため、これらを読み書きマウントしないでください。

このアプローチは、実行中のコンテナを変更する柔軟性に欠けるため、テスト以外では推奨されません。

SSSD

ユーザーとグループを一元的に管理できる代替アプローチは、SSSDです。System Security Services Daemon(SSSD)は、LDAPやActive DirectoryなどのさまざまなIDおよび認証プロバイダーへのアクセスを提供します。

Linux認証の従来のスキーマは次のとおりです。

application -> libpam -> pam_authenticate -> pam_unix.so -> /etc/passwd

ユーザー検索にSSSDを使用する場合、次のようになります。

application -> libpam -> pam_authenticate -> pam_sss.so -> SSSD -> pam_unix.so -> /etc/passwd

SSSDが通信するUNIXソケットをコンテナにバインドマウントできます。これにより、SSSDクライアント側のライブラリは、ホストで実行されているSSSDに対して認証できるようになります。その結果、ユーザー情報はDockerイメージの/etc/passwdに存在する必要がなくなり、代わりにSSSDによって処理されます。

ホストとコンテナのステップバイステップ構成

  1. ホスト構成
  • パッケージのインストール
    # yum -y install sssd-common sssd-proxy
    
  • コンテナ用のPAMサービスを作成します。
    # cat /etc/pam.d/sss_proxy
    auth required pam_unix.so
    account required pam_unix.so
    password required pam_unix.so
    session required pam_unix.so
    
  • SSSD設定ファイル/etc/sssd/sssd.confを作成します。パーミッションは0600で、ファイルはroot:rootが所有している必要があります。
    # cat /etc/sssd/sssd/conf
    [sssd]
    services = nss,pam
    config_file_version = 2
    domains = proxy
    [nss]
    [pam]
    [domain/proxy]
    id_provider = proxy
    proxy_lib_name = files
    proxy_pam_target = sss_proxy
    
  • sssdを起動します
    # systemctl start sssd
    
  • sssdを使用してユーザーを取得できることを確認します
    # getent passwd -s sss localuser
    
  1. コンテナ設定

SSSDのUNIXソケットがそこに配置されているため、ホストからコンテナに/var/lib/sss/pipesディレクトリをバインドマウントすることが重要です。

-v /var/lib/sss/pipes:/var/lib/sss/pipes:rw
  1. コンテナ構成

以下のすべてのステップは、コンテナ自体で実行する必要があります。

  • sssクライアントライブラリのみをインストールします

    # yum -y install sssd-client
    
  • sssがpasswdとgroupデータベースに対して構成されていることを確認します

    /etc/nsswitch.conf
    
  • アプリケーションがSSSDを呼び出すために使用するPAMサービスを構成します

    # cat /etc/pam.d/system-auth
    #%PAM-1.0
    # This file is auto-generated.
    # User changes will be destroyed the next time authconfig is run.
    auth        required      pam_env.so
    auth        sufficient    pam_unix.so try_first_pass nullok
    auth        sufficient    pam_sss.so forward_pass
    auth        required      pam_deny.so
    
    account     required      pam_unix.so
    account     [default=bad success=ok user_unknown=ignore] pam_sss.so
    account     required      pam_permit.so
    
    password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
    password    sufficient    pam_unix.so try_first_pass use_authtok nullok sha512 shadow
    password    sufficient    pam_sss.so use_authtok
    password    required      pam_deny.so
    
    session     optional      pam_keyinit.so revoke
    session     required      pam_limits.so
    -session     optional      pam_systemd.so
    session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
    session     required      pam_unix.so
    session     optional      pam_sss.so
    
  • Dockerイメージを保存し、アプリケーションのベースイメージとして使用します。

  • YARN環境で起動されたDockerイメージをテストします。

    $ id
    uid=5000(localuser) gid=5000(localuser) groups=5000(localuser),1337(hadoop)
    

特権コンテナのセキュリティに関する考慮事項

特権Dockerコンテナは、ホストシステムデバイスとやり取りできます。これは、適切な注意を払わないと、ホストオペレーティングシステムに悪影響を与える可能性があります。Hadoopクラスタで特権コンテナの実行を許可することのリスクを軽減するために、許可されていない特権Dockerイメージをサンドボックス化するための制御されたプロセスを実装しました。

デフォルトの動作では、特権Dockerコンテナは許可されません。特権Dockerは、ENTRYPOINTが有効なDockerイメージの場合にのみ許可され、docker.privileged-containers.enabledが有効に設定されています。DockerイメージはDockerコンテナ内でroot権限で実行できますが、ホストレベルのデバイスへのアクセスは無効になります。これにより、開発者とテスターは、ホストオペレーティングシステムに悪影響を与えるのを防ぐためのいくつかの制限付きで、インターネットからDockerイメージを実行できます。

Dockerイメージが開発者とテスターによって信頼できるものとして認定された場合。信頼できるイメージは、信頼できるDockerレジストリに昇格させることができます。システム管理者はdocker.trusted.registriesを定義し、信頼できるイメージを昇格させるためにプライベートDockerレジストリサーバーを設定できます。システム管理者は、Docker Hubからの公式Dockerイメージを信頼できるレジストリの一部として許可することを選択できます。「library」は、公式Dockerイメージを信頼するために使用する名前です。Container-executor.cfgの例

[docker]
  docker.privileged-containers.enabled=true
  docker.trusted.registries=library

docker.privileged-containers.registriesを使用して、特権コンテナとして実行できるDockerイメージのサブセットのみを許可するように、きめ細かいアクセス制御を定義することもできます。docker.privileged-containers.registriesが定義されていない場合、YARNは特権Dockerイメージのアクセス制御としてdocker.trusted.registriesを使用します。きめ細かいアクセス制御の例

[docker]
  docker.privileged-containers.enabled=true
  docker.privileged-containers.registries=local/centos:latest
  docker.trusted.registries=library

開発環境では、ローカルイメージにリポジトリ名プレフィックスをタグ付けして、信頼を有効にすることができます。リポジトリ名を選択する推奨事項は、Docker Hubから誤ってDockerイメージをプルしたり、予約済みのDocker Hubキーワード「local」を使用したりしないように、ローカルホスト名とポート番号を使用することです。Docker runは、イメージがローカルに存在しない場合、Docker HubでDockerイメージを探します。イメージ名にローカルホスト名とポートを使用すると、Docker Hubからの標準イメージの誤ったプルを防ぐことができます。localhost:5000を信頼できるレジストリとしてタグ付けするイメージの例

docker tag centos:latest localhost:5000/centos:latest

ローカルリポジトリに変更を加えたUbuntuベースのイメージがあり、それを使用したいとします。次の例は、local_ubuntuイメージにタグを付けます。

docker tag local_ubuntu local/ubuntu:latest

次に、docker.trusted.registrieslocalを追加する必要があります。イメージはlocal/ubuntuを使用して参照できます。

信頼できるイメージは、NFSゲートウェイを介したHDFSやホストレベルのHadoop構成など、外部デバイスのマウントが許可されます。システム管理者がdocker.allow.rw-mountsディレクティブを使用して外部ボリュームへの書き込みを許可する場合、特権Dockerコンテナは、事前に定義されたボリューム内のホストレベルのファイルを完全に制御できます。

YARNサービスHTTPDの例では、container-executor.cfgで、例を実行するためにcentos Dockerレジストリを信頼できるものとして定義する必要があります。

コンテナ再取得の要件

再起動時、NodeManagerはNodeManagerの復旧プロセスの一環として、/procファイルシステム内のコンテナのPIDディレクトリの存在を確認することにより、コンテナがまだ実行されていることを検証します。セキュリティの目的で、オペレーティングシステム管理者は、/procファイルシステムに*hidepid*マウントオプションを有効にする場合があります。*hidepid*オプションが有効になっている場合、*yarn*ユーザーのプライマリグループを、以下の例のようなgidマウントフラグを設定してホワイトリストに登録する必要があります。*yarn*ユーザーのプライマリグループがホワイトリストに登録されていない場合、コンテナの再取得は失敗し、コンテナはNodeManagerの再起動時に強制終了されます。

proc     /proc     proc     nosuid,nodev,noexec,hidepid=2,gid=yarn     0 0

信頼できるDockerレジストリへの接続

Dockerクライアントコマンドは、NodeManagerホストの$HOME/.docker/config.jsonであるデフォルトの場所から構成を取得します。Docker構成は、安全なリポジトリの資格情報が保存される場所であるため、この方法を使用して安全なDockerリポジトリでLCEを使用することはお勧めしません。

YARN-5428は、Dockerクライアント構成を安全に提供するための分散シェルへのサポートを追加しました。使用方法については、分散シェルのヘルプを参照してください。他のフレームワークのサポートは計画されています。

回避策として、Docker loginコマンドを使用して、すべてのNodeManagerホストでDockerデーモンを安全なリポジトリに手動でログインできます。

  docker login [OPTIONS] [SERVER]

  Register or log in to a Docker registry server, if no server is specified
  "https://index.docker.io/v1/" is the default.

  -e, --email=""       Email
  -p, --password=""    Password
  -u, --username=""    Username

このアプローチは、すべてのユーザーが安全なリポジトリにアクセスできることを意味することに注意してください。

Hadoopは、YARNサービスAPIを介してDocker Trusted Registryと統合されます。Dockerレジストリは、CSIドライバを使用して、HDFS、S3、または外部ストレージにDockerイメージを保存できます。

HDFS上のDockerレジストリ

NFSゲートウェイは、HDFSをNFSマウントポイントとしてマウントする機能を提供します。Dockerレジストリは、標準ファイルシステムAPIを使用してHDFSマウントポイントに書き込むように構成できます。

hdfs-site.xmlで、NFS構成を構成します。

    <property>
      <name>nfs.exports.allowed.hosts</name>
      <value>* rw</value>
    </property>

    <property>
      <name>nfs.file.dump.dir</name>
      <value>/tmp/.hdfs-nfs</value>
    </property>

    <property>
      <name>nfs.kerberos.principal</name>
      <value>nfs/_HOST@EXAMPLE.COM</value>
    </property>

    <property>
      <name>nfs.keytab.file</name>
      <value>/etc/security/keytabs/nfs.service.keytab</value>
    </property>

hdfsユーザーを使用して、すべてのデータノードでNFSゲートウェイを実行します。

$ $HADOOP_HOME/bin/hdfs --daemon start nfs3

各データノードで、/hdfsを使用してnfsマウントポイントが公開されます。

# mount -t nfs -o vers=3,proto=tcp,nolock,noacl,sync $DN_IP:/ /hdfs

ここで、DN_IPはデータノードのIPアドレスです。

Container-executor.cfgは、libraryからの信頼できるDockerイメージを許可するように構成されています。

[docker]
  docker.privileged-containers.enabled=true
  docker.trusted.registries=library,registry.docker-registry.registry.example.com:5000
  docker.allowed.rw-mounts=/tmp,/usr/local/hadoop/logs,/hdfs

Dockerレジストリは、YARNサービスを使用して開始できます:registry.json

{
  "name": "docker-registry",
  "version": "1.0",
  "kerberos_principal" : {
    "principal_name" : "registry/_HOST@EXAMPLE.COM",
    "keytab" : "file:///etc/security/keytabs/registry.service.keytab"
  },
  "components" :
  [
    {
      "name": "registry",
      "number_of_containers": 1,
      "artifact": {
        "id": "registry:latest",
        "type": "DOCKER"
      },
      "resource": {
        "cpus": 1,
        "memory": "256"
      },
      "run_privileged_container": true,
      "configuration": {
        "env": {
          "YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE":"true",
          "YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS":"/hdfs/apps/docker/registry:/var/lib/registry"
        },
        "properties": {
          "docker.network": "host"
        }
      }
    }
  ]
}

YARNサービスは、/hdfs/apps/docker/registryからDockerコンテナ内の/var/lib/registryへのDockerマウントを構成します。

yarn app -launch docker-registry /tmp/registry.json

Dockerの信頼できるレジストリはYARNフレームワークにデプロイされ、レジストリにアクセスするためのURLはHadoopレジストリのDNS形式に従います。

registry.docker-registry.$USER.$DOMAIN:5000

docker-registryアプリケーションがYARNでSTABLE状態に達すると、ユーザーはイメージ名をregistry.docker-registry.registry.example.com:5000/でプレフィックスすることで、Dockerの信頼できるレジストリにDockerイメージをプッシュまたはプルできます。

S3上のDockerレジストリ

Docker Registryは独自のS3ドライバとYAML構成を提供します。YARNサービス構成はYAMLテンプレートを生成し、Docker RegistryからS3ストレージへの直接アクセスを有効にします。このオプションは、AWSへのDocker Trusted Registryの展開において最良の選択肢です。Docker RegistryのストレージドライバをS3に構成するには、/etc/docker/registry/config.ymlファイル(YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS経由)をマウントする必要があります。これには、対応するアクセスキーとシークレットキーを使用してS3バケットを構成する必要があります。

config.ymlのサンプル

version: 0.1
log:
    fields:
        service: registry
http:
    addr: :5000
storage:
    cache:
        blobdescriptor: inmemory
    s3:
        accesskey: #AWS_KEY#
        secretkey: #AWS_SECRET#
        region: #AWS_REGION#
        bucket: #AWS_BUCKET#
        encrypt: #ENCRYPT#
        secure:  #SECURE#
        chunksize: 5242880
        multipartcopychunksize: 33554432
        multipartcopymaxconcurrency: 100
        multipartcopythresholdsize: 33554432
        rootdirectory: #STORAGE_PATH#

Dockerレジストリは、YARNサービスを使用して開始できます:registry.json

{
  "name": "docker-registry",
  "version": "1.0",
  "kerberos_principal" : {
    "principal_name" : "registry/_HOST@EXAMPLE.COM",
    "keytab" : "file:///etc/security/keytabs/registry.service.keytab"
  },
  "components" :
  [
    {
      "name": "registry",
      "number_of_containers": 1,
      "artifact": {
        "id": "registry:latest",
        "type": "DOCKER"
      },
      "resource": {
        "cpus": 1,
        "memory": "256"
      },
      "run_privileged_container": true,
      "configuration": {
        "env": {
          "YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE":"true",
          "YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS":"<path to config.yml>:/etc/docker/registry/config.yml",
        },
        "properties": {
          "docker.network": "host"
        }
      }
    }
  ]
}

S3ストレージドライバで構成できる詳細およびパラメータについては、https://docs.docker.com/registry/storage-drivers/s3/を参照してください。

例:MapReduce

この例では、Hadoopが/usr/local/hadoopにインストールされていることを前提としています。

さらに、container-executor.cfg内のdocker.allowed.ro-mountsは、/usr/local/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"

  export YARN_CONTAINER_RUNTIME_TYPE=docker
  export YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$IMAGE_ID
  export YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS=$MOUNTS

  yarn jar $YARN_EXAMPLES_JAR pi \
    -Dmapreduce.map.env.YARN_CONTAINER_RUNTIME_TYPE=docker \
    -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=docker \
    -Dmapreduce.reduce.env.YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS=$MOUNTS \
    -Dmapreduce.reduce.env.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE=$IMAGE_ID \
    1 40000

アプリケーションマスター、マップタスク、およびリダイスタスクは個別に構成されていることに注意してください。この例では、3つすべてにopenjdk:8イメージを使用しています。

例:Spark

この例では、Hadoopが/usr/local/hadoopに、Sparkが/usr/local/sparkにインストールされていることを前提としています。

さらに、container-executor.cfg内のdocker.allowed.ro-mountsは、/usr/local/hadoop,/etc/passwd,/etc/groupディレクトリを含むように更新されています。

DockerコンテナでSparkシェルを実行するには、次のコマンドを実行します。

  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 --master yarn \
    --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イメージを使用しています。

DockerコンテナENTRYPOINTサポート

Hadoop 2.xにDockerサポートが導入されたとき、プラットフォームは既存のHadoopプログラムをDockerコンテナ内で実行するように設計されていました。ログのリダイレクトと環境設定はNode Managerと統合されています。Hadoop 3.xでは、Hadoopワークロードの実行を超えてDockerコンテナをサポートし、dockerfileのENTRYPOINTを使用してネイティブ形式でDockerコンテナをサポートします。アプリケーションは、YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE環境変数を定義することにより、デフォルトでYARNモードをサポートするか、デフォルトでDockerモードをサポートするかを決定できます。システム管理者は、クラスタのデフォルト設定としてENTRY_POINTをデフォルトの動作モードにすることもできます。

yarn-site.xmlに、YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLEをノードマネージャの環境ホワイトリストに追加します。

<property>
        <name>yarn.nodemanager.env-whitelist</name>
        <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,HADOOP_YARN_HOME,HADOOP_HOME,PATH,LANG,TZ,HADOOP_MAPRED_HOME,YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE</value>
</property>

yarn-env.shで、次のように定義します。

export YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE=true

ENTRYPOINTを使用しない場合の要件(YARNモード)

ENTRYPOINTを使用しない場合、2つの要件があります。

  1. /bin/bashはイメージ内で使用可能である必要があります。これは一般的には当てはまりますが、小さなDockerイメージ(例:シェルコマンドにbusyboxを使用するもの)にはbashがインストールされていない場合があります。この場合、次のエラーが表示されます。

    Container id: container_1561638268473_0015_01_000002
    Exit code: 7
    Exception message: Launch container failed
    Shell error output: /usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:235: starting container process caused "exec: \"bash\": executable file not found in $PATH".
    Shell output: main : command provided 4
    
  2. findコマンドもイメージ内で使用可能である必要があります。findがないと、このエラーが発生します。

    Container exited with a non-zero exit code 127. Error file: prelaunch.err.
    Last 4096 bytes of prelaunch.err :
    /tmp/hadoop-systest/nm-local-dir/usercache/hadoopuser/appcache/application_1561638268473_0017/container_1561638268473_0017_01_000002/launch_container.sh: line 44: find: command not found
    

DockerコンテナYARN SysFSサポート

YARN SysFSは、YARNフレームワークによって提供される疑似ファイルシステムであり、クラスタリング情報をDockerコンテナにエクスポートします。クラスタ情報は/hadoop/yarn/sysfsパスにエクスポートされます。このAPIを使用すると、アプリケーション開発者は外部サービスの依存関係なしにクラスタリング情報を取得できます。カスタムアプリケーションマスターは、ノードマネージャのREST APIを呼び出すことでクラスタ情報を設定できます。YARNサービスフレームワークは、クラスタ情報を/hadoop/yarn/sysfs/app.jsonに自動的に設定します。YARNサービスの詳細については、YARNサービスを参照してください。

Dockerコンテナサービスモード

Dockerコンテナサービスモードは、イメージで定義されているとおりにコンテナを実行しますが、ユーザー(–userおよび–group-add)を設定しません。このモードはデフォルトで無効になっています。管理者は、dockerセクションの下にあるcontainer-executor.cfgでdocker.service-mode.enabledをtrueに設定して有効にします。

Dockerサービスモードを許可するcontainer-executor.cfgの一部を以下に示します。

yarn.nodemanager.linux-container-executor.group=yarn
[docker]
  module.enabled=true
  docker.privileged-containers.enabled=true
  docker.service-mode.enabled=true

アプリケーションユーザーは、アプリケーションの環境で環境変数YARN_CONTAINER_RUNTIME_DOCKER_SERVICE_MODEをそれぞれtrueまたはfalseの値でエクスポートすることにより、ジョブレベルでサービスモードを有効または無効にすることができます。