HDFS・YARNの完全分散クラスタを構築する


## Outline

HadoopのYARN上で色々なアプリを動かすことになったのでテスト環境を作ってみた。

基本的な動作確認は擬似分散モードでいいはずだが、nodeを増やしたり別ホストにnodeを置いた状態でのテストをするために構築してみた。

## 環境

### 共通設定

OS: Ubuntu14.04 （AWS EC2）
ユーザー: ubuntu
VPC: 全マシンは同一subnetに配置
IP: PublicIPとPrivateIPのどちらも使用。
Hadoop 2.5.2
port: 全開放（22, 80, 8020, 8032, 8088, 50070が開いてればたぶん大丈夫）

### マシン・役割

- client
  - 自分のメインマシン。
  - 主にsshで各ノードを操作したり、PublicIP経由で接続を確認したりする。

- master
  - Namenode/ResourceManager用

- node1
  - datanode/NodeManager用

- node2
  - datanode/NodeManager用


各terminalに、対象マシンの名前（client, master, node1, node2と記すことで区別します。）

役割については以下を参照。

http://hadoop.apache.org/docs/r2.5.2/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html

https://hadoop.apache.org/docs/r2.5.2/hadoop-yarn/hadoop-yarn-site/YARN.html


## 初期準備

Hadoopクラスタではsshで通信しあうので、クラスタ同士はパスワードでなく鍵で認証できるようにする。
（AWSならもっと便利な方法があるのかもしれないけど知らないのでアナログな感じです。。。）

まずは鍵を作る。

```bash:terminal(master,node1,node2)
# PasswordAuthentication no　を確認
sudo vim /etc/ssh/sshd_config

# 鍵作成
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
```

まだクラスタ間でやりとりできないのでclientが集めて配布する。
（自動化出来るように書いてないので各自適当にやってください。）

```bash:terminal(client)

# 各ノードの公開鍵を取得する。
scp -i shiba_tokyo_key.pem ubuntu@PublicIP:/home/ubuntu/.ssh/id_rsa.pub ~/Desktop/id_rsa.pub

# 各ノードへ公開鍵を配布する。
scp -i shiba_tokyo_key.pem ~/Desktop/id_rsa.pub ubuntu@PublicIP:/home/ubuntu/id_rsa.pub 
```

```bash:terminal(master,node1,node2)

# 鍵を自身のリストに登録
cat ~/id_rsa.pub >> ~/.ssh/authorized_keys

# 試しにお互いのマシンにSSHしてみる。
ssh PrivateIP
# logoutする。
exit
```


## 各種インストール

### Library

```bash:terminal
# java
sudo add-apt-repository ppa:webupd8team/java -y
sudo apt-get update
sudo apt-get install oracle-java8-installer -y

# Hadoop
# めんどくさいのでHomeにそのまま置く
wget http://ftp.meisei-u.ac.jp/mirror/apache/dist/hadoop/common/hadoop-2.5.2/hadoop-2.5.2.tar.gz
tar zxvf hadoop-2.5.2.tar.gz
```

### 環境変数を設定する。

sudo vim /etc/profile

```bash:/etc/profile
# 末尾に追記する。
export JAVA_HOME=/usr/lib/jvm/java-8-oracle
export HADOOP_HOME=/home/ubuntu/hadoop-2.5.2
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib"
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin
```

```bash:terminal
# 適用する
source /etc/profile
```

重複するけど、こいつも読まれるので編集。
（既に初期値が入っているので上書きします。）

vim hadoop-2.5.2/etc/hadoop/hadoop-env.sh

```bash:hadoop-env.sh
# 既に初期値が入っているので上書きします。
export JAVA_HOME=/usr/lib/jvm/java-8-oracle
export HADOOP_CONF_DIR=/home/ubuntu/hadoop-2.5.2/etc/hadoop
```

## HDFS準備

### datanodeのディレクトリ用意

```bash:terminal(node1,node2)
# datanodeの保存先を用意しておく。
mkdir -p myHadoop/data1
```

### core-site.xml

vim hadoop-2.5.2/etc/hadoop/core-site.xml(master,node1,node2)

```xml:core-site.xml
<configuration>
	<property>
		<name>fs.defaultFS</name>
		<value>hdfs://[master_PrivateIP]:8020</value>
	</property>
	<property>
		<name>hadoop.tmp.dir</name>
		<value>/home/ubuntu/myHadoop/data1</value>
	</property>
</configuration>
```

項目の意味やデフォルト値はこちらを参照。
http://hadoop.apache.org/docs/r2.5.2/hadoop-project-dist/hadoop-common/core-default.xml

### hdfs-site.xml

vim hadoop-2.5.2/etc/hadoop/hdfs-site.xml(master,node1,node2)

```xml:hdfs-site.xml
<configuration>
	<property>
		<name>dfs.replication</name>
		<value>1</value>
	</property>
</configuration>
```

項目の意味やデフォルト値はこちらを参照。
http://hadoop.apache.org/docs/r2.5.2/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml

### namenodeのformat

```bash:terminal(master)
# 実行すると現状のnameNodeのデータは消えるので注意。
# 設定を変えて試したい時とかにリセット目的で使うとかしました。
hdfs namenode -format
```

### 起動

```bash:terminal(master)
# namenode起動
hadoop-2.5.2/sbin/hadoop-daemon.sh start namenode

# 確認（namenodeがあればOK）
jps
```

```bash:terminal(node1,node2)

## datanode起動
## dataNode起動
hadoop-2.5.2/sbin/hadoop-daemon.sh start datanode

# 確認（datanodeがあればOK）
jps
```

WebUIから確認
http://master_PublicIP:50070/
DataNodeタブで、node1_privateIP, node2_privateIPでノードが登録されていることを確認

### 停止（必要があれば）

```bash:terminal
hadoop-2.5.2/sbin/hadoop-daemon.sh stop namenode
hadoop-2.5.2/sbin/hadoop-daemon.sh stop datanode
```


## YARN準備

vim hadoop-2.5.2/etc/hadoop/yarn-site.xml

```xml:yarn-site.xml
<configuration>
	<property>
		<name>yarn.resourcemanager.hostname</name>
		<value>[PrivateIP]</value>
	</property>
</configuration>
```

項目の意味やデフォルト値はこちらを参照。
http://hadoop.apache.org/docs/r2.5.2/hadoop-yarn/hadoop-yarn-common/yarn-default.xml

### 起動

master

```bash:terminal
## resource Manager起動
hadoop-2.5.2/sbin/yarn-daemon.sh start resourcemanager

## NodeManager起動
hadoop-2.5.2/sbin/yarn-daemon.sh start nodemanager
```

### 確認

#### terminalから

```bash:terminal
# ResourceManager, NodeManagerがあればOK
jps
```

#### WebUIから

http://[PublicIP]:8088/

nodesで一つ登録されていることを確認

### 停止（必要があれば）

```bash:terminal
hadoop-2.5.2/sbin/yarn-daemon.sh stop resourcemanager
hadoop-2.5.2/sbin/yarn-daemon.sh stop nodemanager
```

## クライアントからの動作確認

別記事にて記載。

## ハマったポイントとか

### 起動に失敗した時にログが便りにならない。
何が原因で失敗したのかのログはどこかに出力されてるんだろうか？

### ホストの設定をlocalhostにすると、clientから（PublicIPから）繋げない。。。
`netstat -antu`とかで見ると、localhostからのアクセスしか受け付けないようになってた。。
fsDefaultをlocalhostにするとつなげない。

### DataNodeが立ち上がらないケースがある。
分散モード・擬似分散モードを行き来していたため、なんどかnameNodeをフォーマットしなおしたのだが、
その際にDataNodeが立ち上がらなくなる。（特にエラー吐かないがjpsコマンドで立ち上がってない。）
理由は単純で、nameNodeを新しくしたのにDataNodeのデータはまだ残ってしまっていて、そのままではデータが合わないため。
core-site.xmlのtemp〜〜のところを変えるか、該当フォルダの中身を全部消すと立ち上がる。