はじめに
- docker API をもう少し突っ込んで色々と触ってみたい
- serf を使って全自動インフラを夢見て
必読(参考)
- Docker + Mesos + Marathon + Graphite + Fluentd + Sensuを組み合わせたデプロイ管理ツールの話 [Show on Hatena Bookmark]
- Docker, Mesos, Sensu等を利用したBlue-Green Deploymentの仕組み - $shibayu36->blog;
- Docker コンテナにアプリケーションを立てて Graphite でいい感じに可視化するまで - wtatsuru's blog
Mesos
や Marathon
や Graphite
は初めて聞く単語なのでまたまた調べないといけないことが出てきて焦っている。
docker API について
docker API で docker run -d 的なことを実現する
さて、ここ数日悩んでいたことの一つがコレ。
docker API
でdocker run -d
(デタッチモード)をどのように実現するか
簡単に出来そうな気がしてなかなか出来なかった。ググり続けたら以下のような記事を見つけてさらにガクリ。
同じことで悩んでいらっしゃる方が世界に自分だけではなかったのが嬉しいやら、サクッと出来ない切なさやら色々と残念だったが、この記事のコメントにも書かれているように「単純に create
して start
してみたらどやろ?」というアドバイスを基に試してみたのが以下。
docker API クライアントの python バージョン
ちょっとだけ齧ったことのある ruby
で実装されたクライアントを使って試してみたところ以下の点で期待したように動作しなかった(試し方の問題かもしれない)。
- 任意のポートバインドの指定方法が明確ではない
docker run
と同じ動きしかしない(コマンドを実行してexit 0
で終了する)
ということで python
で実装されたこちらで試してみることにした。
dotcloud
現在では Docker と名前を変えて飛ぶ鳥を落とす勢いかどうかは知らないが Docker
謹製のクライアントなので何か進歩があるのではという期待を持って以下のような簡単なスクリプトを作ってみた。
import docker c = docker.Client(base_url='http://127.0.0.1:4243', version='1.8', timeout=10) containerid = c.create_container('inokappa/wheezy-serf', command='serf agent -join 172.17.42.1:7946', ports=[7946]) c.start (containerid)
ローカルホストで動作する docker
に対して inokappa/wheezy-serf
というベースイメージを基にして serf agent -join 172.17.42.1:7946
というコマンドを実行するコンテナを作成して実行するだけだがまさに自分がやりたかったことに一歩近づいた。以下のように実行すると...
python test.py
以下のように見事にコンテナが実行される。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2e4d73fa036e inokappa/wheezy-serf:latest serf agent -join 172 38 seconds ago Up 38 seconds 7946/tcp stupefied_pike 44dc4959fdcb inokappa/wheezy-serf:latest serf agent -join 172 44 minutes ago Up 44 minutes 7946/tcp sharp_poincare
もちろん、serf
のクラスタ内にも join
されている。
ubuntu1304 172.16.80.60:7946 alive 44dc4959fdcb 172.17.0.29:7946 alive 2e4d73fa036e 172.17.0.31:7946 alive
serf のイベントハンドラで docker API
docker API
を serf
のイベントハンドラから叩ければ夢の全自動インフラが出来そうな気がしたので試してみた。使うの上述の dotcloud / docker-py を使う。実用的か否かはさて置いてクラスタ内のノードの障害を自動で検知してノード内のホストを自動で起動みたいなことをしてみたい。イメージ的には以下のような感じ。
準備
先ほどの pyhon
スクリプトを適当なファイル名で保存。(例:containerup.py)
#!/usr/bin/env python import docker c = docker.Client(base_url='http://127.0.0.1:4243', version='1.8', timeout=10) containerid = c.create_container('inokappa/wheezy-serf', command='serf agent -join 172.17.42.1:7946', ports=[7946]) c.start (containerid)
もちろん、docker-py
等もインストールしておく。
sudo apt-get install python-pip sudo install docker-py
試すのみ
以下のように最初の serf
エージェントを起動する。(※コンテナをホストしているマシンで起動する)
serf agent -event-handler=member-failed=./containerup.py &
次々と ./containerup.py
を実行することで docker API
が叩かれて serf
エージェントが実行するコンテナを起動する。コンテナを立ち上げることに飽きてきたところでおもむろにコンテナを停止する。
docker stop ${コンテナ ID}
そうすると以下のようなメッセージと共に conatainer.py
が実行され(docker API
) が実行されて新しいコンテナが起動して serf
クラスタにジョインしてくる。
2013/12/25 01:44:33 [INFO] agent: Received event: member-failed 2013/12/25 01:44:33 [INFO] Responding to push/pull sync with: 172.17.0.48:48481 2013/12/25 01:44:33 [INFO] serf: EventMemberJoin: 2f1ae635ceef 172.17.0.48 2013/12/25 01:44:34 [INFO] agent: Received event: member-join
serf members
の遷移は以下のような感じ。
~/docker$ serf members ubuntu1304 172.16.80.60:7946 alive ec0fc463a3a9 172.17.0.51:7946 alive eeb3a1657bbc 172.17.0.52:7946 alive ~/docker$ docker stop ec0fc463a3a9 #=> コンテナ停止! ec0fc463a3a9 ~/docker$ serf members ubuntu1304 172.16.80.60:7946 alive ec0fc463a3a9 172.17.0.51:7946 failed #=> 停止したコンテナが failed eeb3a1657bbc 172.17.0.52:7946 alive ~/docker$ serf members ubuntu1304 172.16.80.60:7946 alive ec0fc463a3a9 172.17.0.51:7946 failed eeb3a1657bbc 172.17.0.52:7946 alive 2c75b5019bc1 172.17.0.53:7946 alive #=> でも暫くすると新しいコンテナが join
落としても、落としてもまた新しいコンテナが立ち上がってくる、まさに無限増殖!
最後に
docker
コマンドを叩けないような環境でdocker API
とserf
を用いることで落ちないクラスタを構成出来そうな何かを感じた- 次こそ
docker
コンテナ間だけで試してみたい - 手軽に
docker API
をいじるには各種言語のスキルは必須だなと痛感