LoginSignup
4
4

More than 5 years have passed since last update.

Apache Zeppelinでデータ分析を分散処理する - Part 5: Ambari on DockerとsbtのScalaビルド環境

Last updated at Posted at 2015-12-26

 Part 2でセットアップしたAmbari on DockerとApache Zeppelinの環境にsbtを使ったビルド環境をDockerで作ってみます。ScalaのコードもZeppelinの画面上で書いて実行したほうが簡単なのですが、Sparkアプリのjarをspark-submitする環境も作っておきます。

このシリーズ

プロジェクト

 プロジェクトのディレクトリを作成します。

$ mkdir -p ~/scala_apps/spike
$ cd !$

DockerとDocker Compose

 sbtのビルド環境はDockerとDocker Compose上に構築します。コンテナは使い捨て、プロジェクトのディレクトリはDockerホストからマウントします。成果物のjarもDokcerホスト上に作成されます。ScalaのコーディングはDockerホスト上のエディタか、別のコーディング用コンテナで行う想定です。

Dockerfile

 DockerfileはオフィシャルjavaのOpenJDK 7をベースにします。Apache Ivyのartifactsのキャッシュディレクトリとsbtのグローバルセッティングのディレクトリをボリュームにします。この2つは実行時にDockerホストのディレクトリをマウントして永続化します。sbtを始めて実行する時にartifactsをたくさんダウンロードするのですが、これが結構時間がかかります。

Dockerfile
FROM java:openjdk-7-jdk
MAINTAINER Masato Shimizu <ma6ato@gmail.com>

ENV SBT_VERSION 0.13.9
ENV PATH ${PATH}:/usr/local/sbt/bin

WORKDIR /app

RUN wget -O- http://dl.bintray.com/sbt/native-packages/sbt/$SBT_VERSION/sbt-$SBT_VERSION.tgz | tar xz -C /usr/local

VOLUME ["/root/.ivy2", "/root/.sbt", "/app"]

docker-compose.yml

 docker-compose.ymlファイルにコンテナを起動するときの設定を書いておきます。Ambari on Dockerで構成するHadoopクラスタのConsulを使ったDNSを外部から利用しています。sbtコンテナでビルドしたjarファイルをWebHDFS経由でPUTするときにHadoopノードの名前解決が必要になります。

docker-compose.yml
sbt:
  build: .
  volumes:
    - .:/app
    - /temp/.sbt:/root/.sbt
    - /temp/.ivy2:/root/.ivy2
  dns:
    - $AMB_CONSUL
    - 172.17.0.1
    - 8.8.8.8
  dns_search:
    - service.consul

 Dockerイメージをbuidします。

$ docker-compose build

Scala REPL

 Scalaのインタープリターをsbt consoleコマンドから起動してみます。AMB_CONSUL環境変数はREPLの起動では使いませんが、docker-compose.ymlに定義してある環境変数が見つからないと警告が出るため最初にexportしておきます。

$ export AMB_CONSUL=$(docker inspect --format="{{ .NetworkSettings.IPAddress }}" amb-consul)
$ docker-compose run --rm sbt sbt console
[info] Set current project to Sample app (in build file:/app/)
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.10.5 (OpenJDK 64-Bit Server VM, Java 1.7.0_91).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :quit

sbtコンテナ

 Scalaのコードを配置するディレクトリを作成します。

$ cd ~/scala_apps/spike
$ mkdir -p src/main/scala/

SampleApp.scala

 SparkのLICENSEファイルの行数を数える単純なSparkアプリを書きます。

src/main/scala/SampleApp.scala
import org.apache.spark.{SparkContext, SparkConf}

object SampleApp {
  def main(args: Array[String]) {
    val conf = new SparkConf().setAppName("App")
    val sc = new SparkContext(conf)

    val src = sc.textFile("LICENSE")
    val lines = src.count()

    println("Lines %,d".format(lines))
  }
}

build.sbt

 プロジェクトのビルド定義を書きます。sbtの0.13.9に合わせてScalaは2.10.5を指定します。HDP 2.3と同じSpark 1.4.1をビルド用に使います。今回は最初なのでspark-submitするjarはsbt assemblyを使ったuberjarではありません。

build.sbt
name := "Sample app"

version := "1.0"

scalaVersion := "2.10.5"

libraryDependencies += "org.apache.spark" %% "spark-core" % "1.4.1"

sbt package

 プロジェクトのディレクトリはScalaのソースコードを含めて以下のようになりました。

$ tree
.
├── Dockerfile
├── build.sbt
├── docker-compose.yml
└── src
    └── main
        └── scala
            └── SampleApp.scala

 sbtコンテナを使ってSparkアプリをビルドします。target/scala-2.10/sample-app_2.10-1.0.jarファイルがDockerホスト上に作成されました。

$ docker-compose run --rm sbt sbt package
[info] Set current project to Sample app (in build file:/app/)
[info] Packaging /app/target/scala-2.10/sample-app_2.10-1.0.jar ...
[info] Done packaging.
[success] Total time: 1 s, completed Dec 26, 2015 4:13:52 AM

HDFS

 ここからはAmbari on Dockerで構成されたHadoopクラスタのコンテナを使います。HDFSのNameNodeであるamb1ノードを使います。

 今回はrootユーザーのまま作業をしているので、HDFSの/userディレクトリにユーザーのホームディレクトリがあることを確認します。

$ docker exec amb1 hadoop fs -ls /user
Found 5 items
drwxrwx---   - ambari-qa hdfs          0 2015-12-25 17:08 /user/ambari-qa
drwxr-xr-x   - hcat      hdfs          0 2015-12-25 17:10 /user/hcat
drwx------   - hive      hdfs          0 2015-12-25 17:10 /user/hive
drwxr-xr-x   - root      hdfs          0 2015-12-26 02:40 /user/root
drwxrwxr-x   - spark     hdfs          0 2015-12-25 17:09 /user/spark

 /user/rootディレクトリがなければ、以下のようにhdfsユーザーにスイッチして作成します。

$ su hdfs 
$ hadoop fs -mkdir /user/root
$ hadoop fs -chown root /user/root

 サンプルのSparkアプリで利用するLICENSEファイルはHDPの以下のディレクトリにあります。

/usr/hdp/2.3.4.0-3485/spark/LICENSE

 LICENSEファイルをyarn-clusterモードで実行するSparkアプリから読み込むためにHDFSにputしておきます。

$ docker exec amb1 hadoop fs -put /usr/hdp/2.3.4.0-3485/spark/LICENSE /user/root
$ docker exec amb1 hadoop fs -ls /user/root/LICENSE
-rw-r--r--   3 root hdfs      17356 2015-12-25 17:20 LICENSE

 SparkアプリのjarファイルもWebHDFS経由でputします。

$ docker-compose run --rm sbt \
  curl -L -X PUT -T /app/target/scala-2.10/sample-app_2.10-1.0.jar "http://amb1:50070/webhdfs/v1/user/root/test/sample-app_2.10-1.0.jar?user.name=root&op=CREATE&overwrite=true"

 HDFSに/user/test/sample-app_2.10-1.0.jarファイルが作成されました。

$ docker exec amb1 hadoop fs -ls ./test/sample-app_2.10-1.0.jar
-rwxr-xr-x   3 root hdfs       1862 2015-12-26 04:16 test/sample-app_2.10-1.0.jar

spark-submit

 最後にspark-submitをしてHDFSにputしたSparkアプリを実行します。--masterフラグにはyarn-clusterを指定してYARNのアプリケーションマスターのプロセスで実行しています。

$ docker exec  amb1 \
 spark-submit \
  --class SampleApp \
  --master yarn-cluster \
  --driver-memory 1g \
  --executor-memory 1g \
  --executor-cores 1 \
  hdfs://amb1/user/root/test/sample-app_2.10-1.0.jar
...
15/12/26 02:54:18 INFO Client:
     client token: N/A
     diagnostics: N/A
     ApplicationMaster host: 172.17.0.5
     ApplicationMaster RPC port: 0
     queue: default
     start time: 1451098443955
     final status: SUCCEEDED
     tracking URL: http://amb1.service.consul:8088/proxy/application_1451063385654_0011/
     user: root
15/12/26 02:54:18 INFO ShutdownHookManager: Shutdown hook called
15/12/26 02:54:18 INFO ShutdownHookManager: Deleting directory /tmp/spark-c30cdca1-6f2b-4432-a866-c63391e619b2

 yarn longコマンドからSparkアプリの実行結果を確認します。SparkのLICENSEファイルは294行ありました。

$ docker exec amb1 \
  yarn logs -applicationId application_1451063385654_0011
...
LogType:stdout
Log Upload Time:Sat Dec 26 02:54:19 +0000 2015
LogLength:10
Log Contents:
Lines 294
End of LogType:stdout
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4