HadoopWithSecurityセットアップ >
DEPRECATED!: このバージョンのHadoopは古いです。ご利用は非推奨です。 Hadoop1.0セットアップ をご参照ください。
目次 †
概要 †
このドキュメントは、認証バックエンドにKerberosを、認可バックエンドにLDAPを使用したセキュアHadoopクラスタを構築する手順を説明しています。
主な例示環境は、 Debian 6.0 (squeeze) amd64 (2.6.32-5-amd64)です。i386 (2.6.32-5-686)環境でも手順はほぼ同様で、異なるところは jsvc の扱いと task-controller のビルドについてのみです。
古いバージョン †
Hadoop0.20.2xxWithSecurityセットアップ(旧)
例示環境の詳細 †
サーバ構成 †
クラスタ名 pleiades ドメイン grid.example.com No. ホスト 役割 備考 ns0{0..1} NameService? (Kerberos、LDAP、場合によってはDNSを追加)クラスタのサイズにあわせて増設 nn0{0..2} nn00がマスタNameNode 、nn01がバックアップ、nn02がチェックポイントノード jt0{0..1} jt00がマスタJobTracker 、jt01がバックアップ dn0000{0..1} DataNode およびTaskTracker 必要に応じて増設
ディレクトリ構成 †
VIP †
ドメイン grid.example.com No. VIPのDNS 説明 備考 pleiades-nn マスタNameNode のVIPのため pleiades-cn チェックポイントノードのVIPのため pleiades-jt マスタJobTracker のVIPのため
Kerberosプリンシパル †
セットアップ手順 †
Java実行環境 †
NameService? を除く全ノードに Sun(現Oracle) JDK 6 をインストールします。
SunのJDKにおいてKerberos認証で強度の高いAES256暗号を利用するためは、強度が無制限のJCE管轄ポリシーファイル をインストールする必要があります。インストールにあたっては、Javaにおける高強度暗号の利用 をご参照ください。
Kerberos認証環境 †
Kerberos認証は、クラスタを構成するノード間およびクライアントとの認証に使用されます。
プリンシパルとOSユーザとのマッピングはHadoopの設定ファイルの定義にて行われますので、Kerberos認証がOSのユーザ認証として直接利用されることはありません。
時刻を正確に同期するため、全ノードにNTPデーモンをインストールします。通常、組織内のNTPサーバを参照するようにします。
プリンシパルのインスタンス部に指定されたホスト名が正しく逆引きできるようにDNSを設定します。必要ならば、DNSサーバの管理者に依頼してください。検証目的であれば、ローカルの /etc/hosts ファイルでも代用できます。
NameService? の、マスタノード(ns00)にKerberos Adminサーバを、各ノード(ns00、ns01)にはKDC (Key Distribution Center)を、そしてその他の各ノードには、Kerberosクライアントをセットアップします。
セットアップの詳細はこちら
クラスタの実行に必要なプリンシパルとテスト用のユーザプリンシパル(alice)を追加します。
各ノードで必要なプリンシパルをランダム暗号鍵を用いて追加します。
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 host/pleiades-nn.grid.example.com
...
kadmin.local: add_principal -randkey hdfs/pleiades-cn.grid.example.com
...
kadmin.local: add_principal -randkey host/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 mapred/pleiades-jt.grid.example.com
...
kadmin.local: add_principal -randkey mapred/dn00000.grid.example.com
...
kadmin.local: add_principal -randkey mapred/dn00001.grid.example.com
...
hdfsユーザは、NameNode デーモンの起動ユーザにしてスーパーユーザなので、HDFSの管理のためユーザプリンシパルを追加しておきます。
kadmin.local: addprinc hdfs
WARNING: no policy specified for hdfs@GRID.EXAMPLE.COM; defaulting to no policy
Enter password for principal "hdfs@GRID.EXAMPLE.COM":
Re-enter password for principal "hdfs@GRID.EXAMPLE.COM":
Principal "hdfs@GRID.EXAMPLE.COM" created.
同じくmapredユーザもMapReduce? ジョブの管理ユーザなので、管理用のユーザプリンシパルを追加しておきます。
kadmin.local: addprinc mapred
WARNING: no policy specified for mapred@GRID.EXAMPLE.COM; defaulting to no policy
Enter password for principal "mapred@GRID.EXAMPLE.COM":
Re-enter password for principal "mapred@GRID.EXAMPLE.COM":
Principal "mapred@GRID.EXAMPLE.COM" created.
aliceのユーザプリンシパルを追加します。
kadmin.local: addprinc alice
WARNING: no policy specified for alice@GRID.EXAMPLE.COM; defaulting to no policy
Enter password for principal "alice@GRID.EXAMPLE.COM":
Re-enter password for principal "alice@GRID.EXAMPLE.COM":
Principal "alice@GRID.EXAMPLE.COM" created.
各ノードに必要なkeytabファイルを作成し、配備します。DataNode /TaskTracker のkeytabファイルについては、設定の便宜のため配備後、ホスト名部分を削除した dn.keytab、tt.keytab にリネームします。
ns00:$ sudo mkdir -p /grid/etc/keytabs
ns00:$ 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-jt.keytab -glob */pleiades-jt.grid.example.com
...
kadmin.local: ktadd -k /grid/etc/keytabs/dn00000-dn.keytab -p hdfs/dn00000.grid.example.com
...
kadmin.local: ktadd -k /grid/etc/keytabs/dn00001-dn.keytab -p hdfs/dn00001.grid.example.com
...
kadmin.local: ktadd -k /grid/etc/keytabs/dn00000-tt.keytab -p mapred/dn00000.grid.example.com
...
kadmin.local: ktadd -k /grid/etc/keytabs/dn00001-tt.keytab -p mapred/dn00001.grid.example.com
keytabファイルの参照権限は、(LDAP認可環境セットアップ後に)各Hadoopデーモンプロセスの起動ユーザにのみ付与します。
nn:$ sudo chown hdfs:hdfs /grid/etc/keytabs/pleiades-nn.keytab
nn:$ sudo chmod 400 /grid/etc/keytabs/pleiades-nn.keytab
nn:$ sudo chown hdfs:hdfs /grid/etc/keytabs/pleiades-cn.keytab
nn:$ sudo chmod 400 /grid/etc/keytabs/pleiades-cn.keytab
jt:$ sudo chown mapred:mapred /grid/etc/keytabs/pleiades-jt.keytab
jt:$ sudo chmod 400 /grid/etc/keytabs/pleiades-jt.keytab
dn:$ sudo chown hdfs:hdfs /grid/etc/keytabs/dn.keytab
dn:$ sudo chmod 400 /grid/etc/keytabs/dn.keytab
dn:$ sudo chown mapred:mapred /grid/etc/keytabs/tt.keytab
dn:$ sudo chmod 400 /grid/etc/keytabs/tt.keytab
LDAP認可環境 †
HadoopWithSecurity では、ユーザとグループの認可をOSのそれに依存しています。
このセットアップ例では、nsswitchを利用してバックエンドのLDAPにそれらの認可処理を委譲し、一元管理します。
NameService? のマスタノード(ns00)にLDAPプロバイダを、バックアップノード(ns01)にはLDAPコンシューマを、そしてその他の各ノードには、NSS-LDAP と NSCDをセットアップします。
セットアップの詳細はこちら
Hadoop起動ユーザ追加のためのldifファイル(例: hadoop_users.ldif )を作成します。
起動ユーザを追加します。
ns00:$ ldapadd -cxWD cn=admin,dc=grid,dc=example,dc=com -f hadoop_users.ldif
Enter LDAP Password:
adding new entry "cn=hadoop,ou=groups,dc=grid,dc=example,dc=com"
adding new entry "uid=hadoop,ou=people,dc=grid,dc=example,dc=com"
adding new entry "cn=hdfs,ou=groups,dc=grid,dc=example,dc=com"
adding new entry "uid=hdfs,ou=people,dc=grid,dc=example,dc=com"
adding new entry "cn=mapred,ou=groups,dc=grid,dc=example,dc=com"
adding new entry "uid=mapred,ou=people,dc=grid,dc=example,dc=com"
テストユーザ追加のためのldifファイル(例: test_users.ldif )を作成します。
ユーザを追加します。
ns00:$ ldapadd -cxWD cn=admin,dc=grid,dc=example,dc=com -f test_users.ldif
Enter LDAP Password:
adding new entry "cn=alice,ou=groups,dc=grid,dc=example,dc=com"
adding new entry "uid=alice,ou=people,dc=grid,dc=example,dc=com"
分散監視環境 †
Ganglia
Nagios
rsyncのセットアップ †
Hadoopのバイナリと設定ファイルの配布のために、rsyncをセットアップします。nn00(バックアップにnn01) から各ノードに rsync できるようにします。
rsync 専用のrootのSSHキーペアを生成し、公開鍵を各ノードの authorized_keys に以下の制限オプションを付加して追加します。
from="nn00.grid.example.com,nn01.grid.example.com",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-dss ...
直接的なrsyncコマンドの実行は以下の通りですが、ノードの数だけ(さらにシンボリックリンクも)同期するのでスクリプト(例: hadoop_rsync.sh )にしておきます。
$ sudo rsync -v -a --delete -e "ssh -i /root/.ssh/id_dsa4rsync" /grid/usr/hadoop root@dn00000.grid.example.com:/grid/usr
$ sudo rsync -v -a --delete -e "ssh -i /root/.ssh/id_dsa4rsync" /grid/usr/hadoop-0.20.203.0 root@dn00000.grid.example.com:/grid/usr
VIPの付与 †
サービスするマスタノードのNICにVIPを追加します。
nn00:$ sudo ip addr add xxx.xxx.xxx.xxx/32 dev eth0 # マスタNameNodeのVIP
nn02:$ sudo ip addr add xxx.xxx.xxx.xxx/32 dev eth0 # CheckpointNodeのVIP
jt00:$ sudo ip addr add xxx.xxx.xxx.xxx/32 dev eth0 # マスタJobTrackerのVIP
最新の hadoop-0.20.205.0 をダウンロードし、nn00 の /grid/usr に展開します。
$ sudo tar -xvzf hadoop-0.20.205.0-bin.tar.gz -C /grid/usr
$ sudo ln -s /grid/usr/hadoop-0.20.205.0 /grid/usr/hadoop
データおよびログ格納用のディレクトリを作成します。これらのディレクトリに実際に読み書きするのは hadoop グループに属する hdfs または mapred ユーザなので適切にグループ権限を付与します。※通常、読み書きのパフォーマンスを向上させるため、(特にDataNode のサーバでは)データ格納用とログ出力用のディレクトリは異なるディスクにし、さらにデータ格納用のディレクトリは複数のディスクに分散させます。DataNode では、まずjsvcのログをrootユーザで、次いで通常のHadoopのログをhdfsユーザで出力する関係上、rootしか書き込めないようなログディレクトリが作成されてしまわないように、あらかじめ 0/log/hdfs/ ディレクトリを作成しておきます。
$ sudo mkdir -p /grid/vol/0/var/lib/hdfs
$ sudo mkdir -p /grid/vol/0/var/lib/mapred
$ sudo mkdir -p /grid/vol/0/var/log/hdfs
$ sudo mkdir -p /grid/vol/0/var/run
$ sudo mkdir -p /grid/vol/0/tmp
$ sudo chown -R root:hadoop /grid/vol/0
$ sudo chmod -R 775 /grid/vol/0
$ sudo chown -R hdfs:hdfs /grid/vol/0/var/lib/hdfs
$ sudo chmod -R 755 /grid/vol/0/var/lib/hdfs
$ sudo chown -R mapred:mapred /grid/vol/0/var/lib/mapred
$ sudo chmod -R 755 /grid/vol/0/var/lib/mapred
$ sudo chmod -R 1777 /grid/vol/0/tmp
Hadoopの各設定ファイルを編集します(設定例 )。
Hadoopネイティブライブラリのロードについてですが、lib/libhadoop.a の存在チェックによって lib/ 以下のオブジェクト(32bit)が優先的にロードされてしまいますので、64bit環境など問題がある場合には、lib/libhadoop.a をリネームし、適切なアーキテクチャのオブジェクト(lib/native/Linux-{amd64-64 ,i386-32 }/*)がロードされるようにします。
$ file lib/libhadoop.so
lib/libhadoop.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped
$ sudo mv lib/libhadoop.a lib/libhadoop.a.bak
このHadoopにはセキュアDataNode 起動用に32/64bit両版のjsvcが同梱されていますが、実行権限が付与されていないため、付与します。
$ sudo chmod 775 libexec/jsvc.*
Taskプロセス制御に LinuxTaskController? を使用しますので、環境にあわせた task-controller 実行ファイルをビルドします。
ビルドに必要なパッケージをインストールします。
$ sudo aptitude -R install ant autoconf automake libtool make
ソースパッケージをダウンロードし、task-controller をビルドし実行ファイルを配備します。
$ tar xvzf hadoop-0.20.205.0.tar.gz
$ cd hadoop-0.20.205.0/
$ ant task-controller -Dhadoop.conf.dir=/grid/usr/hadoop/conf
...
$ sudo mv /grid/usr/hadoop/bin/task-controller /grid/usr/hadoop/bin/task-controller.dist
$ sudo cp build/hadoop-0.20.205.1/bin/task-controller /grid/usr/hadoop/bin/
【参考: i386環境でのビルド】そのままでは次のエラーで失敗しますので、configure.ac の中の AC_SYS_LARGEFILE をコメントアウトしてからビルドする必要があります(MAPREDUCE-2178: ac-sys-largefile.patch )。
...
[exec] /usr/include/fts.h:41:3: error: #error "<fts.h> cannot be used with -D_FILE_OFFSET_BITS==64"
...
BUILD FAILED
/grid/usr/hadoop-0.20.203.0/build.xml:2303: exec returned: 2
$ cat src/c++/task-controller/configure.ac
...
AC_INIT(linux-task-controller, 1.0.0, mapreduce-dev@hadoop.apache.org)
AC_GNU_SOURCE
#AC_SYS_LARGEFILE
AM_INIT_AUTOMAKE([subdir-objects foreign no-dist])
...
task-controller 実行ファイルのパーミッションを適切に変更します。
$ cd /grid/usr/hadoop
$ sudo chown root:mapred bin/task-controller
$ sudo chmod 6050 bin/task-controller
次に設定ファイル conf/taskcontroller.cfg を環境にあわせて編集し、パーミションを適切に制限します。
mapred.local.dir=/ grid/ vol/ 0/ var/ lib/ mapred/ local
hadoop.log.dir=/ grid/ vol/ 0/ var/ log/ mapred
mapred.tasktracker.tasks.sleeptime-before-sigkill =5000
mapreduce.tasktracker.group=mapred
$ sudo chown root:root conf/taskcontroller.cfg
$ sudo chmod 0400 conf/taskcontroller.cfg
先のrsyncスクリプトを実行し、Hadoopのバイナリと設定ファイルを各ノードに配布します。
HDFS を初期化します。
nn00:$ sudo -u hdfs hadoop namenode -format
11/07/24 10:27:03 INFO namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG: host = nn00.grid.example.com/xxx.xxx.xxx.xxx
STARTUP_MSG: args = [-format]
STARTUP_MSG: version = 0.20.203.0
STARTUP_MSG: build = http://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20-security-203 -r 1099333;
compiled by 'oom' on Wed May 4 07:57:50 PDT 2011
************************************************************/
11/07/24 10:27:04 INFO util.GSet: VM type = 64-bit
11/07/24 10:27:04 INFO util.GSet: 2% max memory = 19.33375 MB
11/07/24 10:27:04 INFO util.GSet: capacity = 2^21 = 2097152 entries
11/07/24 10:27:04 INFO util.GSet: recommended=2097152, actual=2097152
11/07/24 10:27:04 INFO namenode.FSNamesystem: fsOwner=hdfs
11/07/24 10:27:04 INFO namenode.FSNamesystem: supergroup=hdfs
11/07/24 10:27:04 INFO namenode.FSNamesystem: isPermissionEnabled=true
11/07/24 10:27:04 INFO namenode.FSNamesystem: dfs.block.invalidate.limit=100
11/07/24 10:27:04 INFO namenode.FSNamesystem: isAccessTokenEnabled=true accessKeyUpdateInterval=600 min(s), accessTokenLifetime=600 min(s)
11/07/24 10:27:04 INFO namenode.NameNode: Caching file names occuring more than 10 times
11/07/24 10:27:04 INFO common.Storage: Image file of size 104 saved in 0 seconds.
11/07/24 10:27:05 INFO common.Storage: Storage directory /grid/vol/0/var/lib/hdfs/name has been successfully formatted.
11/07/24 10:27:05 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at nn00.grid.example.com/xxx.xxx.xxx.xxx
************************************************************/
各Hadoop HDFSデーモンを起動します。各デーモンは適切なユーザで起動する必要がありますので、起動ユーティリティスクリプト(例: hadoopctl )を用意しておくとよいでしょう。
hdfs ユーザでNameNode を起動させます。
nn00:$ sudo -u hdfs hadoop-daemon.sh start namenode
starting namenode, logging to /grid/vol/0/var/log/hdfs/hadoop-hdfs-namenode-nn00.out
hdfs ユーザでSecondaryNameNode を起動させます。
nn02:$ sudo -u hdfs hadoop-daemon.sh start secondarynamenode
starting secondarynamenode, logging to /grid/vol/0/var/log/hdfs/hadoop-hdfs-secondarynamenode-nn02.out
root ユーザでDataNode を起動させます。
dn00000:$ sudo hadoop-daemon.sh start datanode
starting datanode, logging to /grid/vol/0/var/log/hdfs/hadoop-hdfs-datanode-dn00000.out
各デーモンの起動状況は、jpsコマンドで確認できます。
dn00000:$ sudo jps -mv
1850 Jps -mv -Dapplication.home=/usr/lib/jvm/java-6-sun-1.6.0.26 -Xms8m
1688 -Dproc_datanode -Xmx1000m -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Stack=true
-Dsecurity.audit.logger=ERROR,DRFAS -Dhadoop.log.dir=/grid/vol/0/var/log/hdfs
-Dhadoop.log.file=hadoop-hdfs-datanode-dn00000.log -Dhadoop.home.dir=/grid/usr/hadoop/bin/..
-Dhadoop.id.str=hdfs -Dhadoop.root.logger=INFO,DRFA
-Djava.library.path=/grid/usr/hadoop/bin/../lib/native/Linux-amd64-64
-Dhadoop.policy.file=hadoop-policy.xml abort
HDFS上に必要なディレクトリを作成します。HDFSとMapReduce? ジョブの管理にはそれぞれ適切な管理ユーザでコマンドを実行する必要がありますので、コマンド実行ユーティリティスクリプト(例: hadoopadmin )を用意しておくとよいでしょう。
(はじめにhdfsユーザでkinitを実行してから)ホームディレクトリのルート(/user)を作成します。
$ sudo -u hdfs kinit
Password for hdfs@GRID.EXAMPLE.COM:
$ sudo -u hdfs kinit -R
$ sudo -u hdfs hadoop fs -chown hdfs:hdfs /
$ sudo -u hdfs hadoop fs -chmod 755 /
$ sudo -u hdfs hadoop fs -mkdir /user
$ sudo -u hdfs hadoop fs -chmod 755 /user
mapredユーザがMap/Reduce実行に必要なディレクトリを作成できるように以下のディレクトリを作成します。
$ sudo -u hdfs hadoop fs -mkdir /grid/vol/0/var/lib/mapred
$ sudo -u hdfs hadoop fs -chown mapred:mapred /grid/vol/0/var/lib/mapred
$ sudo -u hdfs hadoop fs -chmod 700 /grid/vol/0/var/lib/mapred
各Hadoop MapReduce? デーモンを起動します。
mapred ユーザでJobTracker を起動させます。JobTracker は、HDFS上に動作に必要なディレクトリを作成できない場合、起動に失敗しますのでご注意ください。
jt00:$ sudo -u mapred hadoop-daemon.sh stop jobtracker
starting jobtracker, logging to /grid/vol/0/var/log/mapred/hadoop-mapred-jobtracker-jt00.out
mapred ユーザでTaskTracker を起動させます。
dn00000:$ sudo -u mapred hadoop-daemon.sh start tasktracker
starting tasktracker, logging to /grid/vol/0/var/log/mapred/hadoop-mapred-tasktracker-dn00000.out
テストユーザのホームディレクトリを用意します。パーミッションはDebianのそれと同様で良いでしょう。
$ sudo -u hdfs hadoop fs -mkdir /user/alice
$ sudo -u hdfs hadoop fs -chown alice:alice /user/alice
$ sudo -u hdfs hadoop fs -chmod 755 /user/alice
サンプルジョブの実行
$ whoami
alice
$ kinit
Password for alice@GRID.EXAMPLE.COM:
$ kinit -R
$ cd /grid/usr/hadoop
$ ./bin/hadoop jar hadoop-examples-0.20.205.0.jar pi 5 10