Docker SwarmでApache Sparkクラスタを構築してみる

  • 2016-01-12 (Tue)
  • namikingsoft

前回の記事でSwarmクラスタを構築したので、Apache Sparkのクラスタを載せてみる。

本来ならオンプレでクラスタを組んだり、AmazonのEMRを使うのが一般的かもだが、安めのクラウドでもできないかなーという試み。

まずはシンプルに、Standaloneモードから動かしてみたい。

事前準備

マルチホスト同士の通信が可能なSwarmクラスタを構築しておく

Sparkのクラスタ同士は、一方通行な通信ではなく、割りと親密な双方向通信をするため、オーバーレイ・ネットワーク上に構築しないとうまく動作しない。

オーバーレイ・ネットワーク構築するには、Consul, etcd, Zookeeperのようなキーストアを自身で導入する必要があるので、 DigitalOceanでマルチホストなDockerSwarmクラスタを構築を参考に、以下の様なSwarmクラスタを構築しておいた。

Swarm Structure

Sparkクラスタをコンテナで構築する

docker-composeを用いて、各ノードにSparkクラスタを構築する。

Spark Containers

Apache SparkのDockerイメージ

Standaloneモードで動くシンプルなものが使いたかったので、SparkのDockerイメージは自前で用意したものを使った。

namikingsoft/docker-spark
https://github.com/namikingsoft/docker-spark

masterならbin/start-master.shを実行し、workerならbin/start-slave.sh ${MASTER_HOSTNAME}:7077を実行するだけのシンプルなもの。

docker-compose.yml

master:
  image: namikingsoft/spark
  hostname: master
  container_name: master
  environment:
    - constraint:node==/node0/
  privileged: true
  command: master

worker:
  image: namikingsoft/spark
  environment:
    - MASTER_HOSTNAME=master
    - constraint:node!=/node0/
    - affinity:container!=/worker/
  privileged: true
  command: worker

environmentからのconstraintaffinityの指定によってコンテナの配置をコントロールできる。コンテナの数をスケールするときもこのルールに沿って配置される。
>> 指定方法の詳細

イメージ各コンテナはDockerのオーバーレイネットワークで繋がるので、 ポートも特に指定しなくてもよい。WebUIなどは後ほど、Socksプロキシ経由で確認する。

Swarm Masterの環境変数を設定

eval "$(docker-machine env --swarm swarm-node0)"

docker-compose up

docker-compose --x-networking up -d

--x-networkingを引数で指定すれば、各コンテナがDockerのオーバーレイ・ネットワークで繋がる。--x-network-driver overlayを省略しているが、デフォルトで指定されるみたい。

docker-compose up直後の状態では、ワーカーコンテナが1つしか立ち上がらないので、以下の様な感じになっている。

Spark Containers Progress

ワーカーをスケールしてみる

docker-composeのscaleコマンドでワーカーノードを指定数分スケールすることができる。

docker-compose scale worker=2

コンテナ配置の確認

docker ps --format "{{.Names}}"
swarm-node0/master
swarm-node1/dockerspark_worker_1
swarm-node2/dockerspark_worker_2

各ノードにコンテナが配置されたのがわかる。

ちなみに、MasterとWorkerを一緒のノードで動かしたら
spark-shell起動時にCannot allocate memory的なエラーを吐いた。 チューニング次第かもだが、DigitalOcean 2GBだとリソース的には厳しそう。

Sparkシェルを動かしてみる

仮にSparkマスターコンテナをドライバーとして、動かしてみる。 (ワーカーでも動作可能)

docker-exec -it master bash
spark-shell --master spark://master:7077
scala> sc.parallelize(1 to 10000).fold(0)(_+_)
res0: Int = 50005000

Spark UIを確認

SparkのWebUIから、ワーカーが接続されているか確認したいが、docker-compose.ymlではポートを開けていない。(本来閉じたネットワークで動かすので、ポートを開放するのはあまりよろしくない)

なので、新たにSSHdコンテナを設置して、Socksプロキシ経由でWebUIを確認する。

Sparkマスター WebUI

SSHdコンテナを追加

先ほどのdocker-compose.ymlに追加する。

master:
  image: namikingsoft/spark
  hostname: master
  container_name: master
  environment:
    - constraint:node==/node0/
  privileged: true
  command: master

worker:
  image: namikingsoft/spark
  hostname: woker
  environment:
    - constraint:node!=/node0/
    - affinity:container!=/worker/
  privileged: true
  command: worker

# SSHdコンテナを追加
sshd:
  image: fedora/ssh
  ports:
    - "2222:22"
  environment:
    SSH_USERNAME: user
    SSH_USERPASS: something

以下のコマンドで、SSHdコンテナが起動する。

docker-compose --x-networking up -d

ローカルPCでSocksプロキシを起動

swarm-masterのIPを確認。

docker-machine ls

Socksプロキシの起動。

ssh user@(swarm-masterのIP) -p2222 -D1080 -fN
Password: something

Socksプロキシを止めるときはCtrl-cを押下。

ローカルPCにてSocksプロキシを設定

ローカルPCのSocksプロキシ設定をlocalhost:1080に設定する。 SSHのSocks周りについては以下のページが参考になった。

ssh経由のSOCKSプロキシを通じてMac上のGoogle Chromeでブラウジング
ssh -D と tsocks - 京大マイコンクラブ (KMC)

ブラウザで確認

open http://(swarm-masterのIP):8080

Sparkマスター WebUI

先ほど、スケールした2つのワーカーコンテナがマスターに接続されているのがわかる。 IPや名前解決はSSH接続先のものを参照してくれて便利。(OSX10.9+Chromeで確認)

Sparkワーカー WebUI

comments powered by Disqus

この記事について

書いた人
Written by

namikingsoft

何かを残して逝きたい
フロントエンドエンジニア