DockerでHadoop


## 課題

- [Docker](https://www.docker.com/) 上で [Hadoop](http://hadoop.apache.org/) を構築する。

## 手法

- [SequenceIQ](http://sequenceiq.com/) の提供する [Apache Hadoop Docker image](https://hub.docker.com/r/sequenceiq/hadoop-docker/) を活用する。

## 前提

|対象|バージョン|
|:--|:--|
|Apache Hadoop Docker image|2.7.1|

|環境|バージョン|
|:--|:--|
|[Boot2docker](http://boot2docker.io/)|1.10.3|
|[Docker Toolbox](https://www.docker.com/products/docker-toolbox) |1.10.3|
|[VartualBox](https://www.virtualbox.org/)|5.0|
|[Cygwin](https://www.cygwin.com/)|2.4.1|
|Windows|8.1|

## 内容

### 1. マスタノード（ResourceManager+NameNode）を構築

- マスタノード用の Apache Hadoop Docker image を起動する。

```bash
$ docker run -itd -p 8088:8088 -p 9000:9000 -p 19888:19888 -p 50070:50070 -h hadoop-00 --name hadoop-00 sequenceiq/hadoop-docker /bin/bash
$ docker exec hadoop-00 service sshd start
```

- マスタノードの Hadoop 設定を編集する。

```diff:/usr/local/hadoop/etc/hadoop/core-site.xml
--- a/core-site.xml
+++ b/core-site.xml
@@ -1,6 +1,6 @@
   <configuration>
       <property>
           <name>fs.defaultFS</name>
-          <value>hdfs://localhost:9000</value>
+          <value>hdfs://hadoop-00:9000</value>
       </property>
   </configuration>
```

```diff:/usr/local/hadoop/etc/hadoop/yarn-site.xml
--- a/yarn-site.xml
+++ b/yarn-site.xml
@@ -29,4 +29,16 @@
     <value>600</value>
   </property>

+  <property>
+    <name>yarn.resourcemanager.address</name>
+    <value>hadoop-00:8032</value>
+  </property>
+  <property>
+    <name>yarn.resourcemanager.resource-tracker.address</name>
+    <value>hadoop-00:8031</value>
+  </property>
+  <property>
+    <name>yarn.resourcemanager.scheduler.address</name>
+    <value>hadoop-00:8030</value>
+  </property>
 </configuration>
```

```diff:/usr/local/hadoop/etc/hadoop/hdfs-site.xml
--- a/hdfs-site.xml
+++ b/hdfs-site.xml
@@ -3,4 +3,8 @@
         <name>dfs.replication</name>
         <value>1</value>
     </property>
+    <property>
+      <name>dfs.namenode.datanode.registration.ip-hostname-check</name>
+      <value>false</value>
+    </property>
 </configuration>
```

```diff:/usr/local/hadoop/etc/hadoop/mapred-site.xml
--- a/mapred-site.xml
+++ b/mapred-site.xml
@@ -3,4 +3,8 @@
         <name>mapreduce.framework.name</name>
         <value>yarn</value>
     </property>
+    <property>
+        <name>mapreduce.jobhistory.address</name>
+        <value>hadoop-00:10020</value>
+    </property>
 </configuration>
```

```diff:/usr/local/hadoop/etc/hadoop/slaves
--- a/slaves
+++ b/slaves
@@ -1 +0,0 @@
-localhost
```

- マスタノードの HDFS データを削除する。

```bash
$ docker exec hadoop-00 rm -rf /tmp/hadoop-root/dfs/data/current
```

- マスターノードのデーモンを起動する。

```bash
$ docker exec hadoop-00 /usr/local/hadoop/sbin/yarn-daemon.sh start resourcemanager
$ docker exec hadoop-00 /usr/local/hadoop/sbin/hadoop-daemon.sh start namenode
$ docker exec hadoop-00 sh -c "USER=root /usr/local/hadoop/sbin/mr-jobhistory-daemon.sh start historyserver"
```

### 2. スレーブノード（NodeManager+DataNode）を構築

- スレーブノード用の Apache Hadoop Docker image を起動する。

```bash
$ docker run -itd -p 50010:50010 -h hadoop-01 --name hadoop-01 sequenceiq/hadoop-docker /bin/bash
$ docker exec hadoop-01 service sshd start
```

- マスタノードの  `/etc/hosts` にスレーブノードを追加する。

```bash
$ docker exec hadoop-00 sh -c "echo $(docker inspect --format {{.NetworkSettings.IPAddress}} hadoop-01) hadoop-01 >> /etc/hosts"
```

- マスタノードの `/usr/local/hadoop/etc/hadoop/slaves` にスレーブノードを追加する。

```bash
$ docker exec hadoop-00 sh -c "echo hadoop-01 >> /usr/local/hadoop/etc/hadoop/slaves"
```

- スレーブノードの  `/etc/hosts` をマスタノードと同期する。

```bash
$ docker exec hadoop-00 scp /etc/hosts hadoop-01:/etc/hosts
```

- スレーブノードの Hadoop 設定をマスタノードと同期する。

```bash
$ docker exec hadoop-00 rsync -av /usr/local/hadoop/etc/hadoop/ hadoop-01:/usr/local/hadoop/etc/hadoop/
```

- スレーブノードのデーモンを起動する。

```bash
$ docker exec hadoop-01 /usr/local/hadoop/sbin/yarn-daemon.sh start nodemanager
$ docker exec hadoop-01 /usr/local/hadoop/sbin/hadoop-daemon.sh start datanode
```

### 3. クライアントを構築

- クライアント用の Apache Hadoop Docker image を起動する。

```bash
$ docker run -itd -h hadoop-cli --name hadoop-cli sequenceiq/hadoop-docker /bin/bash
```

- クライアントの `/etc/hosts` にマスタノードを追加する。

```bash
$ docker exec hadoop-cli sh -c "echo $(docker inspect --format {{.NetworkSettings.IPAddress}} hadoop-00) hadoop-00 >> /etc/hosts"
```

- クライアントのHadoopの設定をマスタノードと同期する。

```bash
$ docker exec hadoop-cli rsync -av hadoop-00:/usr/local/hadoop/etc/hadoop/ /usr/local/hadoop/etc/hadoop/
```

### 4. 動作確認

- Hadoop のサンプルを実行する。

```bash
$ docker exec hadoop-cli /usr/local/hadoop/bin/hdfs dfs -rm -r output
$ docker exec hadoop-cli /usr/local/hadoop/bin/hadoop jar /usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.0.jar grep input output 'dfs[a-z.]+'
```

- 実行結果

```bash
$ docker exec hadoop-cli /usr/local/hadoop/bin/hdfs dfs -cat output/*
6       dfs.audit.logger
4       dfs.class
3       dfs.server.namenode.
2       dfs.period
2       dfs.audit.log.maxfilesize
2       dfs.audit.log.maxbackupindex
1       dfsmetrics.log
1       dfsadmin
1       dfs.servers
1       dfs.replication
1       dfs.file
```

### A. スレーブノード（NodeManager+DataNode）を追加

- スレーブノード用の Apache Hadoop Docker image を起動する。

```bash
$ docker run -itd -h hadoop-02 --name hadoop-02 sequenceiq/hadoop-docker /bin/bash
$ docker exec hadoop-02 service sshd start
```

- マスタノードの  `/etc/hosts` にスレーブノードを追加する。

```bash
$ docker exec hadoop-00 sh -c "echo $(docker inspect --format {{.NetworkSettings.IPAddress}} hadoop-02) hadoop-02 >> /etc/hosts"
```

- マスタノードの `/usr/local/hadoop/etc/hadoop/slaves` にスレーブノードを追加する。

```bash
$ docker exec hadoop-00 sh -c "echo hadoop-02 >> /usr/local/hadoop/etc/hadoop/slaves"
```

- スレーブノードの  `/etc/hosts` をマスタノードと同期する。

```bash
$ docker exec hadoop-00 scp /etc/hosts hadoop-01:/etc/hosts
$ docker exec hadoop-00 scp /etc/hosts hadoop-02:/etc/hosts
```

- スレーブノードの Hadoop 設定をマスタノードと同期する。

```bash
$ docker exec hadoop-00 rsync -av /usr/local/hadoop/etc/hadoop/ hadoop-01:/usr/local/hadoop/etc/hadoop/
$ docker exec hadoop-00 rsync -av /usr/local/hadoop/etc/hadoop/ hadoop-02:/usr/local/hadoop/etc/hadoop/
```

- スレーブノードの HDFS データを削除する。

```bash
$ docker exec hadoop-02 rm -rf /tmp/hadoop-root/dfs/data/current
```

- スレーブノードのデーモンを起動する。

```bash
$ docker exec hadoop-02 /usr/local/hadoop/sbin/yarn-daemon.sh start nodemanager
$ docker exec hadoop-02 /usr/local/hadoop/sbin/hadoop-daemon.sh start datanode
```

## 参考
- [Apache Hadoop YARN](https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/YARN.html)
- [HDFS Architecture](https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html)
- [Hadoop Cluster Setup](https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/ClusterSetup.html)
- [Apache Hadoop 2.7.1 Docker image](https://github.com/sequenceiq/hadoop-docker)
- [Apache Yarn 2.7.1 cluster Docker image](https://github.com/lresende/docker-yarn-cluster)