正月休みだし1人ハッカソンやろうかなぁと思って、Mesos-Docker でプライベート IaaS っぽいものを構築してみたのでそのメモ。昨日は Mesos を触ったのでその続き。
まえおき
最近流行りの Immutable Infrastructure というアイデアは AWS (EC2) のように手軽にインスタンスを作ったり、消したりできるような IaaS があったからこそ発展して出て来たアイデアだと思っている。気軽にインスタンスを作ったり、消したりできないと、稼働中クラスタ(Blue) から、新しく立ち上げたクラスタ (Green) に、LBの向き先をすげかえることでデプロイとするような Blue-Green Deployment なんて正直やる気も起きないと思う。作ったり消したりするだけで何時間かかるんだ、と。
ということで、まずはプライベート IaaS を作ってみようと思う。昨日 Mesos (+ Marathon) を触ったかんじでは、さらに Mesos-Docker を追加すればできそうなかんじ。Immutable Infrastructure 関係なく、社内 IaaS あったらあったで便利だしね ^^
おさらい
- Mesos はクラスタリソースマネージャで、物理マシン(物理じゃなくてもいいけど)を一杯ならべて1つのクラスタとして管理し、タスクを走らせる時に効率的にリソースの分配をして実行してくれるもの
- Mesos は基本的にはタスクを走らせるときにリソースを割り当てて終わったら解放する動きをするため、ウェブアプリのように常時起動するようなアプリケーションを動かすためには別の仕組みが必要で、それを可能にするのが Marathon
ということがわかった。元々プライベート IaaS が作れるのかな?と思って触った Mesos だけれども、Mesos そのものはもっと用途が広くて、Jenkins のジョブを分散処理させるのに使えたりするということもわかった。
今日は、本来の目的だった プライベート IaaS 構築のために、続けて Mesos-Docker を触ってみる。
Mesos-Docker とは
Marthon でウェブアプリを動かせるようになったけれど、Mesos Slave 上でそのままアプリが動くため、例えば rails アプリを動かそうとおもった場合、どの Mesos Slave に配分されても動くように全ての Mesos Slave なホストに ruby とアプリをインストールしておかないといけないわけで、これが perl アプリ、python アプリ、memcached、nginx のように多岐にわたると辛い思いをすることが想像に難くない。
というわけで、Docker コンテナに環境を隔離して、Docker コンテナとアプリを同時に起動させたいと思うのは当然の発想なわけで、それを実現してくれるのが Mesos-Docker である!!ということらしい。
あとは、1. 稼働中インスタンスを Docker イメージに保存して、2. イメージから複数インスタンスを立ち上げる、なんてことができれば IaaS と呼んでいいんじゃないかな!!
ということで試してみる。
Docker のインストール
Mesos から Docker を動かすにあたって、もちろん Docker が動くようにしておく必要があるので入れておく。CentOS の場合、CentOS 6.5 から対応された、と聞いているのでCentOS 6.5 環境に Docker を入れてみる。CentOS 6.5 に Docker をインストールしてみた - Shin x blog を参考にさせて頂いた。
インストール。epel 入れて yum で入れるだけっぽい。簡単ですねー ^^
試す
おkおk
補足:RHEL6.4やCentOS6.4でDockerを使う | iOSS という記事もあるので、CentOS 6.5 じゃなくても良いっぽいすね。なんだと。。。
Mesos-Docker のインストール
Mesos-Docker の Tutorial に従ってインストール。
Ubuntu 13.04 環境であれば、Mesos, Marathon, Mesos-Docker をまとめて入れてすぐ試せるようなスクリプトを Mesos-Dockerが用意してくれているのでそれで試せるっぽい。これだけ。
ただ、今回は CentOS 環境に Mesos, Marathon を入れているのと、仕組み理解のため手でインストールしたいので、Mesos-Docker だけ別途入れる。Mesos-Docker 自体は python スクリプト一枚にすぎないっぽい。Mesos, Marathon のインストールは昨日の記事参照。
Mesos-Docker スクリプトが python の mesos モジュールを使うらしいのでそれを入れる。まずは easy_install (もとい、distribute) を入れておく.
mesos の src ディレクトリに行って、egg ファイルを指定して easy_install を使って mesos モジュールを入れる
そしたら Mesos-Docker を所定の位置に配置する。スクリプト1枚。
これはついでだけど、Mesos-Docker のサンプルが python な http クライアント httpie を使っているので、一緒にインストールしておこう。curl でも良いとは思うんだけど。
sudo easy_install httpie
Mesos-Docker を試す
昨日触ってた Marathon の Web UI のほうだと、executor (さっき配置した /var/lib/mesos/executors/docker)を指定できないので、REST API を叩いてインスタンスを起動するらしい。Mesos-Docker が python で書かれているということもあって、curl じゃなくて python 製の httpie を推していたので、httpie で REST API を叩いてみる。
Tutorial 通りに johncosta/redis イメージを起動してみる。redis が動くらしい。Docker の動作確認のためにまず単体で動かしてみる. docker pull で時間かかるし。
動いたっぽいので、止めて、Marathon の REST API 経由で Mesos-Docker (/var/lib/mesos/executors/docker) を起動し、Docker イメージを起動してみる。インスタンス2つで、それぞれにメモリ 128MB と CPU 1 コア割り当てている。
http POST http://localhost:8080/v1/apps/start \
id=multidis instances=2 mem=128 cpus=1 \
executor=/var/lib/mesos/executors/docker \
cmd='johncosta/redis'
Marathon の REST API と docker ps で確認。2インスタンスが起動していてそれぞれ 31001 と 31000 ポートが Docker イメージの redis が動いている 6379 ポートにマッピングされていることが確認できる。素晴らしい!!
あと、プロセス見るとこんなかんじで起動しているっぽい。
Mesos + Marathon だけの時とは違って、Mesos Slave を動かしているホストには Redis を入れていないあたりがポイントになるかな。
一応 redis につないで動作確認。Docker インスタンスにしか redis-cli 入れていないので、telnet で動作確認してみる。
できてるっぽい ^^
Docker イメージを作って動かしてみる
Tutorial は終わったので、ちょっと応用ということで、試しに @kazeburo さんがやってたGrowthForecast イメージを作って動かしてみる。
以下の内容のDockerfile を用意して
FROM centos
RUN yum -y groupinstall "Development Tools"
RUN yum -y install pkgconfig glib2-devel gettext libxml2-devel pango-devel cairo-devel git ipa-gothic-fonts
RUN git clone https://github.com/tagomoris/xbuild.git
RUN xbuild/perl-install 5.18.1 /opt/perl-5.18
RUN echo 'export $PATH=/opt/perl-5.18/bin:$PATH' > /etc/profile.d/xbuild-perl.sh
RUN /opt/perl-5.18/bin/cpanm -n GrowthForecast
RUN mkdir -p /var/lib/growthforecast
EXPOSE 5125
CMD ["/opt/perl-5.18/bin/growthforecast.pl","--data-dir","/var/lib/growthforecast"]
ビルド。kazeburo さんも言ってたけど perl のインストールからやっているので結構待つ。
Docker Repository に push。ここでも 8分ぐらい待つ。
NOTE: push したので、誰でも `docker pull sonots/growthforecast`で GrowthForecast イメージが利用可能ですよ :D
Marathon の REST API を叩いてインスタンスを起動
http POST http://localhost:8080/v1/apps/start \
id=multidis instances=1 mem=128 cpus=1 \
executor=/var/lib/mesos/executors/docker \
cmd='sonots/growthforecast'
今回はお試しなので Public な Docker Repository を使ったけれど、お試しでなければ Docker Private Repository を作ってそこに push すると良いと思う。@hansode 先輩の Private Docker Registryを、あっさりセットアップする | blog.hansode.org あたりが参考になると思う。
Docker イメージを更新してみる
あとは、AWS (EC2) というか一般的な IaaS を思い浮かべると、稼働中インスタンスをイメージに保存したり、それをロードしたりできるわけなので、稼働中インスタンスのイメージを保存できるか試してみた。
普通に考えたら ssh でログインしてイメージをいじる所だけど、イメージ作る時に 22 番ポートを EXPOSE し損なったので、docker run -i /bin/bash 経由で入っててきとうに更新してみる
別の端末から。docker commit するのに CONTAINER_ID とやらが必要らしいので docker ps して確認しておく。
docker commit する。Dockerfile で書いていた EXPOSE とか ENV とかが無効になってしまうらしく、もう1度指定しないといけないっぽい。しかも書式が違う。腐ってる。。。T T
commit を push する。
push された。あとは、再度 Marathon の REST API を叩いてインスタンスを起動すれば良い。
http POST http://localhost:8080/v1/apps/start \
id=multidis instances=2 mem=128 cpus=1 \
executor=/var/lib/mesos/executors/docker \
cmd='sonots/growthforecast'
まとめ
Mesos-Docker を使って、1. 稼働中インスタンスをイメージに保存して、2. イメージから複数インスタンスを立ち上げる、という IaaS の基礎要素を実現できることが確認できた。あとはそれらをボタン1つでサクッとできるようにすれば、プライベート IaaS の出来上がり、ってかんじかな。
もう少しつっこんで、起動と同時に github からソースコードを pull してアプリを動かす、とかできるようにすると、プライベート PaaS も構築できるのかもしれない。オープンソースアプリだけでこういうものを、サクッとは言えなかったけど ^^; 自分で構築できるようになったとは時代も進んだもんですねー :D
まだまだ触ってみたレベルで、Mesos がやってるタスクの分配アルゴリズムや、リソースの利用を制限している仕組みなど、いろいろ良くわかっていなかったりするので、また時間を取って、もう少し深堀りしていきたい。
ぼやき
ただ、Mesos + Marathon + Docker + Mesos-Docker と4つもコンポーネントを組み合わせて作った上に、それぞれが依存をたくさん持っていて正直辛かった。言語も C++, Python, Java, Scala と多岐に渡ってるし 。
そして、virtualbox イメージ作ろうかと思って、1度環境クリーンにして作り直したら Mesos-Docker が動かなくなったというのはまた別の話。。。腐ってる。。。もう1日正月休みがあれば深堀り出来たと思うんだけど、無念><
以上、@sonotsでした。
追記: @riywo さんに教えてもらった。Vagrant で立ち上げるとデフォルト CPU 1 なので、Marathon にinstances=2 cpus=1 と指定するとコア数が足りなくて2つ目のインスタンスが立ち上がらない、ということだった。ログに ERROR でないとかマジ泣けるT T だから virtualbox 作ろうとしたらおかしくなったのか。Vagrantfile で
config.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--cpus", "4"]
vb.customize ["modifyvm", :id, "--memory", "1024"]
end
のように CPU コア数を MBA のコア数 4 に指定したところうまくいくようになった。riywo++