Docker
Mesos
Marathon
Chronos

瞬殺で作るMesos + Chronos + Marathon + Dockerクラスタ環境

More than 3 years have passed since last update.


瞬殺で作るMesos + Chronos + Marathon + Dockerクラスタ環境

本記事では、瞬殺でApache Mesosの環境を簡単に試してみたい方のために、Apache Mesos + Chronos + Marathon + Dockerのクラスタを簡単にセットアップするための方法をご紹介いたします。


Apache Mesosとは

Apache Mesosは、クラスタリソースマネージャであり、物理マシン(または仮想マシン)を1つのクラスタとして管理し、タスクを処理させたいときに、空いているマシンを探して、そこでリソースを割り当てて実行してくれるような仕組みです。この説明部分は正月休みだし Mesos 触ってみたという素晴らしい記事を参考にしています。すごくわかりやすい説明でした。


Marathonとは

Apache Mesosでタスクを実行すると、どこかのサーバーでタスクを実行してくれるわけなのですが、タスクの実行をするのは一瞬です。これは、通常のOSでの挙動に例えると、MesosはOSのカーネルみたいなもので、そのカーネルでコマンドを実行した状態に似ています。

 通常のOSでは、デーモンを実行させるサービスみたいな仕組みがあるのですが、クラスタの状態でこの長期に実行されるようなデーモンを実行させる仕組みがMarathonです。

 


Chronosとは

Chronosとは、同じノリで例えると、クラスタ用のクーロンの仕組みです。定期実行するタスクを管理していきます。

さて、ここまで読んでも、正直ナンノコッチャ?という感じだと思いますので、実際に環境を作って試してみましょう。


クラスタ構成を組む難しさ

シングルノードで上記の環境をセットアップするのは簡単なのですが、クラスタ構成を組まないと、Mesosの本当の魅力は体験することができないと思います。ところが、クラスタ構成を組むと、クラスタ構成を組むこと自体にも時間がかかりますし、それに加えて、試行錯誤をしていると、その都度結構な時間がかかってしまいます。そこで、今回は、Vagrantを使って、クラスタ構成のファイルをそのままGitHubにあげておきましたので、そこからクローンすることで簡単に構成を作れるような手順を作成してみました。簡単にMesosのクラスタを試してみたい人は是非ご利用ください。

もちろん、記事内には設定の意味とか、つまづいたポイントそして、チュートリアルを整理しておきましたので少しでも皆さんの参考になれば幸いです。

参考までに、筆者の環境は次の通りです。多分厳密に一緒じゃなくても動作すると思います。

Mac OS X Yosemite version 10.10.2 

Virtual Box 4.3.26
vagrant 1.7.2
git 2.2.1


クラスタ構成イメージ

今回構成をするクラスタのイメージを共有しておきます。次からご紹介する手順を実行すれば下記の図のような構成のクラスタを構成することができます。

クラスタ構成

マスター3台、スレーブ2台で構成されています。OSは、Ubuntuを使ってみました。実際にジョブを動作させるのはスレーブの方になります。スレーブにはDockerもインストールしています。


クラスタ構成を作成する手順

さて、クラスタを構築するのは下記の手順です。まず、動いているものがないと理解しにくいと思いますので、下記の手順で環境を作っていきましょう。


1. 前提条件

このチュートリアルの前提ですが、MacOSXに、Vagrant、gitがインストールされていることを前提としています。また、メモリは、2G x 6台使うように設定していますので、メモリをある程度積んでいるマシンで試してみてください。さすがにクラスタ環境なので、Vagrant上で起動させるVMのメモリを少なくすると、メモリ割当のエラーがでてしまいますのでこの設定にしています。


2. ファイルのクローン

次のコマンドを実行して、必要なファイルを取得してください。

$ git clone https://github.com/TsuyoshiUshio/MesosClusterSpyke.git

$ cd MesosClusterSpyke
$ ls

これで、幾つかのシェルファイルと、Vagrantファイルがダウンロードできたと思います。


3. クラスタのセットアップ

クラスタのセットアップはとても簡単で

$ vagrant up

$ vagrant reload

で完了です。私の環境で40分程度かかりました。

余談ですが、ここで、vagrant upの後にvagrant reloadをかけています。これは実はとても重要です。vagrant upを実行すると、vagrantで自動的にプロビジョンしてくれるように設定してくれるのですが、この状態だけだと、Mesosや、Chronosがちゃんと動いているように見えるのですが、実際にはChronosでジョブ投入しても、Mesosに反映されないなどの謎の挙動をします。このような状態は、パッケージのインストール、設定の実施後、一旦全てのマシンの再起動をすることで、正常に動作するようになります。

上記の内容でもMesosを試すにはなんの問題もないのですがreload時にSlaveのノードでは次のようなエラーがでます。

mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group vagrant | cut -d: -f3` vagrant /vagrant

mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` vagrant /vagrant

The error output from the last command was:

stdin: is not a tty
/sbin/mount.vboxsf: mounting failed with the error: No such device

英語のサイトも沢山みて、実施してみたのですが、基本的にVagrant (3) 続・CentOS7 の仮想マシンを作るの方法でうまくいきました。

原因はGuest Additionsという、ホストコンピュータに対するゲストコンピュータの便利ツールのパッケージがおそらくdocker関連のインストールでバージョンがずれてしまっていることだと思います。よって解決策は、Guest Additionsを再構成したらいいのですが、これがインターネットに出回っている一般的な方法だと、現在のVirtual BoxやVagrantに比べてバージョンが古いので実行できません。結局解決したのはvagrantのvagrant-vbguestプラグインで、これにより、vagrant-vbguestプラグインがGuestAdditionsを無効にしてしまうの問題が出ることがあるらしいので、もし出たら参照してくださいね。

$ vagrant plugin install vagrant-vbguest


4. 動作の確認

動作の確認ですが、次のページを起動しましょう。ただし、Apache Mesosのページにアクセスすると、違うサーバーにリダイレクトされる場合があります。今回はマスター3台構成にしていますが、Mesosが自動的にクラスタの3台のうち、マスターノードのサーバーにリダイレクトするからです。ジョブの発行は、マスターノードのサーバーから実行します。マスターノードが192.168.33.10ではない場合、MesosがリダイレクトしたサーバーのIPアドレス(192.168.33.11 or 192.168.33.12)でMarathon/Chronosのサイトを実行してみてください。

Apache Mesos :   http://192.168.33.10:5050

Marathon : http://192.168.33.10:8080
Chronos : http://192.168.33.10:8081

これで準備は完了です。


Mesos/Marathon/Chronosセットアップのポイント

さて、自分のお試し環境は簡単に上記の手順で作れますが、内部でどういう設定をしているか知りたい人は次のパートを読んでください。とにかく試してみたい方は「Mesosを試してみる」から続きを読んでいただければと思います。


1. Masterの設定

まず、Masterノードの設定です。Vagrantファイルの該当部分を見てみます。1つ目のマスターノードの設定部分をピックアップしてみます。ここでは、UbuntuのBoxを使って、仮想マシン名、IPアドレス、メモリの設定をしています。加えて仮想マシンができた後に、シェルファイルを実行して、各種パッケージのインストールや設定を自動的に行っています。

Vagrant.configure(2) do |config|

config.vm.box = "ubuntu/trusty64"
config.vm.define "master_01" do |master|
master.vm.network "private_network", ip: "192.168.33.10"
master.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
end
master.vm.provision "file", source: "common_ubuntu.sh", destination: "/tmp/user-shell/common_ubuntu.sh"
master.vm.provision "file", source: "master_file.sh", destination: "/tmp/user-shell/master_file.sh"
master.vm.provision "shell", path: "master_01_file.sh"
end

:

具体的には上記のmaster.vm.provision "shell", path: "master_01_file.sh"の部分でmaster_01_file.shをカレントディレクトリから、仮想マシンにアップロードして、そこでそのシェルを実行してくれます。

実はこのシェルの内部で、common_ubuntu.shとmaster_file.shを使っているのですが、内部で使っているシェルファイルまでは一緒にアップロードしてくれないので、master.vm.provision "file"を用いて、個別に/tmp/user-shellというディレクトリにアップロードしています。

では、次に、上記のシェルの中身を見ていきましょう。最初にcommon_ubuntu.shです。これは、基本的なタイムクライアントの設定、ロケールの設定、タイムゾーンの設定を行っています。これは、Mesosに関係ない設定ですね。

sudo ntpdate ntp1.jst.mfeed.ad.jp 

sudo apt-get -y update
sudo apt-get -y install language-pack-ja

export LC_CTYPE="ja_JP.UTF-8"
export LC_ALL="ja_JP.UTF-8"

sudo update-locale LANG=ja_JP.UTF-8
sudo update-locale LANGUAGE=ja_JP
sudo update-locale LC_CTYPE=ja_JP.UTF-8
sudo update-locale LC_ALL=ja_JP.UTF-8

echo "Asia/Tokyo" | sudo tee /etc/timezone
sudo dpkg-reconfigure --frontend noninteractive tzdata

次にmaster_01_file.shですが、マスタノードは3台セットアップしますが、マスターノードのインストールのうち違う箇所だけ切り出しています。先ほどのcommon_ubuntu.shの実行の他に、インストール手順でマシンごとに異なる部分を切り出しています。

source /tmp/user-shell/common_ubuntu.sh

export ZOOKEEPER_MY_ID=1
export HOST_IP_ADDRESS=192.168.33.10

source /tmp/user-shell/master_file.sh

そして、最後に、master_file.shです。これが本体です。長いのでパートごとに解説していきます。

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E56151BF

export DISTRO=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
export CODENAME=$(lsb_release -cs)

echo "deb http://repos.mesosphere.io/${DISTRO} ${CODENAME} main" | \
sudo tee /etc/apt/sources.list.d/mesosphere.list

最初のパートでapt-keyで、公開キーをダウンロードしています。このコマンドはapt-getコマンドで、標準ではないサーバーからパッケージを取得したいような時に使います。ちなみにdebはコマンドではなく、aptでパッケージを取得するためのサーバーのアドレスの設定です。

sudo apt-get update

sudo apt-get -y install mesos marathon

ここは、mesosとmarathonのインストールですね。これらをインストールすると依存関係から、zookeeperも自動でインストールされます。

echo $ZOOKEEPER_MY_ID | sudo tee /etc/zookeeper/conf/myid

echo -e "server.1=192.168.33.10:2888:3888\nserver.2=192.168.33.11:2888:3888\nserver.3=192.168.33.12:2888:3888" | sudo tee -a /etc/zookeeper/conf/zoo.cfg

sudo service zookeeper restart

ZooKeeperの設定です。マスターノードのIPアドレスの設定をzoo.cfgに記述するので、それをしています。設定変更後、zookeeperを再起動しています。Zookeeprの説明はこちらのサイトに詳しいです。

echo "zk://192.168.33.10:2181,192.168.33.11:2181,192.168.33.12:2181/mesos" | sudo tee /etc/mesos/zk

echo "2" | sudo tee /etc/mesos-master/quorum
echo $HOST_IP_ADDRESS | sudo tee /etc/mesos-master/hostname
echo $HOST_IP_ADDRESS | sudo tee /etc/mesos-master/ip
echo "Cluster01" | sudo tee /etc/mesos-master/cluster

sudo service mesos-slave stop
sudo sh -c "echo manual > /etc/init/mesos-slave.override"

sudo service mesos-master restart
sudo service marathon restart

ここは、Mesosのマスターノードの設定をしています。ここで、/etc/mesos-master/hostname/etc/mesos-masterに、IPアドレスを記述していますが、これは、DNSでホスト名が引けないような環境だとこの設定が必要になります。

curl -sSfL http://downloads.mesosphere.io/chronos/chronos-2.1.0_mesos-0.14.0-rc4.tgz --output chronos.tgz

tar xzf chronos.tgz

echo -e "description \"Chronos scheduler for Mesos\"\n\nstart on runlevel [2345]\nstop on runlevel[!2345]\n\nrespawn\nrespawn limit 10 5\n\nscript\ncd /home/vagrant/chronos;./bin/start-chronos.bash --master `cat /etc/mesos/zk` --zk_hosts `cat /etc/mesos/zk` --http_port 8081 >> /var/log/mesos/chronos.log 2>&1\nend script\n" | sudo tee /etc/init/chronos.conf

最後は、Chronosのインストールと設定です。 chronos自体は、/home/vagrant/chronosに展開されていますが、chronosの起動を自動化するために、/etc/init/chronos.confに自動起動スクリプトを作成しています。詳しくはUbuntu サービス/ジョブの管理をご参照ください。

これらの手順を自動化して、3台分実行しています。


2. Slaveの設定

Slaveも同じような感じなのですが、mesosのslaveが起動されているのと、Dockerがインストールされて、Mesos-Dockerの設定がなされていることです。これによって、Mesosのコマンド発行で、Dockerが使えるようになります。

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E56151BF

export DISTRO=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
export CODENAME=$(lsb_release -cs)

echo "deb http://repos.mesosphere.io/${DISTRO} ${CODENAME} main" | \
sudo tee /etc/apt/sources.list.d/mesosphere.list

sudo apt-get update
sudo apt-get -y install mesos

sudo service zookeeper stop
sudo sh -c "echo manual > /etc/init/zookeeper.override"

echo -e "zk://192.168.33.10:2181,192.168.33.11:2181,192.168.33.12:2181/mesos" | sudo tee /etc/mesos/zk

sudo service mesos-master stop
sudo sh -c "echo manual > /etc/init/mesos-master.override"

sudo service mesos-slave restart

sudo apt-get update
sudo apt-get install wget
wget -qO- https://get.docker.com/ | sudo sh

echo 'docker,mesos' | sudo tee /etc/mesos-slave/containerizers
echo '5mins' | sudo tee /etc/mesos-slave/executor_registration_timeout
echo $HOST_IP_ADDRESS | sudo tee /etc/mesos-slave/hostname
echo $HOST_IP_ADDRESS | sudo tee /etc/mesos-slave/ip

sudo service mesos-slave restart


Mesosを試してみる

インストールをしたら早速Mesosを試してみましょう。


1. Chronosからタスクを実行してみる

簡単なタスクをChronosから実行してみましょう。いづれかのMasterでChronosを実行します。

クラスタ構成された3台のマスターのなかで、実際に使えるのは一台です。

注意ポイントとしては、chronosでジョブを発行しても、なぜか動かないケースがあります。どうやら、Mesosのリーダーノードにある、chronosでないとうまく動かない感じがします。その場合、Mesosリーダーノードではない、chronosを停止してあげるとうまくいきます。

Mesosのリーダーノードを探すのは簡単で、master_01のhttp://192.168.33.10:5050をブラウザでオープンします。しばらく待っているとリダイレクトされます。もし、リダイレクトされなければ、そのノードがリーダーノードです。尚リーダーノードというのは、Mesosの3台のマスターのなかから自動で選定される代表的なノードのことです。

Mesos管理画面

次に、リーダノードがわかったら、それではない、ノードのChronosを停止させましょう。例えば、master_01のchronosを止めたい場合は、次の通りです。

$ vagrant ssh master_01

vagrant@vagrant-ubuntu-trusty-64:~$ sudo initctl stop chronos

では、お試しで、Chronosから、簡単なタスクを実行させましょう。「+ New Job」ボタンを押してください。もし、ここで、このボタンを押しても何も起こらないようでしたら、他のMasterのサーバーのChronosを開いてください。私の環境の場合はhttp://192.168.33.10:8081のものが有効でした。注:スクリーンショットでは192.168.33.10が有効なのですが、実際のリーダーノードが192.168.33.11だったので、この有効だった192.168.33.10のChronosを上記手順で停止させて192.168.33.11のものが有効になるように途中で変更しました。ややこしくてすみません。

Chronosトップ画面

Screen Shot 2015-05-12 at 20.38.43.png

設定する項目は次のような感じです。

NAME    : Sleep Task      

COMMAND : sleep 120
OWNERS : (xxx@xxx.com)
SCHEDULE: R0/2015-05-12T13:01:30.000Z/PT2M

NAMEはタスク名、COMMANDは、スレーブで実行されるコマンド、OWNERSにはE-Mailアドレスを入れます。タスクが実行されたら通知される先みたいですが、Vagrant環境なので、なんでもいいでしょう。SCHEDULEですが、ここだけ、ポイントがあります。ここで指定される日時に、タスクが何回か繰り返されて実行されるのですが、時間が、日本時間になっておらず、UTCになります。UTCについてはUTC協定世界時とGMTグリニッジ標準時の違いをご参照ください。ですので、時差を考えて時間を設定してください。

 普通に「New Job」ボタンを押すと現在時が入るのでそれを参考にして設定してみてください。R0の0が繰り返し回数です。PT2Mの部分は、繰り返しの時間です。この場合、2分後に2回目が実行されるという感じです。Createボタンを押して、タスクを作成すると、図のようになります。

 

 

 しばらくするとタスクが実行されます。

Screen Shot 2015-05-12 at 21.55.01.png

 

 

 Mesosの画面の方からも見てみると、タスクが現在処理中から、、、

Screen Shot 2015-05-12 at 21.56.14.png

 

 処理済みになっているのがわかります。そして、2台のスレーブのどちらかで実行されています。

Screen Shot 2015-05-12 at 21.57.54.png

Screen Shot 2015-05-12 at 21.58.01.png

Screen Shot 2015-05-12 at 21.58.53.png

 

 実行結果のログも見ることができています。

Screen Shot 2015-05-12 at 21.59.04.png

Screen Shot 2015-05-12 at 21.59.36.png


2. ChronosからDockerのタスクを実行してみる

 次ですが、同じノリで折角スレーブにインストールしたDockerでコマンドを実行してみましょう。これは、リポジトリに入れておいたDocker.jsonを使っていただければいいと思います。タスク名のところと、スケジュールのところだけ、皆さんの環境に合わせてください。

Docker.json

{

"schedule": "R\/2015-05-12T06:29:00Z\/PT2M",

"name": "dockerjobs3",
"container": {
"type": "DOCKER",
"image": "libmesos/ubuntu"
},
"cpus": "0.5",
"mem": "512",
"uris": [],
"command": "date -u +%T"
}

実行はこんな感じでコマンドラインから行います。chronosが実行されているIPアドレスに変えて試してください。

$ curl -L -H "Content-Type: application/json" -X POST -d@Docker.json http://192.168.33.11:8081/scheduler/iso8601

単純ですが、Docker上でのコマンド実行も成功しました。


3. Marathonから常時起動させるインスタンスを起動させる

さて、Marathonも、どうやら、Mesosのリーダーノードで動いているもののみが有効なようです。次のコマンドで、リーダーノード以外のMarathonを停止させてみましょう。どうやら、Mesosの画面で、Frameworksというところにある、Active Frameworksには1つしかChronosやMarathonが登録されないので、そこで認識されたものだけが有効なようです。

$ vagrant ssh master_01

vagrant@vagrant-ubuntu-trusty-64:~$ sudo initctl stop marathon

これは、すべて画面から操作できるチュートリアルになっています。まず、「+ New App」ボタンを押しましょう。http://192.168.33.11:8080などで起動します。

Screen Shot 2015-05-12 at 22.39.51.png

Screen Shot 2015-05-12 at 22.49.50.png

次のような画面がでてきますので

IDに適当な名前をつけて、 Commandには次のコマンドをいれてください。これは簡易的なWebサイトで、正月休みだし Mesos 触ってみたの内容をそのまま使わせてもらっています。本当にこのブログは素晴らしい。

while true; do ( echo "HTTP/1.0 200 Ok"; echo; echo "Hello World" ) | nc -l $PORT; done

さて、Createを押すとサーバーにデプロイされます。

Screen Shot 2015-05-12 at 22.56.12.png

Screen Shot 2015-05-12 at 22.56.21.png

さらに、インスタンス数を増やしてみましょう。IDをクリックすると次の画面になりますので、Scaleボタンを押します。スクリーンショットはインスタンスを2にしていますが、実際は6ぐらいにしてみました。

Screen Shot 2015-05-12 at 22.56.37.png

Screen Shot 2015-05-12 at 22.57.00.png

スレーブの両方に分散されてサービスが起動しているのがわかります。COMMANDの部分で$PORTにしていたポート番号が自動的に振られています。

Screen Shot 2015-05-12 at 22.57.43.png

Screen Shot 2015-05-12 at 22.58.06.png

実際にスレーブにアクセスしてみますと、無事サービスが起動したことがわかりました。

ちなみに、Marathon経由でDockerをぶちかますサンプルもここにあります Launching a Docker Container on Mesosphere

では、よいクラスタ環境を!


参考URL

参考になったURLを貼っておきます!

How to run Chronos on Apache Mesos

Launching a Docker Container on Mesosphere

Setting up a Mesosphere Cluster

正月休みだし Mesos 触ってみた

mesos / chronos (GitHub)

Build Mesos Multi-node HA Cluster

Mesosphere チュートリアル02:Mesosphere Chronos検証 #mesos

ZooKeeper Getting Started Guide

15 Practical Examples of ‘echo’ command in Linux

How to insert text into a root-owned file using sudo? [duplicate]

Vagrant Shell Provisioner

Mesos Getting Started

SETLOCALE

環境変数LC_ALLは未定義のほうがよい?ロケール用環境変数について

http://www.server-world.info/query?os=Ubuntu_14.04&p=initial_conf&f=4

Upstart is not seeing my new script

aptコマンド

管理が困難―分散処理の常識はZooKeeperで変わる