このシリーズ
- Spark on Dockerで分散型機械学習を始める - Part 1: インストール
- Spark on Dockerで分散型機械学習を始める - Part 2: UbuntuでIPython Notebookを使う
- Spark on Dockerで分散型機械学習を始める - Part 3: ローカルモードでspark-shellを起動する
- Spark on Dockerで分散型機械学習を始める - Part 4: AmbariでHadoopとSparkのsingle nodeセットアップ
Apache Ambari
Sparkの勉強はローカルモードでもspark-shellやspark-submitを実行することができますが、分散型機械学習のためには最初から分散環境で動かす方がやる気が出ます。
今回はHadoopクラスタ管理ツールのApach AmbariでHadoopをDocker上に構築します。AmbariエージェントのコンテナにセットアップしたSparkからYARNとHDFSを使ってみます。
Apach AmbariはHDPクラスタ管理ツールのCloudbreakの中心コンポーネントです。開発元のSequenceIQ2015年4月にHortonworksされているので、HDPをクラウドとDockerで構築する場合に安心して使えます。
Blueprint
Ambariの特徴にBlueprintがあります。JSONのBlueprint定義されたクラスタはAmbari ShellのCLI、CloudbreakのAPIなどから使いクラウドの仮想マシンやDockerコンテナにデプロイできます。
single-node-hdfs-yarn
SequenceIQのリポジトリにあるsingle-node-hdfs-yarnのBlueprintを試してみます。他にもCloudbreakのリポジトリもあるのでもいろいろ試してみたいと思います。
Ambari provisioned Hadoop cluster on Dockerを読みながら作業を進めます。
Docker
DockerはMesosをDocker Composeを使い起動する - Part 1: 1つの仮想マシンにセットアップするで構築したDebianの仮想マシンを使います。
Ambari
Ambariのセットアップはとても簡単です。j.mp/docker-ambariからダウンロードしたシェルスクリプトを読み込み関数や環境変数の設定を行います。インストール関数の引数は2 single-node-hdfs-yarn
を指定するとamb-server
とamb-agent
で計2台のコンテナができます。single
ですが引数は2なので注意が必要です。
$ curl -Lo .amb j.mp/docker-ambari && . .amb && amb-deploy-cluster 2 single-node-hdfs-yarn
...
ambari-shell>cluster build --blueprint single-node-hdfs-yarn
HOSTNAME STATE
------------------- -------------------
amb1.service.consul amb1.service.consul
HOSTGROUP COMPONENT Installation: 6.81% ----------
--------- -------------------
master ZOOKEEPER_CLIENT
master MAPREDUCE2_CLIENT
master RESOURCEMANAGER
master TEZ_CLIENT
master SECONDARY_NAMENODE
master HISTORYSERVER
master APP_TIMELINE_SERVER
master HDFS_CLIENT
master DATANODE
master NAMENODE
master NODEMANAGER
master ZOOKEEPER_SERVER
master YARN_CLIENT
CLUSTER_BUILD:single-node-hdfs-yarn>cluster autoAssign
HOSTGROUP HOST
--------- -------------------
master amb1.service.consul
CLUSTER_BUILD:single-node-hdfs-yarn>cluster create --exitOnFinish true
Successfully created the cluster
CLUSTER:single-node-hdfs-yarn>
このインストール関数ではDockerイメージのダウンロードとコンテナの起動、Ambari Shellを使った設定まで自動的に行ってくれます。シェルの右上にプログレスバーが表示されしばらく待つと終了します。
作成されたDockerコンテナを確認します。Ambari Server、Ambari Aagent、Consulの3つのコンテナが起動しました。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
70cbaaf536d9 sequenceiq/ambari:2.1.2-v1 "/start-agent" 9 minutes ago Up 9 minutes 8080/tcp amb1
682212a98724 sequenceiq/ambari:2.1.2-v1 "/start-server" 9 minutes ago Up 9 minutes 8080/tcp amb-server
04bf47cee35e sequenceiq/consul:v0.5.0-v6 "/bin/start -server -" 9 minutes ago Up 9 minutes 53/tcp, 53/udp, 8300-8302/tcp, 8400/tcp, 8301-8302/udp, 8500/tcp amb-consul
Spark
Ambari Agentのamb1コンテナに入りSparkのインストールを行います。
$ docker exec -it amb1 bash
Single nodeなのでこのコンテナにHDPのコンポーネントが全てインストールされています。 HDPのバージョンは2.3.2です。
$ rpm -qa | grep hdp-select
hdp-select-2.3.2.0-2950.el6.noarch
$ hdp-select versions
2.3.2.0-2950
$ /usr/hdp/2.3.2.0-2950
Install Apache Spark with Cloudbreakを読みながら作業を進めていきます。シェルスクリプトをダウンロードして関数と環境変数を読み込みます。Ambariのインストールと同じような手順でインストール関数を実行します。
$ curl -Lo .spark-install j.mp/spark-hdp-install && . .spark-install
$ install-spark
upload assembly jar to hdfs
HDFSにSparkのjarがアップロードされました。このスクリプトを読み込むとSparkの起動に必要な環境変数も設定されています。
$ echo $YARN_CONF_DIR
/usr/hdp/2.2.0.0-2041/hadoop/conf
$ echo $SPARK_JAR
hdfs:///spark/spark-assembly-1.2.0.2.2.0.0-82-hadoop2.6.0.2.2.0.0-2041.jar
次にspark-env.shはテンプレートをコピーしてHADOOP_CONF_DIR
環境変数を指定します。
$ cd /usr/local/spark/conf
$ cp spark-env.sh.template spark-env.sh
$ vi spark-env.sh
HADOOP_CONF_DIR=/usr/hdp/current/hadoop-client/conf
spark-submit
spark-submitを実行して円周率の計算をします。
$ spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn-cluster \
--num-executors 3 \
--driver-memory 512m \
--executor-memory 512m \
--executor-cores 1 \
/usr/local/spark/lib/spark-examples*.jar
...
15/11/30 02:04:13 INFO yarn.Client:
client token: N/A
diagnostics: N/A
ApplicationMaster host: amb1.service.consul
ApplicationMaster RPC port: 0
queue: default
start time: 1448850560018
final status: SUCCEEDED
tracking URL: http://amb1.service.consul:8088/proxy/application_1448849730081_0004/
user: hdfs
YARNのlogに計算された円周率が出力されています。
$ yarn logs -applicationId application_1448849730081_0004
...
LogType:stdout
Log Upload Time:Mon Nov 30 02:48:54 +0000 2015
LogLength:23
Log Contents:
Pi is roughly 3.140252
End of LogType:stdout
- HDFS
$ hadoop fs -ls /user
Found 2 items
drwxrwx--- - ambari-qa hdfs 0 2015-11-30 02:14 /user/ambari-qa
drwxr-xr-x - hdfs hdfs 0 2015-11-30 02:18 /user/hdfs
$ hadoop fs -ls /user/hdfs
Found 1 items
drwxr-xr-x - hdfs hdfs 0 2015-11-30 02:35 /user/hdfs/.sparkStaging
spark-shell
次にspark-shellの起動を確認します。デフォルトだとログがたくさん出るのでrootCategory
のログレベルをINFOからWARNに変更します。
$ cd /usr/local/spark/conf
$ cp log4j.properties.template log4j.properties
$ sed -i 's/log4j.rootCategory=INFO/log4j.rootCategory=WARN/' log4j.properties
--master
フラグにyarn
を指定してYARN上でspark-shellを実行します。
$ spark-shell --master yarn
tput: No value for $TERM and no -T specified
Spark assembly has been built with Hive, including Datanucleus jars on classpath
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 1.2.0
/_/
Using Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_67)
Type in expressions to have them evaluated.
Type :help for more information.
15/11/30 03:06:02 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
15/11/30 03:06:09 WARN DomainSocketFactory: The short-circuit local reads feature cannot be used because libhadoop cannot be loaded.
15/11/30 03:06:09 WARN ClientBase: SPARK_JAR detected in the system environment. This variable has been deprecated in favor of the spark.yarn.jar configuration variable.
15/11/30 03:06:09 WARN ClientBase: SPARK_JAR detected in the system environment. This variable has been deprecated in favor of the spark.yarn.jar configuration variable.
Spark context available as sc.
scala>
SPARK_JAR環境変数がdeprecatedになった警告が出ています。環境変数をunset、環境設定スクリプトもコメントアウトして次回実行時にはロードしないようにします。
$ echo $SPARK_JAR
hdfs:///spark/spark-assembly-1.2.0.2.2.0.0-82-hadoop2.6.0.2.2.0.0-2041.jar
$ unset SPARK_JAR
$ sed -i 's/^ *\(export SPARK_JAR.*\)$/# \1/' /tmp/.spark-install}}}
再度spark-shellを実行すると警告が消えました。
spark-shell --master yarn
tput: No value for $TERM and no -T specified
Spark assembly has been built with Hive, including Datanucleus jars on classpath
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 1.2.0
/_/
Using Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_67)
Type in expressions to have them evaluated.
Type :help for more information.
15/11/30 03:14:08 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
15/11/30 03:14:14 WARN DomainSocketFactory: The short-circuit local reads feature cannot be used because libhadoop cannot be loaded.
Spark context available as sc.
scala>
次にSparkを使うとき
セットアップをしたシェルとコンテナを抜けた後にSparkを実行する場合は、環境設定スクリプトを読み込み必要な環境変数を読み込みます。
$ cd /tmp
$ source spark-install
$ set-spark-envs
$ echo $SPARK_HOME
/usr/local/spark
$ echo $HADOOP_USER_NAME
hdfs
$ which spark-submit
/usr/local/spark/bin/spark-submit
set-spark-envs
関数を実行すると以下の環境変数をexportします。
set-spark-envs() {
export SPARK_HOME=/usr/local/spark
export YARN_CONF_DIR=/usr/hdp/$HDP_VERSION/hadoop/conf
export PATH=$PATH:$SPARK_HOME/bin
export HADOOP_USER_NAME=hdfs
# export SPARK_JAR=hdfs:///spark/spark-assembly-$SPARK_ASSEMBLY_VERSION.jar
}
まとめ
次回はAmbariのBlueprintにあるmulti-node-hdfs-yarnや、Apache Zeppelinをセットアップするdatascientist.bpなどもう少し大きめのクラスタを構築してみようと思います。
参考
以下のサイトを参考にしました。