docker containerに対して直接ansibleを実行する

注釈

まだ試作段階ということをご承知おきください。ツッコミ大歓迎です。

dockerのイメージを構築するにはDockerfileを使って構築します。しかし、 Dockerfileはほぼ単なるshell scriptなのでいろいろと書きにくいという問題 があります。そのため、packerを使ってイメージを構築する手段が取られたり します。が、packerのansible provisionerはansible-pullを内部で実行すると いう形式のため、ansible実行環境やgitをイメージの中に入れる必要がありま す。

また、起動しているコンテナに対してコマンドを実行するためにはsshで入る必 要があります。これはつまり、sshdを入れてsshのポートをexposeする必要があ り、なおかつ動的に変わるdockerの外側sshポートを把握する必要があります。

これらの問題点を解決するために、ansibleが直接dockerコンテナとやりとりを するプラグインを作成しました。(注: ansibleはssh以外も使え、さらに その部分はプラグイン構造になっていて任意に追加できるのです)

dockerに対してlxcでアクセス

docker 0.9.0からlibcontainerというライブラリが入り、dockerはLXCに依存す る必要はなくなりました。しかし、現時点ではdockerは通常はLXCを使用してい ると思います。そのため、今回のプラグインはLXCを使ってアクセスします。

前提

  • docker 0.9.1

  • lxcを入れること

  • linux 3.8以上

  • imageにはpython2が入っていること (ansibleはpython3に非対応。残念)

  • /usr/bin/tee がimageにあること (/bin/teeじゃないです)

準備

  1. docker -e lxc でlxcドライバーで立ち上げておきます

  2. docker run でコンテナを起動しておきます

  3. このgist からファイルを2つ取得し、配置します

    • docker_connection.py はinventoryファイルの置き場に。 chmod ugo+x して実行権限を付けておく

    • docker_inventory.py は connection_plugins というディレクトリの下におく

    結果としてこんな構成になります。

    |- docker_inventory.py
    |- connection_plugins
    |  |
    |  +- docker_connection.py
    +- なにか.yml
    

実行

通常のansible実行と異なる点は、inventoryにdocker_inventory.pyを指定することだけです。

% ansible-playbook -i docker_inventory.py  なにか.yml

これにより、 dockerという名前のグループに対して指定したplaybookが実行さ れます。なお、中でホスト側のsudoを呼んでいるため、実行前にsudoを実行し てキャッシュしておく必要があるかもしれません。

ちなみに、sshを介していないため、実行はかなり早いです。

内部詳細

ansibleには libvirtを使ったlxcアクセスのプラグイン がすでに内蔵されている のですが、手元の環境ではvirshからdockerのLXCが見えなかったのと、LXC決め 打ちであればlibvirtを使う必要はないことから、lx-attachを使っています。 というか、このlibvirt_lxc.pyをほぼそのまま使っています。

lxc-attachで任意のコマンドを実行するにはLinux 3.8以上が必要です。

dockerのcontainer IDは docker ps --no-trunc で得ることが出来、この container IDを使ってLXCでコンテナにアクセスできます。

本当はdockerというグループ決め打ちじゃなく、iamge名をグループにしようと したのですが、imageのIDしかinspectでは得られなかったので一旦後回しにし ました。

まとめ

試作ではありますが、起動しているdocker containerに対して直接ansibleを実 行できるプラグインを作成しました。ansible-playbookを実行した後にcommit をすることで、イメージを作成できると思います。

また、生成と実行が早いことから、ansible playbookを作成するときの試行錯誤にも使えると思います。

さらに、 dockerモジュール と組み合わせることにより、 より複雑な動作ができるかもしれません。

最後に、 助言 を頂いた mopemope さんに感謝します。

Comments

comments powered by Disqus