CoreOSクラスタ内のDockerコンテナの動的リンク
Dynamic Docker links with an ambassador powered by etcd
CoreOSのクラスタ内で複数ホスト間にまたがりDockerコンテナを連携させる方法について検証した.
複数ホストにまたがりDockerのコンテナを接続する方法としてはAmbassador パターンが有名である.これはトラフィックを別ホストへforwardすることに特化したコンテナを立てる方法で,ホストに無駄な設定なし,かつDockerコンテナのみで行えるシンプルな方法である.例えば,あるホストからredis-cli
を使って,別ホストで動くredis
に接続する場合は以下のように接続する.
1
|
|
redis-cli
コンテナとambassador
コンテナ,redis
コンテナとambassador
コンテナはdockerのlink機能で接続し,ambassador
コンテナはトラフィックをネットワーク越しにフォワードする.
この方法は,接続側がその相手先のホストを知っている必要がある.例えば上記の場合,redis-cli
コンテナ側のambassador
コンテナは以下のように相手先のホストのIP(e.g., 192.168.1.52
)を指定して起動しなければならない.
1
|
|
ホストが固定されている場合は問題ないが,CoreOSのように動的にホストが変わる可能性がある場合は問題になる.
CoreOSはクラスタの形成に分散Key-Valueストアであるetcdを使っている.そこに接続先のホスト情報を保存し続けることで,この問題を解決することができる.
想定する接続の例
Link via an Ambassador Containerと同様の例を用いる.クラスタ内のあるホストよりredis-cli
コンテナを使って,別ホストのredis
コンテナに接続する.
コンテナ
全部で5つのコンテナを用いる.
https://coreos.com/assets/images/media/etcd-ambassador-hosts.png
HostA (redis
を動かすホスト)
- crosbymichael/redis - Ambassador パターンで使われているものと同様のRedisコンテナ
- polvi/simple-amb -
socat
コマンドを使って,特定のポート(10000)のトラフィックを与えられたホストにforwardするだけのコンテナ.etcdへのフォーワードに利用する. - polvi/docker-register -
docker port
コマンドを使って与えられたDockerコンテナのIPとPortを取得し,etcdにそれを登録するコンテナ
HostB (redis-cli
を動かすホスト)
- polvi/simple-amb - HostAと同様のコンテナ.etcdへのフォーワードに利用する.
- polvi/dynamic-etcd-amb - etcdからRedisコンテナのホストとIPを取得し,環境変数にそれを設定するコンテナ.複数ホストが得られたらラウンドロビンする.
- relateiq/redis-cli - Ambassador パターンで使われているものと同様のコンテナ
Unitファイル
CoreOSはコンテナの管理とスケジューリングにFleetを用い,その設定はsystemdにFleet特有の設定を加えたUnitファイルで行う(詳しくは,“Fleetの使い方,Unitファイルの書き方”に書いた).
上述したDockerを起動するためのUnitファイルについて簡単に説明する.
HostA
crosbymichael/redisを動かすためのredis.service
は以下.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
単純にredis
コンテナを起動するだけ.polvi/docker-registerを使って,ホストのIPとPortをetcdに登録する必要があるので,-p ${COREOS_PRIVATE_IPV4}::6379
を指定して起動する.CoreOSはそのホスト情報を/etc/environment
に保存しているので,それをそのまま使える.どのホストかを直接指定する必要はない.また,%n
はsystemdのUnitファイルの記法で,そのファイル名が代入される(今回の場合は,redis.service
).
polvi/simple-ambを動かすためのetcd-amb-redis.service
は以下.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
このコンテナは特定のポート(10000)のトラフィックを与えられた引数のホストにforwardする.CoreOSのDockerコンテナからは172.17.42.1:4001
でそのetcdにアクセスできる.引数にそれを与えることで,10000
portへのトラフィックはすべてetcdにforwardされるようになる.
X-ConditionMachineOf
にredis.service
を指定することで,このコンテナは,redis
コンテナと同じホストにスケジューリングされるようになる.
polvi/docker-registerのregister-redis-etcd.service
は以下.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
このコンテナは与えられたコンテナのホストにおけるIPとPortのマッピング情報を取得し,それをetcdに登録する.今回はredis
コンテナの6379
portのホストにおけるIPとPortのマッピング情報をredis-A
という名前でetcdに登録する.polvi/docker-registerとlinkで接続することにより,環境変数でetcd
の接続先を取得する.
X-ConditionMachineOf
にredis.service
を指定することで,このコンテナは,redis
コンテナと同じホストにスケジューリングされるようになる.
HostB
polvi/simple-ambを動かすためのetcd-amb-redis-cli.service
は以下.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
内容はHostAのetcd-amb-redis.service
と同様だが,スケジューリングの条件が異なる.X-Conflicts
にredis.service
を指定することでredis
コンテナとは異なるホストにスケジューリングされるようになる.
polvi/dynamic-etcd-ambのredis-dyn-amb.service
は以下.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
このコンテナはetcdに保存されたホストへのプロキシとして動作する.6379
portを解放し,そこへの接続をredis-A
という名前でetcdに登録されたredis
コンテナが動くIPとPortに向けるようにする.polvi/docker-registerとlinkで接続することにより,環境変数でetcd
の接続先を取得する.
redis-cli
コンテナは,このコンテナと接続することで,ネットワーク越しにredis
コンテナに接続する.
クラスタを立てる
利用するクラスタはtcnksm/vagrant-digitalocean-coreosを使って,VagrantでDigitalOcean上に立てる.使い方は,“CoreOSに入門した | SOTA”を参考.
1 2 |
|
これで,DigitalOcean上に3つのCoreOSインスタンスが立ち上がる.
接続を試す
上述したUnitファイルで定義したサービスをCoreOSクラスタにデプロイしredis
コンテナに接続してみる.
まず,サービスのデプロイする..service
ファイルがあるディレクトリで以下を実行する.
1
|
|
サービスの起動を確認する.Unitファイルで定義したように別々のホストでサービスが起動していることが確認できる.
1 2 3 4 5 6 7 |
|
redis
コンテナに接続するには,etcd-amb-redis-cli
コンテナが動いているホストに移動する必要がある.以下で移動できる.
1
|
|
実際に接続してみる.
1 2 3 |
|
何が起こっているのか
この時何が起こっているのかをそのログで確認してみる.まず,etcdに保存されている情報を確認してみる.
1 2 |
|
Redis-A
にredis.service
が動いているホストとIPが保存されている.
次にregister-redis-etcd.service
のログを見てみる.
1 2 |
|
etcdにホストのIPとPortをポストしているのがわかる.
最後にregister-redis-etcd.service
のログを見てみる.
1 2 |
|
etcdからホストのIPとPortを取得しているのがわかる.
耐障害性の確認
redis
コンテナを再起動してもすぐに設定は更新され再接続できる.これらは,redis
コンテナが動くホスト情報のetcdへの動的な書き込み,読み込みにより実現できている.
また,redis
コンテナが動くホストを,ホストごと殺しても再び接続できる.これは,fleetによるフェイルオーバー(再スケジューリング)とetcdの動的に書き込み・読み込みにより実現できる.
まとめ
CoreOSのクラスタ内で複数ホスト間にまたがりDockerコンテナを連携させる方法について検証した.etcdに接続先のホストを保存することで,コンテナがどのホストで動いているかを意識しないでそれに接続することができた.