瞬殺で作る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台のマスターのなかから自動で選定される代表的なノードのことです。
次に、リーダノードがわかったら、それではない、ノードの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
のものが有効になるように途中で変更しました。ややこしくてすみません。
設定する項目は次のような感じです。
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ボタンを押して、タスクを作成すると、図のようになります。
しばらくするとタスクが実行されます。
Mesosの画面の方からも見てみると、タスクが現在処理中から、、、
処理済みになっているのがわかります。そして、2台のスレーブのどちらかで実行されています。
実行結果のログも見ることができています。
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
などで起動します。
次のような画面がでてきますので
IDに適当な名前をつけて、 Commandには次のコマンドをいれてください。これは簡易的なWebサイトで、正月休みだし Mesos 触ってみたの内容をそのまま使わせてもらっています。本当にこのブログは素晴らしい。
while true; do ( echo "HTTP/1.0 200 Ok"; echo; echo "Hello World" ) | nc -l $PORT; done
さて、Createを押すとサーバーにデプロイされます。
さらに、インスタンス数を増やしてみましょう。IDをクリックすると次の画面になりますので、Scaleボタンを押します。スクリーンショットはインスタンスを2にしていますが、実際は6ぐらいにしてみました。
スレーブの両方に分散されてサービスが起動しているのがわかります。COMMANDの部分で$PORTにしていたポート番号が自動的に振られています。
実際にスレーブにアクセスしてみますと、無事サービスが起動したことがわかりました。
ちなみに、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
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]
環境変数LC_ALLは未定義のほうがよい?ロケール用環境変数について
http://www.server-world.info/query?os=Ubuntu_14.04&p=initial_conf&f=4