docker-composeでnamenodeとdatanodeの簡易なyarnのhadoopクラスタを作成してみる

さくっと試したい方は、下記の3-6を試していただければと思います。

# 1. やりたいこと

yarn, mesos等いくつか構成パターンのあるhdfsのクラスタを作成したいが、動きや構成を追いかけるだけならdockerで簡単に出来たら嬉しいかな、と考えていました。

# 2. 参考にしたGitHubリポジトリ

下記のリポジトリをforkしました。

https://github.com/lresende/docker-yarn-cluster

上記のリポジトリは、[sequenceiq](https://github.com/sequenceiq)さんから下記のリポジトリをforkしていたので、forkのforkリポジトリになります。

https://github.com/sequenceiq/hadoop-docker

# 3. 実施手順

1. EC2インスタンスを構築（割愛）
2. docker-composeをインストール
3. forkしたリポジトリをclone
4. docker buildを実施してyarn-cluser用のイメージ作成
5. docker-compose.ymlを用意する。
6. コンテナを起動

## 3-2. docker-composeをインストール

最近[公式サイトでアナウンス](https://blog.docker.com/2015/11/docker-1-9-production-ready-swarm-multi-host-networking/)が有ったとおり、docker-composeが1.5にバージョンアップしました。
ので、1.5をインストールしました。

```bash
export VERSION=1.5.0

mkdir -p /opt/bin
curl -L https://github.com/docker/compose/releases/download/${VERSION}/docker-compose-`uname -s`-`uname -m` > /opt/bin/docker-compose
chmod +x /opt/bin/docker-compose
docker-compose -v
```

参考サイト
https://docs.docker.com/compose/install/

## 3-3. forkしたリポジトリをclone

```bash
git clone https://github.com/letusfly85/docker-yarn-cluster.git

cd docker-yarn-cluster
```

## 3-4. docker buildを実施してyarn-cluser用のイメージ作成

[Dockerfile](https://github.com/letusfly85/docker-yarn-cluster/blob/hadoop_2.7/Dockerfile)を編集して、hadoopのバージョン番号を編集し、docker buildを実施します。

備忘のため本投稿の末尾にもDockerfileを記載します。


```bash
sudo docker build  -t letusfly85/yarn-cluster .
```

このとき、Dockerfileの`yum install`が失敗します。
なんだこのエラー。。とぐぐってみたところ、下記がヒットしました。

[CoreOSのoverlayfsでyumエラー](http://qiita.com/skame/items/f1c755d66256b750b3e8)

なにこれ。。。と思いつつも、記載のある通り、`yum install ${packages...} | true`とすることでいったん回避しました。

また、buildが完了した後は、[docker.hub](https://hub.docker.com/)にログインして、imageをpushしました。

```bash
docker login

docker push letusfly85/yarn-cluster
```

## 3-5. docker-compose.ymlを用意して、コンテナを起動

docker-compose.ymlを下記のように実装しました。

```yaml
namenode:
  image: letusfly85/yarn-cluster
  container_name: namenode
  hostname: namenode
  ports:
    - "8088:8088"
    - "50090:50090"
  command: "/etc/bootstrap.sh -d -namenode"
datanode:
  image: letusfly85/yarn-cluster
  container_name: datanode
  links:
    - "namenode:namenode"
  ports:
    - "50070:50070"
  hostname: datanode 
  dns: "docker inspect --format=\"{{ .NetworkSettings.IPAddress }}\" namenode"
  command: "/etc/bootstrap.sh -d -datanode"
```

もとのリポジトリでそうだったのですが、dnsでnamenodeのprivate ipを指定するところをなんとかやめたいです。。

## 3-6. コンテナを起動

用意したymlを利用してcontainerをrunしてみました。

```bash
sudo docker-compose -f docker-compose up -d
```

起動確認をしてみます。

```bash
$ docker-yarn-cluster # docker ps -a
CONTAINER ID        IMAGE                     COMMAND                CREATED             STATUS              PORTS                                                                                                                                                             NAMES
37f4acc4fb16        letusfly85/yarn-cluster   "/etc/bootstrap.sh -   4 minutes ago       Up 4 minutes        2122/tcp, 8030-8033/tcp, 8040/tcp, 8042/tcp, 8088/tcp, 19888/tcp, 49707/tcp, 50010/tcp, 50020/tcp, 50075/tcp, 50090/tcp, 0.0.0.0:50070->50070/tcp                 datanode
dc88a002f665        letusfly85/yarn-cluster   "/etc/bootstrap.sh -   4 minutes ago       Up 4 minutes        2122/tcp, 8030-8033/tcp, 8040/tcp, 8042/tcp, 19888/tcp, 49707/tcp, 50010/tcp, 50020/tcp, 50070/tcp, 0.0.0.0:8088->8088/tcp, 50075/tcp, 0.0.0.0:50090->50090/tcp   namenode
```

この後、`docker exec -it namenode /bin/bash`ではいって、README.mdに記載のあるgrepのコマンドを実行して動作確認しましたがきちんとmap reduceが実行されました。

# 4. 課題

* [architecture図](https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#NameNode_and_DataNodes)を見て、冗長構成取れるように実装しなおす。
* journalnodeとかzookeeperもはいった構成にしてみる。
* hiveと合わせて実装できるように。
* swarm, k8s, mesos等を利用して、multi nodeで構築できるように。


とはいえ、さくっとモノはできたので、実際の動作、連携方法等をこれから見ていきます。

## 3-7. Dockerfile

```
# Creates pseudo distributed hadoop 2.7.1
#
# sudo docker build -t yarn_cluster .

FROM sequenceiq/pam:centos-6.5
MAINTAINER Luciano Resende lresende@apache.org

USER root

# install dev tools
RUN yum install -y curl which tar sudo openssh-server openssh-clients rsync | true
RUN yum update -y libselinux | true

# passwordless ssh
RUN ssh-keygen -q -N "" -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -q -N "" -t rsa -f /root/.ssh/id_rsa
RUN cp /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys

# java
RUN curl -LO 'http://download.oracle.com/otn-pub/java/jdk/7u71-b14/jdk-7u71-linux-x64.rpm' -H 'Cookie: oraclelicense=accept-securebackup-cookie'
RUN rpm -i jdk-7u71-linux-x64.rpm
RUN rm jdk-7u71-linux-x64.rpm

ENV JAVA_HOME /usr/java/default
ENV PATH $PATH:$JAVA_HOME/bin

# hadoop
RUN curl -s http://ftp.jaist.ac.jp/pub/apache/hadoop/core/hadoop-2.7.1/hadoop-2.7.1.tar.gz | tar -xz -C /usr/local/
RUN cd /usr/local && ln -s ./hadoop-2.7.1 hadoop

ENV HADOOP_PREFIX /usr/local/hadoop
ENV HADOOP_COMMON_HOME /usr/local/hadoop
ENV HADOOP_HDFS_HOME /usr/local/hadoop
ENV HADOOP_MAPRED_HOME /usr/local/hadoop
ENV HADOOP_YARN_HOME /usr/local/hadoop
ENV HADOOP_CONF_DIR /usr/local/hadoop/etc/hadoop
ENV YARN_CONF_DIR $HADOOP_PREFIX/etc/hadoop

RUN sed -i '/^export JAVA_HOME/ s:.*:export JAVA_HOME=/usr/java/default\nexport HADOOP_PREFIX=/usr/local/hadoop\nexport HADOOP_HOME=/usr/local/hadoop\n:' $HADOOP_PREFIX/etc/hadoop/hadoop-env.sh
RUN sed -i '/^export HADOOP_CONF_DIR/ s:.*:export HADOOP_CONF_DIR=/usr/local/hadoop/etc/hadoop/:' $HADOOP_PREFIX/etc/hadoop/hadoop-env.sh

RUN mkdir $HADOOP_PREFIX/input
RUN cp $HADOOP_PREFIX/etc/hadoop/*.xml $HADOOP_PREFIX/input

# pseudo distributed
ADD core-site.xml $HADOOP_PREFIX/etc/hadoop/core-site.xml
#RUN sed s/HOSTNAME/localhost/ /usr/local/hadoop/etc/hadoop/core-site.xml.template > /usr/local/hadoop/etc/hadoop/core-site.xml
ADD hdfs-site.xml $HADOOP_PREFIX/etc/hadoop/hdfs-site.xml

ADD mapred-site.xml $HADOOP_PREFIX/etc/hadoop/mapred-site.xml
ADD yarn-site.xml $HADOOP_PREFIX/etc/hadoop/yarn-site.xml

RUN $HADOOP_PREFIX/bin/hdfs namenode -format

# fixing the libhadoop.so like a boss
RUN rm  /usr/local/hadoop/lib/native/*
RUN curl -Ls http://dl.bintray.com/sequenceiq/sequenceiq-bin/hadoop-native-64-2.7.0.tar | tar -x -C /usr/local/hadoop/lib/native/

ADD ssh_config /root/.ssh/config
RUN chmod 600 /root/.ssh/config
RUN chown root:root /root/.ssh/config

ADD bootstrap.sh /etc/bootstrap.sh
RUN chown root:root /etc/bootstrap.sh
RUN chmod 700 /etc/bootstrap.sh

ENV BOOTSTRAP /etc/bootstrap.sh

# workingaround docker.io build error
RUN ls -la /usr/local/hadoop/etc/hadoop/*-env.sh
RUN chmod +x /usr/local/hadoop/etc/hadoop/*-env.sh
RUN ls -la /usr/local/hadoop/etc/hadoop/*-env.sh

# fix the 254 error code
RUN sed  -i "/^[^#]*UsePAM/ s/.*/#&/"  /etc/ssh/sshd_config
RUN echo "UsePAM no" >> /etc/ssh/sshd_config
RUN echo "Port 2122" >> /etc/ssh/sshd_config

CMD ["/etc/bootstrap.sh", "-d"]

# Hdfs ports
EXPOSE 50010 50020 50070 50075 50090
# Mapred ports
EXPOSE 19888
#Yarn ports
EXPOSE 8030 8031 8032 8033 8040 8042 8088
#Other ports
EXPOSE 49707 2122
```