ようへいの日々精進XP

よかろうもん

docker API と serf を組み合わせてみた

はじめに

  • docker API をもう少し突っ込んで色々と触ってみたい
  • serf を使って全自動インフラを夢見て

必読(参考)

MesosMarathonGraphite は初めて聞く単語なのでまたまた調べないといけないことが出てきて焦っている。


docker API について

docker API で docker run -d 的なことを実現する

さて、ここ数日悩んでいたことの一つがコレ。

  • docker APIdocker 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 APIserfイベントハンドラから叩ければ夢の全自動インフラが出来そうな気がしたので試してみた。使うの上述の dotcloud / docker-py を使う。実用的か否かはさて置いてクラスタ内のノードの障害を自動で検知してノード内のホストを自動で起動みたいなことをしてみたい。イメージ的には以下のような感じ。

f:id:inokara:20131226065355p:plain

準備

先ほどの 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 APIserf を用いることで落ちないクラスタを構成出来そうな何かを感じた
  • 次こそ docker コンテナ間だけで試してみたい
  • 手軽に docker API をいじるには各種言語のスキルは必須だなと痛感