以前、このブログでは OSS 版の Apache Hadoop を疑似分散モードでセットアップする方法を試した。 疑似分散モードというのは、一つのホスト上に必要なデーモンを全て立ち上げる方法を指す。 このモードを使うと HDFS が使えるような、なるべく本番に近い環境が手軽に作れる。
ただ、疑似分散モードでは本当にちゃんと動作するのかが確認しづらい箇所もある。 それは、主にホストを分割してネットワーク越しにやり取りをする部分で、例えばファイアウォールの設定など。
そこで、今回は Apache Hadoop を完全分散モードでセットアップしてみることにした。 完全分散モードというのは本番運用されるのと同じ環境で、それぞれのデーモンを異なるホストで動かすやり方。 完全分散モードのセットアップ方法については次のドキュメントを参照する。
構成について
今回は、なるべく少ないホストで作りたいので三台のホストを使ってセットアップする。 マスターノード一台とスレーブノード二台という構成になる。 それぞれのホストには、次のように IP アドレスを振った。
- マスターノード
- 192.168.33.10
- スレーブノード1
- 192.168.33.11
- スレーブノード2
- 192.168.33.12
ここからは、それぞれのホストでどういった機能が動作するかを説明する。 まずは、Apache Hadoop で動作させるサービス (デーモン) について説明しておく。
HDFS 関連
- NameNode
- どのノードに目当てのファイルがあるかといったメタデータを管理するサービス
- DataNode
- 細かく分割したファイルを実際に保持して必要に応じて操作できるようにするサービス
- Secondary NameNode
- メタデータなどの情報をメモリからディスクに永続化するためのサービス
- NameNode
YARN 関連
- ResourceManager
- 今どのノードで、どういったタスクが実行されているか管理するサービス
- NodeManager
- タスクを実行するためのサービス
- ResourceManager
MRv2 関連
- MapReduce Job History Server
- MapReduce ジョブの履歴を管理するサービス
- MapReduce Job History Server
上記のサービスを、それぞれ次のように割り当てる。
マスターノード
- NameNode
- ResourceManager
- Secondary NameNode
- MapReduce Job History Server
スレーブノード
- DataNode
- NodeManager
使った環境については次の通り。 疑似分散モードのときと同じように CentOS7 上に OSS 版の Apache Hadoop をセットアップする。
$ cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) $ uname -r 3.10.0-514.21.1.el7.x86_64
全ホスト共通
まずは全ホスト共通の作業から実施する。
hostname
ホスト名を設定しておく。 これはやらなくても大丈夫だけど、操作対象のホストを間違えないようにやっておいた方が良いかも。 それぞれのホストで実施する。
マスターノードには “master” というホスト名をつけておく。
master $ sudo hostname master master $ echo "master" | sudo tee /etc/hostname > /dev/null
一つ目のスレーブノードには “node1” というホスト名をつけておく。
node1 $ sudo hostname node1 node1 $ echo "node1" | sudo tee /etc/hostname > /dev/null
二つ目のスレーブノードには “node2” というホスト名をつけておく。
node2 $ sudo hostname node2 node2 $ echo "node2" | sudo tee /etc/hostname > /dev/null
/etc/hosts
次に /etc/hosts
ファイルを編集する。
これは IP アドレスの代わりにホスト名を使って設定ファイルを書きたいので。
$ cat << 'EOF' | sudo tee -a /etc/hosts > /dev/null 192.168.33.10 master 192.168.33.11 node1 192.168.33.12 node2 EOF
ちゃんと設定ファイルが書き換わったことを確認しておく。
$ tail -n 3 /etc/hosts 192.168.33.10 master 192.168.33.11 node1 192.168.33.12 node2
依存パッケージ
次に必要なパッケージをインストールする。
epel-release
と sshpass
はスレーブノードには必要ないんだけど、まあ入れておいても問題はない。
$ sudo yum -y install epel-release
$ sudo yum -y install openssh-clients rsync wget java-1.8.0-openjdk-devel sshpass
Hadoop
次に Apache Hadoop をダウンロードする。
$ wget http://ftp.riken.jp/net/apache/hadoop/common/hadoop-2.8.0/hadoop-2.8.0.tar.gz $ tar xf hadoop-2.8.0.tar.gz
シェルの設定ファイルに、いくつかの環境変数を指定しておこう。
$ cat << 'EOF' >> ~/.bashrc export JAVA_HOME=/usr/lib/jvm/jre-1.8.0-openjdk export HADOOP_HOME=~/hadoop-2.8.0 export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop export PATH=$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$JAVA_HOME/bin:$PATH EOF $ source ~/.bashrc
これで hadoop
コマンドが動作することを確認しておく。
$ hadoop version Hadoop 2.8.0 Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r 91f2b7a13d1e97be65db92ddabc627cc29ac0009 Compiled by jdu on 2017-03-17T04:12Z Compiled with protoc 2.5.0 From source with checksum 60125541c2b3e266cbf3becc5bda666 This command was run using /home/vagrant/hadoop-2.8.0/share/hadoop/common/hadoop-common-2.8.0.jar
マスターノード
ここからはマスターノードで作業をする。
SSH
Apache Hadoop のセットアップでは、マスターノードから各ホストに SSH でパスフレーズを使わずにログインできる必要がある。 そこで、まずはパスフレーズを空にした公開鍵ペアを用意しておく。
$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
作成した公開鍵を各ホストに設置する。 これでマスターノードから各ホストにログインできるようになる。
$ for node in master node1 node2; do sshpass -p "vagrant" ssh-copy-id -i ~/.ssh/id_rsa.pub -o "StrictHostKeyChecking no" $node; done;
設定ファイルを編集する
ここからは Apache Hadoop の動作に必要な設定ファイルを編集していく。
etc/hadoop/slaves
まずはスレーブノードがどのホストなのかを示す設定ファイルを編集する。
$ cat << 'EOF' > $HADOOP_HOME/etc/hadoop/slaves node1 node2 EOF
今回使うスレーブノードは node1
と node2
の二台になる。
$ cat $HADOOP_HOME/etc/hadoop/slaves
node1
node2
etc/hadoop/core-site.xml
次は HDFS の設定ファイルを編集する。 HDFS の接続エンドポイントがマスターノードであることを指定しておく。
$ cat << 'EOF' > /tmp/core-site.xml.property <property> <name>fs.defaultFS</name> <value>hdfs://192.168.33.10:9000</value> </property> EOF $ sed -i -e ' /^<configuration>$/r /tmp/core-site.xml.property /^$/d ' $HADOOP_HOME/etc/hadoop/core-site.xml
こんな感じになる。
$ tail -n 6 $HADOOP_HOME/etc/hadoop/core-site.xml <configuration> <property> <name>fs.defaultFS</name> <value>hdfs://192.168.33.10:9000</value> </property> </configuration>
etc/hadoop/hdfs-site.xml
同様に HDFS のレプリケーション数 (ファイルのコピーをいくつ作るか) やセカンダリネームノードのエンドポイントを指定していく。
$ cat << 'EOF' > /tmp/hdfs-site.xml.property <property> <name>dfs.replication</name> <value>2</value> </property> <property> <name>dfs.namenode.secondary.http-address</name> <value>192.168.33.10:50090</value> </property> EOF $ sed -i -e ' /^<configuration>$/r /tmp/hdfs-site.xml.property /^$/d ' $HADOOP_HOME/etc/hadoop/hdfs-site.xml
こんな感じになる。
$ tail -n 6 $HADOOP_HOME/etc/hadoop/hdfs-site.xml <configuration> <property> <name>dfs.replication</name> <value>2</value> </property> </configuration>
etc/hadoop/mapred-site.xml
次は分散処理フレームワークの YARN を設定していく。
分散処理フレームワークとして YARN を使うことを指定する。
$ cp $HADOOP_HOME/etc/hadoop/mapred-site.xml{.template,} $ cat << 'EOF' > /tmp/mapred-site.xml.property <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> EOF $ sed -i -e ' /^<configuration>$/r /tmp/mapred-site.xml.property /^$/d ' $HADOOP_HOME/etc/hadoop/mapred-site.xml
こんな感じになる。
$ tail -n 6 $HADOOP_HOME/etc/hadoop/mapred-site.xml <configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>
etc/hadoop/yarn-site.xml
同様に YARN が動作するための設定を行う。
$ cat << 'EOF' > /tmp/yarn-site.xml.property <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.resourcemanager.hostname</name> <value>master</value> </property> EOF $ sed -i -e ' /^<configuration>$/r /tmp/yarn-site.xml.property /^$/d ' $HADOOP_HOME/etc/hadoop/yarn-site.xml
こんあ感じになる。
$ tail -n 11 $HADOOP_HOME/etc/hadoop/yarn-site.xml <configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.resourcemanager.hostname</name> <value>master</value> </property> <!-- Site specific YARN configuration properties --> </configuration>
設定ファイルをスレーブノードにコピーする
マスターノードで作った設定ファイルをスレーブノードにも設置する。 ここは SCP を使って一気にバラまくことにした。
$ for node in node1 node2; do scp $HADOOP_HOME/etc/hadoop/* $node:$HADOOP_HOME/etc/hadoop/; done;
クラスタを構築する
ここまでで必要な設定ファイルは用意できた。 あとはクラスタを構築していくだけ。 以下の操作もマスターノードのみで実施する。
まずは HDFS をフォーマットする。
$ $HADOOP_HOME/bin/hdfs namenode -format
続いて HDFS 関連のデーモンを起動する。
$ $HADOOP_HOME/sbin/start-dfs.sh
マスターノードでは、次のようにネームノードとセカンダリネームノードのサービスが起動する。
$ jps 9062 Jps 8951 SecondaryNameNode 8473 NameNode
続いて YARN 関連のデーモンを起動する。
$ $HADOOP_HOME/sbin/start-yarn.sh
マスターノードでは、次のようにリソースマネージャのサービスが起動する。
$ jps 9648 Jps 8951 SecondaryNameNode 8473 NameNode 9165 ResourceManager
続いて MapReduce のジョブ履歴を管理するサービスを起動する。
$ $HADOOP_HOME/sbin/mr-jobhistory-daemon.sh --config $HADOOP_CONF_DIR start historyserver
マスターノードでは、次のようにジョブヒストリサーバが起動する。
$ jps 9648 Jps 8951 SecondaryNameNode 8473 NameNode 9610 JobHistoryServer 9165 ResourceManager
ここまで実行するとスレーブノードでもネームノードとデータノードのサービスが立ち上がっている。
$ jps 4560 NodeManager 5090 Jps 4456 DataNode
使ってみよう
これで Apache Hadoop のクラスタを完全分散モードで組むことができた。 実際に軽く使ってみることにしよう。
まずはサンプルに入っているプログラムを使って円周率を計算させてみる。
$ $HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.8.0.jar pi 10 10000 Number of Maps = 10 Samples per Map = 10000 Wrote input for Map #0 Wrote input for Map #1 Wrote input for Map #2 Wrote input for Map #3 Wrote input for Map #4 Wrote input for Map #5 Wrote input for Map #6 Wrote input for Map #7 Wrote input for Map #8 Wrote input for Map #9 Starting Job ...(snip)... Job Finished in 52.727 seconds Estimated value of Pi is 3.14120000000000000000
上手く実行できた。
次は、たくさんのファイルの中から特定の文言が何回出現するかを調べる grep
も動かしてみよう。
先ほどの円周率は単なる数値計算だったけど、こちらのプログラムは HDFS との連携も必要になる。
まずは検索対象のファイルを置くために HDFS のホームディレクトリを作っておく。
$ $HADOOP_HOME/bin/hdfs dfs -mkdir -p . $ $HADOOP_HOME/bin/hdfs dfs -ls -R /user drwxr-xr-x - vagrant supergroup 0 2017-06-05 19:58 /user/vagrant
grep
の検索対象は Apache Hadoop の設定ファイル群を使ってみよう。
設定ファイルの入ったディレクトリを input
という名前で HDFS にコピーする。
$ $HADOOP_HOME/bin/hdfs dfs -put $HADOOP_HOME/etc/hadoop input
こんな感じでコピーされるはず。
$ $HADOOP_HOME/bin/hdfs dfs -ls input Found 30 items -rw-r--r-- 2 vagrant supergroup 4942 2017-06-05 19:59 input/capacity-scheduler.xml -rw-r--r-- 2 vagrant supergroup 1335 2017-06-05 19:59 input/configuration.xsl -rw-r--r-- 2 vagrant supergroup 318 2017-06-05 19:59 input/container-executor.cfg ...(snip)... -rw-r--r-- 2 vagrant supergroup 2250 2017-06-05 19:59 input/yarn-env.cmd -rw-r--r-- 2 vagrant supergroup 4567 2017-06-05 19:59 input/yarn-env.sh -rw-r--r-- 2 vagrant supergroup 897 2017-06-05 19:59 input/yarn-site.xml
ちなみに、ファイルの実体はデータノードのサービスが動いているスレーブノードに分散して設置されている。
/tmp/hadoop-$(whoami)/dfs/data/current
サンプルにある grep
のプログラムを動かしてみよう。
設定ファイルの中から dfs
で始まる言葉を探している。
$ $HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.8.0.jar grep input output 'dfs[a-z.]+' 17/06/05 20:00:35 INFO client.RMProxy: Connecting to ResourceManager at master/192.168.33.10:8032 17/06/05 20:00:36 INFO input.FileInputFormat: Total input files to process : 30 17/06/05 20:00:36 INFO mapreduce.JobSubmitter: number of splits:30 17/06/05 20:00:37 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1496645818704_0002 17/06/05 20:00:37 INFO impl.YarnClientImpl: Submitted application application_1496645818704_0002 17/06/05 20:00:37 INFO mapreduce.Job: The url to track the job: http://master:8088/proxy/application_1496645818704_0002/ 17/06/05 20:00:37 INFO mapreduce.Job: Running job: job_1496645818704_0002 17/06/05 20:00:46 INFO mapreduce.Job: Job job_1496645818704_0002 running in uber mode : false 17/06/05 20:00:46 INFO mapreduce.Job: map 0% reduce 0% 17/06/05 20:01:14 INFO mapreduce.Job: map 13% reduce 0% 17/06/05 20:01:15 INFO mapreduce.Job: map 20% reduce 0% ...(snip)
実行が終わったら HDFS の output
ディレクトリに結果が出力される。
$ $HADOOP_HOME/bin/hdfs dfs -cat output/* 6 dfs.audit.logger 4 dfs.class 3 dfs.logger 3 dfs.server.namenode. 2 dfs.audit.log.maxbackupindex 2 dfs.period 2 dfs.audit.log.maxfilesize 1 dfs.log 1 dfs.file 1 dfs.servers 1 dfsadmin 1 dfsmetrics.log 1 dfs.replication
ばっちりだね。
Vagrantfile
上記を手作業で毎回やるのは大変なので Vagrantfile
を書いて自動化してみた。
Vagrantfile for Hadoop Cluster with CentOS 7 and Hadoop 2.8.0 (3 hosts) · GitHub
Vagrant と Git をインストールした Unix 系のシステムなら、次のようにして自動でクラスタを構築できる。 デフォルトで、それぞれのホストに 2GB のメモリを割り当てるので最低でも 8GB できれば 16GB 以上のメモリを積んだマシンで実行した方が良い。
$ git clone https://gist.github.com/0ff814ce4c3aa659723c6b5b0fc85557.git hadoop-cluster $ cd hadoop-cluster $ vagrant provision node1 node2 master
あとはそれぞれのホストに入って色々使ってみるだけ。
$ vagrant ssh master
いじょう。
まとめ
今回は Apache Hadoop のクラスタを完全分散モードで構築してみた。 完全分散モードであればマスターとスレーブがネットワークで分かれているので、よりプロダクション環境に近い状況で検証ができる。
Apache Hadoop については次の本がとても分かりやすい。
Hadoop徹底入門 第2版 オープンソース分散処理環境の構築
- 作者: 太田一樹,岩崎正剛,猿田浩輔,下垣徹,藤井達朗,山下真一,濱野賢一朗
- 出版社/メーカー: 翔泳社
- 発売日: 2013/07/09
- メディア: 大型本
- この商品を含むブログ (5件) を見る