[[Hadoop2.0セットアップ]] >

&ref(images/note.png,nolink);&color(red){''DEPRECATED!: このバージョンのHadoopはすでに古いものです。ご利用は非推奨です。''};[[Hadoop2.1withSecurityセットアップ]]をご参照ください。

これは、Apache Hadoopの&color(green){''2.0系最新版''};のセキュアセットアップ手順です。

* 目次 [#w9d85911]
#contents

* はじめに [#y524edc2]

- このドキュメントでは、Hadoopのセキュア設定の方法を重点的に解説しています。セキュリティ以外の基本的な設定方法については、まずは[[Hadoop2.0セットアップ]]をご参照ください。
- セキュアHadoopのアーキテクチャ概要については、HadoopWithSecurityをご参照ください。

* 他のバージョンのセットアップ [#m1eeec68]

+ [[Hadoop2.0.3alpha>Hadoop2.0.3aWithSecurityセットアップ]] - &color(red){''DEPRECATED''};
+ [[Hadoop2.0.2alpha>Hadoop2.0.2aWithSecurityセットアップ]] - &color(red){''DEPRECATED''};
+ [[Hadoop2.0.1alpha>Hadoop2.0.1aWithSecurityセットアップ]] - &color(red){''DEPRECATED''};

* セットアップ [#x366aceb]

** Chefレシピ [#vc138a73]

参考までに、これらはここで説明している環境を構築する[[Chef]]レシピ(ロール)です。ただし、Java、Kerberos、LDAPの一部およびビルドが必要なHadoopのバイナリについてのセットアップを除きます。
- &ref(images/cake.png,nolink);[[grid-chef-repo:/roles]]/''hadoop-pseudo-distributed-with-security.rb''
- &ref(images/cake.png,nolink);[[grid-chef-repo:/roles]]/''hadoop-pleiades-with-security.rb''
-- これらのロールで定義されているHadoopのデフォルトバージョンは(現時点で)安定版の1.x系ですので、以下の要領でロールを新たに定義して2.0.xのバージョンを指定して使用します。必要に応じて他の属性を設定します。
#geshi(ruby,number){{
name 'test-on-secure-env'
description 'Testing on secure env.'

run_list(
  'role[hadoop-pseudo-distributed-with-security]'
  # or 
  #'role[hadoop-pleiades-with-security]'
)

default_attributes(
  'hadoop' => {
    'version' => '2.0.4-alpha'
  }
)
}}

** Java [#ke571fc2]

+ Oracle(旧Sun)のJDKでは、後述のKerberos認証で強度の高いAES256暗号を利用するためには、''強度が無制限のJCE管轄ポリシーファイル''をインストールする必要があります。インストールにあたっては、[[Javaにおける高強度暗号の利用]]をご参照ください。&color(blue){※OpenJDKなどでは不要です。};

** Kerberos認証環境 [#d1ac69a9]

+ 基本的なKerberos AdminサーバおよびKDCの構築については、[[KerberosセットアップforHadoop]]をご参照ください。
+ 検証目的の場合には、レルムは任意のもの(例えば、LOCALHOST、LOCALDOMAIN等)で構いません。

*** 管理者のユーザプリンシパルの追加 [#m171418a]

+ 管理者(hdfs、yarn、mapred)のユーザプリンシパルを追加しておきます。
#geshi{{
kadmin.local:  add_principal hdfs
...
kadmin.local:  add_principal yarn
...
kadmin.local:  add_principal mapred
...
}}

*** 疑似分散モード(シングルノード)に必要なプリンシパルの準備 [#ae49742b]

+ 必要なサービスプリンシパルをランダム暗号鍵を用いて追加し、keytabファイルを作成します。チェックポイント機構のプロトコルには従来のKSSLではなく、推奨のSPNEGO/Kerberosを使用しますので、host/ プリンシパルの追加は不要です。
#geshi(){{
$ sudo mkdir -p /grid/etc/keytabs/localhost
$ sudo kadmin.local
...
kadmin.local:  add_principal -randkey hdfs/localhost
...
kadmin.local:  add_principal -randkey yarn/localhost
...
kadmin.local:  add_principal -randkey mapred/localhost
...
kadmin.local:  add_principal -randkey HTTP/localhost
...
kadmin.local:  ktadd -k /grid/etc/keytabs/localhost/localhost.keytab -glob */localhost
}}
+ keytabファイルの内容を確認し、適切なパーミッションを設定します。keytabファイルは一つで足りますが、Hadoopの設定に統一感が出るようにシンボリックリンクを張っておきます。
#geshi(){{
$ sudo klist -e -k -t /grid/etc/keytabs/localhost/localhost.keytab
Keytab name: FILE:/grid/etc/keytabs/localhost/localhost.keytab
KVNO Timestamp        Principal
---- ---------------- ---------------------------------------------------------
   2 22/08/2012 21:33 yarn/localhost@LOCALDOMAIN (aes256-cts-hmac-sha1-96) 
   2 22/08/2012 21:33 yarn/localhost@LOCALDOMAIN (aes128-cts-hmac-sha1-96) 
   2 22/08/2012 21:22 yarn/localhost@LOCALDOMAIN (arcfour-hmac) 
   2 22/08/2012 21:35 hdfs/localhost@LOCALDOMAIN (aes256-cts-hmac-sha1-96) 
   2 22/08/2012 21:35 hdfs/localhost@LOCALDOMAIN (aes128-cts-hmac-sha1-96) 
   2 22/08/2012 21:35 hdfs/localhost@LOCALDOMAIN (arcfour-hmac) 
   2 22/08/2012 21:36 mapred/localhost@LOCALDOMAIN (aes256-cts-hmac-sha1-96) 
   2 22/08/2012 21:36 mapred/localhost@LOCALDOMAIN (aes128-cts-hmac-sha1-96) 
   2 22/08/2012 21:36 mapred/localhost@LOCALDOMAIN (arcfour-hmac) 
   2 22/08/2012 21:38 HTTP/localhost@LOCALDOMAIN (aes256-cts-hmac-sha1-96) 
   2 22/08/2012 21:38 HTTP/localhost@LOCALDOMAIN (aes128-cts-hmac-sha1-96) 
   2 22/08/2012 21:38 HTTP/localhost@LOCALDOMAIN (arcfour-hmac) 

$ cd /grid/etc/keytabs/localhost
$ sudo chown root:hadoop localhost.keytab
$ sudo chmod 440         localhost.keytab
$ sudo ln -s localhost.keytab nn.keytab
$ sudo ln -s localhost.keytab cn.keytab
$ sudo ln -s localhost.keytab dn.keytab
$ sudo ln -s localhost.keytab rm.keytab
$ sudo ln -s localhost.keytab nm.keytab
$ sudo ln -s localhost.keytab jh.keytab
$ sudo ln -s localhost.keytab HTTP.keytab
}}

*** 完全分散モードに必要なサービスプリンシパルの準備 [#h431d4d6]

- 例示環境の詳細については、[[Hadoop完全分散モデル環境]]をご参照ください。
+ 各ノードで必要なプリンシパルをランダム暗号鍵を用いて追加し、それぞれのkeytabファイルを作成します。
#geshi{{
kadmin.local:  add_principal -randkey hdfs/pleiades-nn.grid.example.com
WARNING: no policy specified for hdfs/pleiades-nn.grid.example.com@GRID.EXAMPLE.COM; defaulting to no policy
Principal "hdfs/pleiades-nn.grid.example.com@GRID.EXAMPLE.COM" created.
kadmin.local:  add_principal -randkey hdfs/pleiades-cn.grid.example.com
...
kadmin.local:  add_principal -randkey hdfs/dn00000.grid.example.com
...
kadmin.local:  add_principal -randkey hdfs/dn00001.grid.example.com
...
kadmin.local:  add_principal -randkey yarn/pleiades-rm.grid.example.com
...
kadmin.local:  add_principal -randkey yarn/dn00000.grid.example.com
...
kadmin.local:  add_principal -randkey yarn/dn00001.grid.example.com
...
kadmin.local:  add_principal -randkey mapred/pleiades-jh.grid.example.com
...
kadmin.local:  add_principal -randkey HTTP/pleiades-nn.grid.example.com
...
kadmin.local:  add_principal -randkey HTTP/pleiades-cn.grid.example.com
...
kadmin.local:  add_principal -randkey HTTP/pleiades-rm.grid.example.com
...
kadmin.local:  add_principal -randkey HTTP/pleiades-jh.grid.example.com
...
kadmin.local:  add_principal -randkey HTTP/dn00000.grid.example.com
...
kadmin.local:  add_principal -randkey HTTP/dn00001.grid.example.com
...
}}
#geshi{{
$ sudo mkdir -p /grid/etc/keytabs/pleiades
$ sudo kadmin.local
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/nn.keytab -glob */pleiades-nn.grid.example.com
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/cn.keytab -glob */pleiades-cn.grid.example.com
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/rm.keytab -glob */pleiades-rm.grid.example.com
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/jh.keytab -glob */pleiades-jh.grid.example.com
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/dn00000-dn.keytab -p hdfs/dn00000.grid.example.com
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/dn00001-dn.keytab -p hdfs/dn00001.grid.example.com
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/dn00000-nm.keytab -p yarn/dn00000.grid.example.com
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/dn00001-nm.keytab -p yarn/dn00001.grid.example.com
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/dn00000-HTTP.keytab -p HTTP/dn00000.grid.example.com
...
kadmin.local:  ktadd -k /grid/etc/keytabs/pleiades/dn00001-HTTP.keytab -p HTTP/dn00001.grid.example.com
...
}}
+ 各ノードに必要keytabファイルを配備します。DataNode/NodeManagerのkeytabファイルについては、設定の便宜のため配備後、ホスト名部分を削除した ''dn.keytab''、''nm.keytab''、''dn-HTTP.keytab'' にリネームします。keytabファイルの参照権限は、(LDAP認可環境セットアップ後に)各Hadoopデーモンプロセスの起動ユーザにのみ付与します。また、各ノードのSPNEGO用に ''HTTP/'' プリンシパルを含むkeytabファイルに対して ''HTTP.keytab'' という名前でシンボリックリンクを張ります。
#geshi{{
 *:$ cd /grid/etc/keytabs/pleiades
nn:$ sudo chown hdfs:hdfs {nn,cn}.keytab
nn:$ sudo chmod 400       {nn,cn}.keytab
rm:$ sudo chown yarn:yarn rm.keytab
rm:$ sudo chmod 400       rm.keytab
dn:$ sudo chown hdfs:hdfs dn.keytab
dn:$ sudo chmod 400       dn.keytab
dn:$ sudo chown yarn:yarn nm.keytab
dn:$ sudo chmod 400       nm.keytab
dn:$ sudo chown yarn:hadoop dn-HTTP.keytab
dn:$ sudo chmod 440         dn-HTTP.keytab    # for DataNode & NodeManager
jh:$ sudo chown mapred:mapred jh.keytab
jh:$ sudo chmod 400           jh.keytab

# SPNEGO用プリンシパルのために各ノードで適当なkeytabにシンボリックリンクします
 *:$ sudo ln -s {{nn,cn,rm,jh},dn-HTTP}.keytab HTTP.keytab
}}

** LDAP認可環境 [#k7d71a49]

+ 各ノードのOSレベル、Hadoopレベルでの権限認可(グループ解決)をすべてLDAPに委ねます。
+ 構築方法の詳細については、[[LDAPセットアップforHadoop]]をご参照ください。
+ Hadoop 2.0には ''hadoop.security.group.mapping'' に設定する GroupMappingServiceProvider として LdapGroupsMapping が追加されていますが、最終的にユーザ権限でTaskプロセスを起動させる関係上、権限解決はOSレベル(NSS)に統一して委譲するのが効果的です。そのような点で、後述の通り ''JniBasedUnixGroupsMapping'' を使用するのが運用、パフォーマンス両面で最も効果的です。

** セキュアHadoop基盤 [#t5af1a31]

- テスト環境としてセットアップしやすいように、以下の例では主にKerberos認証環境の設定について疑似分散(シングルノード)の設定例を示しています。完全分散([[Hadoop完全分散モデル環境]])の設定は、XMLのコメントとして添えてありますのでご参照ください。
- &ref(images/note.png,nolink);プリンシパルの設定に利用できる特殊変数 ''_HOST'' はコンテクストによってその置換規則が異なります。明示的な設定では柔軟に対応できない場合(例えば、dfs.web.authentication.kerberos.principal)がありますので、基本的には _HOST を使用して設定すべきです。
-- 原則的に、マスタノード(NameNode、ResourceManager)の場合にはサービスするDNS名で置換され、ワーカノード(DataNode、NodeManager)の場合にはその hostname で置換されます。またマスタノードでサービスするDNS名は該当する各プロパティ(fs.defaultFS等)の値によって判断されますので注意が必要です(デフォルト設定ではなく明示的に設定する必要があります)。さらに、プロパティによってはバージョンによって _HOST の利用が未実装の場合(例えば、1.0.xおよび1.1.xのhadoop.http.authentication.kerberos.principal)がありますので、その点も注意する必要があります。
-- ただし、疑似分散環境(localhost)の場合には、通常のサーバセットアップで hostname に localhost を設定していることはまずないと思いますので、プリンシパルには明示的に localhost を設定する必要があります。
- すべての設定後に各デーモンを再起動し反映させる必要があります。特にセキュアDataNodeについては後述の通り起動方法が若干変更になりますので、ご注意ください。

+ ${HADOOP_PREFIX}/etc/hadoop/''core-site.xml'': ''this.*'' で始まるのプロパティは、設定を容易にするためのものです。
#geshi(xml,number){{
    <property>
        <name>this.cluster.name</name>
        <value>localhost</value>
        <!-- <value>pleiades</value> -->
    </property>
    <property>
        <name>this.domain</name>
        <value>localhost</value>
        <!-- <value>grid.example.com</value> -->
    </property>
    <property>
        <name>this.realm</name>
        <value>LOCALDOMAIN</value>
        <!-- <value>GRID.EXAMPLE.COM</value> -->
    </property>
    <property>
        <name>this.keytab.dir</name>
        <value>/grid/etc/keytabs/${this.cluster.name}</value>
    </property>
    <property>
        <name>this.namenode.fqdn</name>
        <value>localhost</value>
        <!-- <value>${this.cluster.name}-nn.${this.domain}</value> -->
    </property>
 
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://${this.namenode.fqdn}:9000/</value>
    </property>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/tmp/hadoop-${user.name}</value>
    </property>

    <property>
        <name>hadoop.security.authentication</name>
        <value>kerberos</value>
        <description>
            Set the authentication for the cluster. Valid values are: simple or
            kerberos.
        </description>
    </property>
    <property>
        <name>hadoop.security.authorization</name>
        <value>true</value>
        <description>
            Enable authorization for different protocols.
        </description>
    </property>
<!--
    <property>
        <name>hadoop.security.auth_to_local</name>
        <value>
            RULE:[2:$1@$0](.*@${this.realm})s/@.*//
            RULE:[1:$1@$0](.*@${this.realm})s/@.*//
            RULE:[2:$1@$0](hdfs@.*${this.realm})s/.*/hdfs/
            RULE:[2:$1@$0](yarn@.*${this.realm})s/.*/yarn/
            RULE:[2:$1@$0](mapred@.*${this.realm})s/.*/mapred/
            DEFAULT
        </value>
    </property>
-->
    <property>
        <name>hadoop.security.group.mapping</name>
        <value>org.apache.hadoop.security.JniBasedUnixGroupsMapping</value>
    </property>
<!--
    <property>
        <name>hadoop.security.groups.cache.secs</name>
        <value>14400</value>
    </property>
    <property>
        <name>hadoop.kerberos.kinit.command</name>
        <value>/usr/bin/kinit</value>
    </property>
-->
}}
+ ${HADOOP_PREFIX}/etc/hadoop/''hdfs-site.xml''
#geshi(xml,number){{
    <property>
        <name>this.secondary.namenode.fqdn</name>
        <value>localhost</value>
        <!-- <value>${this.cluster.name}-cn.${this.domain}</value> -->
    </property>
    <!-- (...) -->
    <property>
        <name>dfs.namenode.kerberos.principal</name>
        <value>hdfs/_HOST@${this.realm}</value>
        <!-- _HOST is replaced with the fs.defaultFS's host name -->
        <!-- <value>hdfs/${this.namenode.fqdn}@${this.realm}</value> -->
        <description>Kerberos principal name for the NameNode</description>
    </property>
    <property>
        <name>dfs.namenode.keytab.file</name>
        <value>${this.keytab.dir}/nn.keytab</value>
        <description>
            Combined keytab file containing the namenode service and host
            principals.
        </description>
    </property>
    <property>
        <name>dfs.secondary.namenode.kerberos.principal</name>
        <value>hdfs/${this.secondary.namenode.fqdn}@${this.realm}</value>
        <!-- <value>hdfs/_HOST@${this.realm}</value> -->
        <description>
            Kerberos principal name for the secondary NameNode.
        </description>
    </property>
    <property>
        <name>dfs.secondary.namenode.keytab.file</name>
        <value>${this.keytab.dir}/cn.keytab</value>
        <description>
            Combined keytab file containing the namenode service and host
            principals.
        </description>
    </property>
    <property>
        <name>dfs.block.access.token.enable</name>
        <value>true</value>
        <description>
            If "true", access tokens are used as capabilities for accessing
            datanodes.
            If "false", no access tokens are checked on accessing datanodes.
        </description>
    </property>
    <property>
        <name>dfs.datanode.kerberos.principal</name>
        <value>hdfs/localhost@${this.realm}</value>
        <!-- <value>hdfs/_HOST@${this.realm}</value> -->
        <description>
            The Kerberos principal that the DataNode runs as. "_HOST" is
            replaced by the real host name.
        </description>
    </property>
    <property>
        <name>dfs.datanode.keytab.file</name>
        <value>${this.keytab.dir}/dn.keytab</value>
        <description>
            The filename of the keytab file for the DataNode.
        </description>
    </property>
    <!-- (...) -->
    <property>
        <name>dfs.namenode.kerberos.internal.spnego.principal</name>
        <value>${dfs.web.authentication.kerberos.principal}</value>
        <!-- <value>HTTP/_HOST@${this.realm}</value> -->
        <!-- _HOST is replaced with dfs.namenode.http-address's host name. -->
    </property>
    <property>
        <name>dfs.secondary.namenode.kerberos.internal.spnego.principal</name>
        <value>${dfs.web.authentication.kerberos.principal}</value>
        <!-- <value>HTTP/_HOST@${this.realm}</value> -->
        <!-- _HOST is replaced with dfs.namenode.secondary.http-address's host name. -->
    </property>
}}
++ &ref(images/info.png,nolink);''SPNEGO/Kerberos の追加と KSSL(Kerberized SSL、TLS/Kerberos)の非推奨化''
+++ これまでHDFSのファイルシステムイメージの転送やfsckには通信プロトコルとしてKSSLが使用されてきましたが、JDK 6のバグ([[6946669>http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6946669]])によりKerberosチケットの暗号タイプに高強度のものを利用できないため、セキュリティの観点から代替プロトコルとしてSPNEGO/Kerberosが追加され、KSSLの利用は非推奨となりました([[HDFS-2617>https://issues.apache.org/jira/browse/HDFS-2617]])。
+++ Apache Hadoop では、実際に ''1.1.0'' と ''2.0.2-alpha'' 以降で SPNEGO/Kerberos 対応が追加されており、それでも KSSL を利用したい場合には明示的にプロパティ ''hadoop.security.use-weak-http-crypto'' に true を設定する必要があります。
+++ この説明では、推奨の SPNEGO/Kerberos にてセットアップを行なっています。
+ ${HADOOP_PREFIX}/etc/hadoop/''yarn-site.xml''
#geshi(xml,number){{
    <property>
        <name>this.resourcemanager.fqdn</name>
        <value>localhost</value>
        <!-- <value>${this.cluster.name}-rm.${this.domain}</value> -->
    </property>
    <!-- (...) -->
    <property>
        <name>yarn.acl.enable</name>
        <value>true</value>
    </property>
    <property>
        <name>yarn.admin.acl</name>
        <value> yarn,gridops</value>
    </property>
    <property>
        <name>yarn.resourcemanager.principal</name>
        <value>yarn/${this.resourcemanager.fqdn}@${this.realm}</value>
        <!-- <value>yarn/_HOST@${this.realm}</value> -->
    </property>
    <property>
        <name>yarn.resourcemanager.keytab</name>
        <value>${this.keytab.dir}/rm.keytab</value>
    </property>
    <property>
        <name>yarn.nodemanager.principal</name>
        <value>yarn/localhost@${this.realm}</value>
        <!-- <value>yarn/_HOST@${this.realm}</value> -->
    </property>
    <property>
        <name>yarn.nodemanager.keytab</name>
        <value>${this.keytab.dir}/nm.keytab</value>
    </property>
    <property>
        <name>yarn.nodemanager.admin-env</name>
        <value>MALLOC_ARENA_MAX=$MALLOC_ARENA_MAX,LD_LIBRARY_PATH=${HADOOP_COMMON_HOME}/lib/native</value>
    </property>
}}
++ ドキュメントでは、''yarn.acl.enable'' のデフォルト値は false とありますが、実際には true です。しかしながら、明示的に true に設定しておきます。
++ &ref(images/note.png,nolink);デフォルト設定では、ネイティブライブラリのロードに失敗し MRAppMaster が起動できない場合がありますので、''yarn.nodemanager.admin-env'' に環境変数 ''LD_LIBRARY_PATH'' の設定を追加しています([[MAPREDUCE-4072>https://issues.apache.org/jira/browse/MAPREDUCE-4072]]も参照のこと)。
//#geshi(text,number){{
//}}
+ ${HADOOP_PREFIX}/etc/hadoop/''mapred-site.xml''
#geshi(xml,number){{
    <property>
        <name>this.jobhistory.fqdn</name>
        <value>localhost</value>
        <!-- <value>${this.cluster.name}-jh.${this.domain}</value> -->
    </property>
    <!-- (...) -->
    <property>
        <name>mapreduce.jobhistory.principal</name>
        <value>mapred/${this.jobhistory.fqdn}@${this.realm}</value>
        <!-- <value>mapred/_HOST@${this.realm}</value> -->
    </property>
    <property>
        <name>mapreduce.jobhistory.keytab</name>
        <value>${this.keytab.dir}/jh.keytab</value>
    </property>
}}
+ YARNではスケジューラが独立したため、キューの設定は ${HADOOP_PREFIX}/etc/hadoop/''mapred-queues.xml'' ではなく、${HADOOP_PREFIX}/etc/hadoop/''capacity-scheduler.xml'' のみで行います。詳細は後述のCapacitySchedulerのアクセス制御をご参照ください。
//&ref(images/info.png,nolink);なお、mapred-queues.xml は、MapReduce v1でセットアップする場合に用い、2.0.3aよりmapred-queue-acls.xmlのテンプレートがなくなり、ACL設定も mapred-queues.xml に統合のポリシーのようです。
+ ${HADOOP_PREFIX}/etc/hadoop/''hadoop-policy.xml'': &ref(images/note.png,nolink);2.0.3aまで設定中の ''${HADOOP_YARN_USER}'' が正しく展開されませんでしたが、2.0.4aでは修正されています([[HADOOP-9444>https://issues.apache.org/jira/browse/HADOOP-9444]])ので、この設定ファイルの編集は必要ありません。

** セキュアDataNode [#x40aa10c]

- DataNodeをroot権限が必要な特権ポートでサービスするための設定です。DataNodeのなりすましを防止します。
+ Hadoopには、jsvc が同梱されていないため、パッケージインストールします。
 $ sudo apt-get install jsvc
++ &ref(images/note.png,nolink);ディストリビューションによっては jsvc のバージョンが古くうまく動作しない場合があります。そのようなときには別途ビルドしてインストールする必要があります。Hadoop 2.0 では、CLASSPATHの設定にワイルドカードを使用しており、古い jsvc ではそれがうまく解決されません(例えば、&ref(images/debian.png,nolink);Debian squeeze)。
+++ Commons Daemonのネイティブ用ソースをダウンロードし、以下の要領でビルドし、適当な場所に生成された jsvc を配備します。
#geshi{{
$ tar xvzf commons-daemon-1.0.13-native-src.tar.gz
$ cd commons-daemon-1.0.13-native-src/unix
$ sh support/buildconf.sh
support/buildconf.sh: configure script generated successfully
$ export JAVA_HOME=/usr/lib/jvm/java-6-sun
$ ./configure
...
$ make
...
$ sudo cp jsvc ${HADOOP_PREFIX}/sbin/
}}
+++ 同じバージョンのCommons Daemonライブラリをダウンロードし、こちらも適当な場所に配備します。
 $ sudo tar xvzf commons-daemon-1.0.13-bin.tar.gz -C /grid/usr
+ ${HADOOP_PREFIX}/etc/hadoop/''hadoop-env.sh'' にセキュアDataNodeの設定を追加します。jsvc が依存する Commons Daemonライブラリについては、(同梱されているものではなく)先程インストールしたものを最初に参照するようにCLASSPATHを設定します。''$JSVC_HOME'' については、jsvcコマンドが含まれるディレクトリを指定します。&ref(images/note.png,nolink);バグでしょうか、''$HADOOP_SECURE_DN_(PID|LOG)_DIR'' より ''$HADOOP_(PID|LOG)_DIR'' の設定が優先されてしまいますので、とりあえずログディレクトリのみ hdfs/ ディレクトリ以下に出力されるようにしています。
#geshi(bash,number){{
...
# Where log files are stored. $HADOOP_PREFIX/logs by default.
#export HADOOP_LOG_DIR=/grid/vol/0/var/log/${USER}
if [ x"$USER" = x'root' ]; then
    export HADOOP_LOG_DIR=/grid/vol/0/var/log/hdfs
else
    export HADOOP_LOG_DIR=/grid/vol/0/var/log/${USER}
fi

export HADOOP_SECURE_DN_USER=hdfs
# This property is N/A or overridden by the HADOOP_PID_DIR
#export HADOOP_SECURE_DN_PID_DIR=/grid/vol/0/var/run/${HADOOP_SECURE_DN_USER}
# This property is N/A or overridden by the HADOOP_LOG_DIR
#export HADOOP_SECURE_DN_LOG_DIR=/grid/vol/0/var/log/${HADOOP_SECURE_DN_USER}
export JSVC_HOME=/usr/bin
#export JSVC_HOME=/grid/usr/hadoop/sbin
# Extra Java CLASSPATH elements.  Optional.
if [ x"$HADOOP_CLASSPATH" = x ]; then
    export HADOOP_CLASSPATH=/usr/share/java/commons-daemon.jar
    #export HADOOP_CLASSPATH=${HADOOP_CLASSPATH}:/grid/usr/commons-daemon-1.0.13/commons-daemon-1.0.13.jar
else
    # for Hive and HCatalog
    export HADOOP_CLASSPATH=${HADOOP_CLASSPATH}:/usr/share/java/commons-daemon.jar
    #export HADOOP_CLASSPATH=${HADOOP_CLASSPATH}:/grid/usr/commons-daemon-1.0.13/commons-daemon-1.0.13.jar
fi
export HADOOP_USER_CLASSPATH_FIRST=true
}}
-- 参考までに同梱されている Commons Daemon は以下の通り。
 $ ls share/hadoop/hdfs/lib/ | grep commons-daemon
 commons-daemon-1.0.3.jar
+ ${HADOOP_PREFIX}/etc/hadoop/''hdfs-site.xml''
#geshi(xml,number){{
    <property>
        <name>dfs.datanode.address</name>
        <value>0.0.0.0:1004</value>
    </property>
    <property>
        <name>dfs.datanode.http.address</name>
        <value>0.0.0.0:1006</value>
    </property>
}}
+ hdfsユーザではなく、&color(red){''root''};でDataNodeを起動させます。起動後、デーモンのオーナはhdfsにスイッチされます。
 $ sudo sbin/hadoop-daemon.sh start datanode

** ユーザ権限でのリソースコンテナ起動(&ref(images/tux.png,nolink);LinuxContainerExecutor) [#j510fc38]

+ ソースパッケージをダウンロードし、環境に合わせて LinuxContainerExecutor をビルドし配備します(&ref(images/info.png,nolink);ビルド環境の構築については、[[Hadoopのビルド]]をご参照ください。)。ちなみに、バイナリパッケージに同梱されているのは前バージョンと異なり''i386''版の実行ファイルですので、''x86_64''環境の場合にはソースからのビルドが必須となります。
++ ビルドに必要なMavenの3.x系とProtocolBuffersをあらかじめインストールしてからビルドします。&ref(images/note.png,nolink);ver. 2.0.2aから追加で cmake が必要となっています。
#geshi{{
[for Debian] $ sudo apt-get install ant build-essential autoconf libtool cmake
[for CentOS] $ sudo yum install ant autoconf automake libtool cmake
[for CentOS] $ sudo yum install     ant gcc-c++ make autoconf automake libtool cmake
...
$ file ${HADOOP_PREFIX}/bin/container-executor
/grid/usr/hadoop/bin/container-executor: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked
 (uses shared libs), for GNU/Linux 2.6.18, BuildID[sha1]=0xe465062277e9ed1eba85c6a256ffb9aafa5a0cd4, not stripped
$ file ${HADOOP_PREFIX}/bin/test-container-executor
/grid/usr/hadoop/bin/test-container-executor: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically
 linked (uses shared libs), for GNU/Linux 2.6.18, BuildID[sha1]=0x9cb6fa7a86a4015032742f3259a1bcf8b55472f1, not stripped
...
$ tar xvzf hadoop-2.0.4-alpha-src.tar.gz
$ cd hadoop-2.0.4-alpha-src/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/
$ mvn package -Dcontainer-executor.conf.dir=/grid/usr/hadoop/etc/hadoop -DskipTests -Pnative
...
$ file target/native/target/usr/local/bin/container-executor
target/native/target/usr/local/bin/container-executor: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
 dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xf294655498d16daf403f727f118eb02a2a6a1aeb,
 not stripped
$ file target/native/target/usr/local/bin/test-container-executor
target/native/target/usr/local/bin/test-container-executor: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
 dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xc13287f59fb04d57e7a725774f89b291542bee77,
 not stripped
}}
++ 生成された実行ファイルを適切な場所にコピーし、NodeManagerの起動ユーザのみが所属するグループ(yarn)についてsetgid属性を付与します。
#geshi{{
$ sudo mv ${HADOOP_PREFIX}/bin/container-executor      ${HADOOP_PREFIX}/bin/container-executor.dist
$ sudo mv ${HADOOP_PREFIX}/bin/test-container-executor ${HADOOP_PREFIX}/bin/test-container-executor.dist
$ sudo cp target/native/target/usr/local/bin/*container-executor ${HADOOP_PREFIX}/bin/
$ cd ${HADOOP_PREFIX}
$ sudo chown root:yarn bin/*container-executor
$ sudo chmod 6050      bin/*container-executor
}}
+ LinuxContainerExecutor の設定ファイル(${HADOOP_PREFIX}/etc/hadoop/''container-executor.cfg'')を ${HADOOP_PREFIX}/etc/hadoop/''mapred-site.xml'' と同様に編集し、適切なパーミッション(rootの読取専用)を設定します。''yarn.nodemanager.(local|log)-dirs'' の設定はすでに不要のようです。
#geshi(bash,number){{
#yarn.nodemanager.local-dirs=/grid/vol/0/var/lib/yarn/nm/local
#yarn.nodemanager.log-dirs=/grid/vol/0/var/log/yarn/nm
yarn.nodemanager.linux-container-executor.group=yarn
#comma separated list of users who can not run applications
banned.users=hfds,yarn,mapred,bin
#Prevent other super-users
#min.user.id=1000    # default
}}
 $ sudo chown root:root etc/hadoop/container-executor.cfg 
 $ sudo chmod 0400      etc/hadoop/container-executor.cfg
++ &ref(images/centos.png,nolink);CentOSでは一般ユーザのuidは通常''500''から振られるため、container-executor.cfgの''min.user.id'' の設定を500に引き下げることをお忘れなく。
#geshi(bash,number){{
#min.user.id=1000    # default
min.user.id=500    # for CentOS
}}
+ ${HADOOP_PREFIX}/etc/hadoop/''yarn-site.xml'' の設定で、DefaultContainerExecutor に替えて、LinuxContainerExecutor を有効にします。(2.0.3aから追加された)リソース管理に [[cgroup]](Control Group) を利用する場合には、以下のようにリソースハンドラに ''CgroupsLCEResourcesHandler'' を設定し、必要に応じて関連するパラメータを調整します。&ref(images/info.png,nolink);なお、cgroup は、''kernel-2.6.24''以降(&ref(images/debian.png,nolink);Debian squeeze、&ref(images/centos.png,nolink);CentOS 6)で利用可能ですのでご注意ください。
#geshi(xml,number){{
    <property>
        <name>yarn.nodemanager.container-executor.class</name>
        <value>org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor</value>
    </property>
    <property>
        <name>yarn.nodemanager.linux-container-executor.group</name>
        <value>yarn</value>
    </property>
    <property>
        <name>yarn.nodemanager.linux-container-executor.resources-handler.class</name>
        <!-- 
        <value>org.apache.hadoop.yarn.server.nodemanager.util.DefaultLCEResourcesHandler</value>
         -->
        <value>org.apache.hadoop.yarn.server.nodemanager.util.CgroupsLCEResourcesHandler</value>
        <description>The class which should help the LCE handle resources.</description>
    </property>
    <!--
    <property>
        <name>yarn.nodemanager.linux-container-executor.cgroups.hierarchy</name>
        <value>/hadoop-yarn</value>
        <description>The cgroups hierarchy under which to place YARN proccesses (cannot contain commas).
        If yarn.nodemanager.linux-container-executor.cgroups.mount is false (that is, if cgroups have
        been pre-configured), then this cgroups hierarchy must already exist and be writable by the
        NodeManager user, otherwise the NodeManager may fail.
        Only used when the LCE resources handler is set to the CgroupsLCEResourcesHandler.</description>
    </property>
    <property>
        <name>yarn.nodemanager.linux-container-executor.cgroups.mount</name>
        <value>false</value>
        <description>Whether the LCE should attempt to mount cgroups if not found.
        Only used when the LCE resources handler is set to the CgroupsLCEResourcesHandler.</description>
    </property>
    <property>
        <name>yarn.nodemanager.linux-container-executor.cgroups.mount-path</name>
        <description>Where the LCE should attempt to mount cgroups if not found. Common locations
        include /sys/fs/cgroup and /cgroup; the default location can vary depending on the Linux
        distribution in use. This path must exist before the NodeManager is launched.
        Only used when the LCE resources handler is set to the CgroupsLCEResourcesHandler, and
        yarn.nodemanager.linux-container-executor.cgroups.mount is true.</description>
    </property>
    -->
}}
++ [[cgroup]]仮想ファイルシステムは設定によりYARNから動的にマウントさせることも可能ですが、それぞれのLinuxディストリビューションにあわせた方法で、あらかじめマウントし必要なリソース管理グループ(ディレクトリ)をセットアップしておくと間違いないでしょう。実装途上だとは思いますが、2.0.3a以降で利用するのはcpuサブシステムのみのようです。
+++ 以下は Ubuntu 12.10の例(マウントポイントは、/sys/fs/cgroup)ですが、相当するシェルコマンドで示しています。
 $ sudo mkdir /sys/fs/cgroup/cpu/hadoop-yarn
 $ sudo chown -R yarn:yarn /sys/fs/cgroup/cpu/hadoop-yarn
+++ Debian や CentOS であれば、cgconfig サービスを利用して、/etc/cgconfig.conf に以下のような設定を追加するとよいでしょう。
#geshi(bash,number){{
group hadoop-yarn {
    perm {
        task {
            uid = yarn;
            gid = yarn;
        }
        admin {
            uid = yarn;
            gid = yarn;
        }
    }
    cpu {
    }
}
}}
+++ なお、ジョブ実行時には、以下の通りHadoopのリソースコンテナ毎にcgroupのリソース管理グループが作成されます。
#geshi{{ 
$ ls -l /sys/fs/cgroup/cpu/hadoop-yarn/
total 0
-rw-r--r-- 1 yarn yarn 0 Feb 19 19:25 cgroup.clone_children
--w--w--w- 1 yarn yarn 0 Feb 19 19:25 cgroup.event_control
-rw-r--r-- 1 yarn yarn 0 Feb 19 19:25 cgroup.procs
drwxr-xr-x 2 yarn yarn 0 Feb 19 19:38 container_1361240603056_0004_01_000001
drwxr-xr-x 2 yarn yarn 0 Feb 19 19:38 container_1361240603056_0004_01_000002
drwxr-xr-x 2 yarn yarn 0 Feb 19 19:38 container_1361240603056_0004_01_000003
drwxr-xr-x 2 yarn yarn 0 Feb 19 19:38 container_1361240603056_0004_01_000004
drwxr-xr-x 2 yarn yarn 0 Feb 19 19:38 container_1361240603056_0004_01_000005
drwxr-xr-x 2 yarn yarn 0 Feb 19 19:38 container_1361240603056_0004_01_000006
-rw-r--r-- 1 yarn yarn 0 Feb 19 19:25 cpu.cfs_period_us
-rw-r--r-- 1 yarn yarn 0 Feb 19 19:25 cpu.cfs_quota_us
-rw-r--r-- 1 yarn yarn 0 Feb 19 19:25 cpu.rt_period_us
-rw-r--r-- 1 yarn yarn 0 Feb 19 19:25 cpu.rt_runtime_us
-rw-r--r-- 1 yarn yarn 0 Feb 19 19:25 cpu.shares
-r--r--r-- 1 yarn yarn 0 Feb 19 19:25 cpu.stat
-rw-r--r-- 1 yarn yarn 0 Feb 19 19:25 notify_on_release
-rw-r--r-- 1 yarn yarn 0 Feb 19 19:25 tasks
}}
-- &ref(images/note.png,nolink);はじめに ''Default''ContainerExecutor を利用していた場合には、切り替え後に以下のようなパーミッションエラーが発生します。一度ユーザキャッシュディレクトリを削除する必要があります。
#geshi(text,number){{
13/05/24 20:32:11 INFO mapreduce.Job: Job job_1369394783756_0001 failed with state FAILED due to: Application
 application_1369394783756_0001 failed 1 times due to AM Container for appattempt_1369394783756_0001_000001 exited with
  exitCode: -1000 due to: java.io.IOException: App initialization failed (255) with output: main : command provided 0
main : user is alice
Can't open appcache in /grid/vol/0/var/lib/yarn/nm/local/usercache/alice/appcache/application_1369394783756_0001 -
 Permission denied
Did not create any app directories

	at org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor.startLocalizer(LinuxContainerExecutor.java:191)
	at org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.ResourceLocalizationService$LocalizerRunner
.run(ResourceLocalizationService.java:859)
Caused by: org.apache.hadoop.util.Shell$ExitCodeException: 
	at org.apache.hadoop.util.Shell.runCommand(Shell.java:202)
	at org.apache.hadoop.util.Shell.run(Shell.java:129)
	at org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:322)
	at org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor.startLocalizer(LinuxContainerExecutor.java:183)
	... 1 more

.Failing this attempt.. Failing the application.
}}
#geshi{{
$ sudo rm -R /grid/vol/0/var/lib/yarn/nm/local/usercache
# YARN を再起動します。
}}

** CapacitySchedulerのアクセス制御 [#m52d42c0]

+ ${HADOOP_PREFIX}/etc/hadoop/''capacity-scheduler.xml'': CapacitySchedulerの設定を適切に行います。CapacitySchedulerには、新たにキューの階層化機能が追加されましたが、アクセス制御に関して言えば、親キューの権限が子のキューに継承される仕様の上、rootキューのデフォルト設定は全権付与(''*'')となっていますので、権限設定には十分注意する必要があります(上位階層で緩和した権限を下位のキューで制限することはできません)。通常、rootキューの権限設定を最小限に絞った上で、子のキューの権限を適切に緩和する必要があります。設定値のフォーマットは、カンマ区切りの許可ユーザリストと許可グループリストをさらに半角スペースで区切ります。''半角スペース一つのみ''は、ユーザリスト、グループリスト何れも設定しないという意味で、どのユーザにもその権限を許可しないことを表します。
#geshi(xml,number){{
  <property>
    <name>yarn.scheduler.capacity.root.acl_submit_applications</name>
    <value> </value>
    <description>
      The ACL of who can submit jobs to the root queue.
    </description>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.acl_administer_queue</name>
    <value> hadoop,gridops</value>
    <description>
      The ACL of who can administer jobs on the root queue.
    </description>
  </property>
  <!-- (...) -->
  <property>
    <name>yarn.scheduler.capacity.root.default.acl_submit_applications</name>
    <value>*</value>
    <description>
      The ACL of who can submit jobs to the default queue.
    </description>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.default.acl_administer_queue</name>
    <value> hadoop,gridops</value>
    <description>
      The ACL of who can administer jobs on the default queue.
    </description>
  </property>
}}
+ デーモンがすでに起動済であれば、以下のコマンドで設定内容を反映させることができます。
 $ sudo -u yarn ${HADOOP_PREFIX}/bin/yarn rmadmin -refreshQueues
+ 各ユーザは、以下のコマンドで自分に付与されている権限を確認することができます。
#geshi{{
$ sudo -u yarn ${HADOOP_PREFIX}/bin/mapred queue -showacls
...
Queue acls for user :  yarn

Queue  Operations
=====================
root  ADMINISTER_QUEUE
default  ADMINISTER_QUEUE,SUBMIT_APPLICATIONS
}}
#geshi(){{
$ sudo -u alice ${HADOOP_PREFIX}/bin/mapred queue -showacls
...
Queue acls for user :  alice

Queue  Operations
=====================
root  
default  SUBMIT_APPLICATIONS
}}

** ProxyUser(Secure Impersonation)の設定 [#u3e66646]

- ProxyUserの許可設定については、それを必要とする[[Oozie]]や[[Hoop]]のセットアップドキュメントをご参照ください。

** WebコンソールのSPNEGO/Kerberos設定 [#dfb9e34c]

- 各HadoopサービスのWebコンソールにもKerberos認証によるシングルサインオンでアクセスするため、SPNEGO/Kerberosの設定を行います。

+ まず署名のためのシークレットファイルを用意し、パーミッションを適切に設定します。完全分散の場合には、各ノードに同じシークレットファイルを配備します。
 $ sudo chmod 640 /grid/etc/hadoop-http-auth-signature-secret 
 $ sudo chown root:hadoop /grid/etc/hadoop-http-auth-signature-secret
+ ${HADOOP_PREFIX}/etc/hadoop/''core-site.xml'' を編集します。''hadoop.http.filter.initializers'' プロパティに ''org.apache.hadoop.security.AuthenticationFilterInitializer'' を設定し、''hadoop.http.authentication.type'' を ''kerberos'' にします。&ref(images/note.png,nolink);ただし、同一ノードで複数のデーモンを起動させる疑似分散環境では、dfs.web.authentication.kerberos.principal 等の値が同一となるため、Web UI等へのリクエストがリプレイ攻撃(([[Step 4: Create and Deploy the Kerberos Principals and Keytab Files>https://ccp.cloudera.com/display/CDHDOC/Configuring+Hadoop+Security+in+CDH3+(SPNEGO)#ConfiguringHadoopSecurityinCDH3%28SPNEGO%29-CreateandDeploytheKerberosPrincipalsandKeytabFiles]]))と判断されてしまいます。そのような場合には、やむを得ませんので hadoop.http.authentication.type を ''simple'' に設定して動作確認するとよいでしょう。
#geshi(xml,number){{
    <property>
        <name>hadoop.http.filter.initializers</name>
        <value>org.apache.hadoop.security.AuthenticationFilterInitializer</value>
        <!-- <value>org.apache.hadoop.http.lib.StaticUserWebFilter</value> -->
        <description>The name of a class that initializes an input filter for Jetty.
            This filter will always return Dr.Who as the web user when the servlets
            query for the authenticated user </description>
    </property>
    <property>
        <name>hadoop.http.authentication.signature.secret.file</name>
        <value>/grid/etc/hadoop-http-auth-signature-secret</value>
    </property>
    <property>
        <name>hadoop.http.authentication.cookie.domain</name>
        <value>${this.domain}</value>
    </property>
    <property>
        <name>hadoop.http.authentication.type</name>
        <value>kerberos</value>
        <description>Defines authentication used for the HTTP web-consoles.
            The supported values are: simple | kerberos | #AUTHENTICATION_HANDLER_CLASSNAME#.
            The dfeault value is simple.</description>
    </property>
    <property>
        <name>hadoop.http.authentication.kerberos.principal</name>
        <value>HTTP/localhost@${this.realm}</value>
        <!-- <value>HTTP/_HOST@${this.realm}</value>
            _HOST N/A!: v1.0, v1.1, HDP1.2; OK: v2.0, CDH3, CDH4 -->
    </property>
    <property>
        <name>hadoop.http.authentication.kerberos.keytab</name>
        <value>${this.keytab.dir}/HTTP.keytab</value>
    </property>
}}
+ ${HADOOP_PREFIX}/etc/hadoop/''hdfs-site.xml'': HDFSのWebコンソールで使用するプリンシパルを設定します。
#geshi(xml,number){{
    <property>
        <name>dfs.namenode.http-address</name>
        <value>${this.namenode.fqdn}:50070</value>
    </property>
    <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>${this.secondary.namenode.fqdn}:50090</value>
    </property>
    <property>
        <name>dfs.web.authentication.kerberos.principal</name>
        <value>HTTP/_HOST@${this.realm}</value>
    </property>
    <property>
        <name>dfs.web.authentication.kerberos.keytab</name>
        <value>${this.keytab.dir}/HTTP.keytab</value>
    </property>
}}
+ 編集後、各デーモンプロセスを再起動し反映させます。
+ ブラウザからのアクセス方法については、[[SPNEGOonBrowser]]をご参照ください。

** その他のサービス [#id325304]

+ [[HttpFS>HttpFS2.0aセットアップ]]
+ [[WebHDFS>WebHDFS2.0aセットアップ]]

* テスト [#zff94ffa]

+ ACL設定を追加して実行します。
#geshi(){{
$ sudo -u alice kinit
Password for alice@LOCALDOMAIN: 
$ sudo -u alice bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.0.4-alpha.jar pi \
> -D mapreduce.job.acl-view-job=* -D mapreduce.job.acl-modify-job=alice 5 10
}}

* 参考リソース [#pc5d773f]

+ [[設定ファイル一式>metasearchSvn:/hadoop_conf/tags/localhost-2.0/]]
+ [[Hadoop MapReduce Next Generation - Cluster Setup>http://hadoop.apache.org/docs/r2.0.4-alpha/hadoop-project-dist/hadoop-common/ClusterSetup.html]]
+ [[CDH4 Security Guide>https://ccp.cloudera.com/display/CDH4DOC/CDH4+Security+Guide]]


トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS