先日リリースされたDocker 1.13で、swarm mode上でのdocker composeが使えるようになったのでさっそく試しました。
何が嬉しいのか
まず、1.12でdockerにビルトインのswarm modeが追加されました。
その時はクラスタをサクッと作れて嬉しいぞ!と歓喜したものです。
しかし、使ってるとservice作るのがめんどくせえ…、とすぐになりました。
そうです。
docker-composeだと各サービスを宣言的に書けるのですが、これがswarm modeのクラスタを対象としていませんでした。
/(^o^)\ナンテコッタイ
serviceをコンスタントに再現可能にするためには職人によるシェルスクリプトを残すなどの工夫が必要になります。
それはそれでまあ別にいいんですが…。
まあでもツラいです。
そこで1.13ですよ。
docker-composeによる宣言的なサービスオプションの定義をswarm modeのクラスタ上で展開できます。
これで必要な定義をdocker-composeで管理できます。
スクリプトを管理するよりか差分など見やすくなるはずです。
ちょっと用語説明
ざっくりこんな感じ
- スタック: docker-composeで管理するサービスのまとまり
- マネージャノード: クラスタをコントロールするノード。通常だとワーカーノードも兼ねてます。
- ワーカーノード: コンテナを実行するノード。
- サービス: コンテナによって実現されるあるプロセス
- タスク: 動いてるコンテナ
Swarm ModeでDocker Composeを使ってみる
docker-compose.yml
まずはcomposeファイルを用意しましょう。
swarm modeで使うにはスキーマバージョンを3
にする必要があります。
version: '3' # ←コレ
services:
hogehoge:...
公式リファレンスにもバージョン3についての記述があるので読んどくといいです。
基本は2
を3
にすれば動きます。
クラスタ作成
適当にdocker swarm init
とdocker swarm join
で複数ノードのクラスタ構成してください。
以前に書いた記事を参考にしてもいいかも。
今回は以下の構成にしています。
- manager node: 1
- worker node: 3
composeファイル
こんな感じにしました。
公式のRedmineイメージを参考(パクった)にしました。
portainerはswarm modeにも対応したコンテナ管理画面です。
今回はついでに入れてみました。
Redmine2台、MariaDB1台、Fluentdでログ収集コンテナを各ワーカーに1台、Portainerを特定のマネージャノードに1台という構成です。
見てもらえばわかるかもしれませんが、この設定だとFluentdはまともにログ収集してくれないので適当に設定してください。
DBも永続化とか全く考えてないのでそこら辺は適当に設定してください。
version: '3'
services:
redmine:
image: redmine
ports:
- 3000:3000
environment:
- REDMINE_DB_MYSQL=db
- REDMINE_DB_PASSWORD=example
depends_on:
- db
restart: always
deploy:
replicas: 2
placement:
constraints:
- node.role == worker
db:
image: mariadb
environment:
- MYSQL_ROOT_PASSWORD=example
- MYSQL_DATABASE=redmine
restart: always
deploy:
placement:
constraints:
- node.role == worker
logger:
image: fluent/fluentd
deploy:
mode: global
restart: always
portainer_master:
image: portainer/portainer
ports:
- "9000:9000"
privileged: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: -H unix:///var/run/docker.sock
deploy:
mode: global
placement:
constraints:
- node.name == manager-node
docker composeの記述を説明していきます。
deploy
ここがswarm modeで動かす時のキモです。
バージョン3からservice
セクションの下にdeploy
が追加されています。
詳細は公式見ましょう。
よく使うのはここら辺です。
services:
hoge:
deploy:
mode: global
replicas: 10
placement:
constraints:
- node.role == worker
update_config:
parallelism:
-
mode
:-
global
いわゆるサイドカーと言うやつです。 -
replicated
普通のクラスタ内のノードにデプロイされるやつ。指定しないとコレ
-
-
placement
-
constraints
docker service createの時に指定できるタスクを実行させるノードを制限するオプション- workerノードでだけ動かしたいとか、ノードのラベル別に実行するタスクを分けたいとかの時に使うのでわりと使います
-
-
update_config
docker service createとかで指定するオプションと同じです。-
parallelism
デプロイ済みのスタックをUpdateするときに同時に何個ずつ実行するか
-
その他、restart_policy
とかresources
とかlabel
があります。
デプロイする
$ docker stack deploy redmine --compose-file docker-compose.yml
これでいけます。
実行してしばらくしたら全部起動すると思うので、確認してみましょう。
redmine
がスタック名です。
stack list
$ docker stack ls
NAME SERVICES
redmine 4
service list
$ docker service list
ID NAME MODE REPLICAS IMAGE
0hvtsyxf9w0u redmine_db replicated 1/1 mariadb:latest
5ms7e2obo0rt redmine_logger global 4/4 fluent/fluentd:latest
fqqumdfkrhmn redmine_portainer_master global 1/1 portainer/portainer:latest
uem99z2hr2km redmine_redmine replicated 2/2 redmine:latest
こっちのコマンドでも結果は同じです。
$ docker stack services redmine
ID NAME MODE REPLICAS IMAGE
0hvtsyxf9w0u redmine_db replicated 1/1 mariadb:latest
5ms7e2obo0rt redmine_logger global 4/4 fluent/fluentd:latest
fqqumdfkrhmn redmine_portainer_master global 1/1 portainer/portainer:latest
uem99z2hr2km redmine_redmine replicated 2/2 redmine:latest
stack ps
ここまで来るとどのノードでどのコンテナが動いてるのか気になるのが人情ってもんです。
docker stack ps redmine
これだとUpdateとか失敗を繰り返してるとわけのわからないことになるのでフィルターをしましょう。
$ docker stack ps redmine --filter desired-state=Running
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
aylrotce96e7 redmine_portainer_master.xkugj8va2mj7zvhy0h4405ken portainer/portainer:latest instance-group-1-1f68 Running Running 49 minutes ago
jf0v0z827qy3 redmine_logger.xkugj8va2mj7zvhy0h4405ken fluent/fluentd:latest instance-group-1-1f68 Running Running about an hour ago
iadivx4e7m7x redmine_logger.nc1inf0awkwscvqt3s4plvjy6 fluent/fluentd:latest instance-group-1-c6k3 Running Running about an hour ago
imata0rft454 redmine_logger.v9h0jiug1yxrm4jc2b2sxua7e fluent/fluentd:latest instance-group-1-x511 Running Running about an hour ago
kgyuz26ptxim redmine_logger.l73tho1n0stdz5swgu76n3dlp fluent/fluentd:latest instance-group-1-vt0t Running Running about an hour ago
w7idyw298gz3 redmine_redmine.1 redmine:latest instance-group-1-vt0t Running Running about an hour ago
kutu765y02xc redmine_db.1 mariadb:latest instance-group-1-c6k3 Running Running about an hour ago
u7xmk4ouxku8 redmine_redmine.2 redmine:latest instance-group-1-vt0t Running Running about an hour ago
これで稼働中のコンテナとどこのノードで動いてるのかが見れます。
Portainer
ちなみに、ブラウザで確認したい場合は、今回はportainerを動かしてるのでこちらでも見れます。
http://{manager node}:9000/
Swarmのノード一覧見たり
サービスのリストを見たり、この画面でスケールさせたりできます。
サービスの詳細も見れます。
Environment variablesとかLabelsとかはこの画面でもいじくれます。
Update Configの値もここでいじくれますね。
下の方にタスクのリストがあるんですが、Runningのやつだけ出したりフィルタできないのでちょっと不便。
サービスの内容を変更する
再度stack deploy
すればUpdateされます。
まとめ
そんなわけで、1.13からはComposeで定義してそれを使ってサクッとクラスタ上でコンテナを動かせるようになりました。
ワンタイムのコンテナバッチの実行とかはSwarm Modeが対応してないのでまだできませんが、たしかIssuesあがってたと思うのでそのうちできるようになるかな、と思います。
やったね!