Edited at

Docker swarmモードを試してみた

More than 1 year has passed since last update.


最初に

ホントはRaft Distributed Consensus Alrogithm/Protocolを使っているようなのでマネージャーが3台より多くあると障害にも強いクラスタになるようですが今回はそんなこと考えないです。

気になった方はetcd総選挙を眺めてみるを読むと良いかもしれないです。(すごい参考になりました)

この辺めっちゃ参考にしてます。

https://docs.docker.com/engine/swarm/


実行環境

node
役割

node-01
worker兼マネージャー

node-02
worker

ターミナル1はnode-01のコマンド実行用にする


ターミナル1

$ docker-machine create -d virtualbox node-01

$ eval $(docker-machine env node-01)

ターミナル2はnode-02のコマンド実行用にする


ターミナル2

$ docker-machine create -d virtualbox node-02

$ eval $(docker-machine env node-02)


初期化

まずはマネージャーの初期化


ターミナル1

$ docker swarm init --advertise-addr $(docker-machine ip node-01)

Swarm initialized: current node (61p7kfvmw4m4nbfz3vodgc2y6) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join \
--token SWMTKN-1-0ue65cw4x1k6j2hys2n6hgzpqy0ckv8du7v88e6drkoylh1snm-d7uhyzmofmli2mxa9n93jwepd \
192.168.99.100:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.


上記を実行するとworkerを参加させるためのtoken付きのコマンドが発行される

このコマンドをworkerにしようと思っているnode-02で実行するとクラスタに参加できる

参加する前に現状のクラスタの状態を確認しておく


ターミナル1

$ docker node ls

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
61p7kfvmw4m4nbfz3vodgc2y6 * node-01 Ready Active Leader

tokenの確認は下記のコマンドでもできる


ターミナル1

$ docker swarm join-token worker

To add a worker to this swarm, run the following command:

docker swarm join \
--token SWMTKN-1-0ue65cw4x1k6j2hys2n6hgzpqy0ckv8du7v88e6drkoylh1snm-d7uhyzmofmli2mxa9n93jwepd \
192.168.99.100:2377


マネージャーとしてクラスタに参加させたい場合は docker swarm join-token manager を実行するとマネージャーとして参加させるためのtokenが見れる

node-02をworkerとして参加させて見る


ターミナル2

$ docker swarm join \

--token SWMTKN-1-0ue65cw4x1k6j2hys2n6hgzpqy0ckv8du7v88e6drkoylh1snm-d7uhyzmofmli2mxa9n93jwepd \
192.168.99.100:2377

This node joined a swarm as a worker.


クラスタの状態を確認する


ターミナル1

$ docker node ls

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
61p7kfvmw4m4nbfz3vodgc2y6 * node-01 Ready Active Leader
cu9p6rego36d4hhtn2653bacj node-02 Ready Active

ちなみにworker側で状態の確認などはできない


ターミナル2

$ docker node ls

Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.


サービスの作成

redisサービスを生成する

(TODO: redisのクラスタが生成できるかもしれないが調査できていないためreplicasは1にしている)


ターミナル1

$docker service create --replicas 1 --name redis -p 6379:6379 redis:3.2.0-alpine

7vurzloshshm2wn5vezxuexku

サービスの確認を連打していたらREPLICASが1/1になるのが確認できる


ターミナル1

$ docker service ls

ID NAME REPLICAS IMAGE COMMAND
ac3iz5deljd1 redis 0/1 redis:3.2.0-alpine
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
ac3iz5deljd1 redis 1/1 redis:3.2.0-alpine


ターミナル1

$ docker service ps redis

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
25g7igyki966vlljtv9lktywx redis.1 redis:3.2.0-alpine node-01 Running Preparing 7 seconds ago

実際にどちらのnodeからでも接続できるか確認する

ついでにnode-01でfooにbarをセットしてnode-02で確認できるかも見ておく


ターミナル1

$ redis-cli -h $(docker-machine ip node-01)

192.168.99.100:6379> set foo bar
OK
192.168.99.100:6379> get foo
"bar"
192.168.99.100:6379> exit

$ redis-cli -h $(docker-machine ip node-02)
192.168.99.101:6379> get foo
"bar"
192.168.99.101:6379> exit



サービスのスケールアップ・スケールダウン、そして自動復旧について

redisのコンテナ数を2つに増やすには下記のscaleコマンドを実行します


ターミナル1

$ docker service scale redis=2

redis scaled to 2

$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
25g7igyki966vlljtv9lktywx redis.1 redis:3.2.0-alpine node-01 Running Running 27 minutes ago
73f8jbhknsqu2xo4czq3ng7r0 redis.2 redis:3.2.0-alpine node-02 Running Running less than a second ago

$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
ac3iz5deljd1 redis 2/2 redis:3.2.0-alpine


上記のようにかんたんにスケールアップできますが、自動的に負荷分散されるのでredis等の場合にはコンテナ側でクラスタ化しないと値のセットして参照したら見れないことになる可能性があるので1つに戻しておきます。


ターミナル1

$ docker service scale redis=1

redis scaled to 1

$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
25g7igyki966vlljtv9lktywx redis.1 redis:3.2.0-alpine node-01 Running Running 32 minutes ago
73f8jbhknsqu2xo4czq3ng7r0 redis.2 redis:3.2.0-alpine node-02 Shutdown Shutdown 3 seconds ago

$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
ac3iz5deljd1 redis 1/1 redis:3.2.0-alpine


上のreplicasの数を減らした場合コンテナは削除されずただストップする形になるので何度も試してるとゴミが残ることになります。


ターミナル2

$ docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a18235283c81 redis:3.2.0-alpine "docker-entrypoint.sh" 6 minutes ago Exited (0) About a minute ago redis.2.73f8jbhknsqu2xo4czq3ng7r0

そして消されるコンテナは古い順ではなくNAMEに書かれてる数値が大きいものから削除されるようです(要検証)

20ぐらいまで増やして1つに絞ってみたらredis.13が生き残ったったのでランダムっぽいです

dcjg438wipqsw6lsi0vw67f5a  redis.11     redis:3.2.0-alpine  node-01  Shutdown       Shutdown about a minute ago

09a4j1fwxb91tkqioz4bti3sz redis.12 redis:3.2.0-alpine node-01 Shutdown Shutdown 3 seconds ago
064hpn2v6jwpy0p8kbpryzwn7 redis.13 redis:3.2.0-alpine node-01 Running Running 3 minutes ago
8lu1d4qwtyb1wz050fjccnbtm redis.14 redis:3.2.0-alpine node-01 Shutdown Shutdown about a minute ago
c9740i08ndi7dte16wsri9ev0 redis.15 redis:3.2.0-alpine node-01 Shutdown Shutdown about a minute ago
099mt2ha487pafhufc37hiutv redis.16 redis:3.2.0-alpine node-02 Shutdown Shutdown 3 seconds ago

docker stop等によってコンテナが眠ってしまった場合自動的にreplicasの数になるように実行されます。

↑この機能を利用していい感じにコンテナの差し替えができるのでは無いかと思ったりもしている


ローリング・アップデート

下記の設定をするだけでローリングアップデートできます。

  --update-delay

--update-parallelism

5秒待ち1コンテナずつ更新かける場合は下記のコマンドになる。


ターミナル1

$ docker service update --update-delay 5s --update-parallelism 1 --image redis:3.2.5-alpine redis

redis

scaleをとりあえず20にして試した結果

840x553ujrfghnbqhqi9s0zx5  redis.7       redis:3.2.5-alpine  node-02  Running        Running 55 seconds ago

3qoj8jpmcfj1ji20aa2hgx1by \_ redis.7 redis:3.2.0-alpine node-01 Shutdown Shutdown 58 seconds ago
844vrpbzjs29q9kua2b3n9r3p \_ redis.7 redis:3.2.0-alpine node-01 Shutdown Shutdown 17 minutes ago
db6k0he84jv9xp0az3r8sqd4z redis.8 redis:3.2.0-alpine node-01 Running Running 3 minutes ago
31ict01zi3l0spo05a4gjixwi \_ redis.8 redis:3.2.0-alpine node-01 Shutdown Shutdown 16 minutes ago
bssq36i1fq20e5a2a629n83bz redis.9 redis:3.2.0-alpine node-01 Running Running 3 minutes ago
e7sea97hqpd5d1pjaugxb33pv \_ redis.9 redis:3.2.0-alpine node-02 Shutdown Shutdown 17 minutes ago
52e7l8s5ossbq6nndbwfrbxxq redis.10 redis:3.2.5-alpine node-02 Running Running 6 seconds ago
8jozd1yew7vou0g8x458t0t9e \_ redis.10 redis:3.2.0-alpine node-01 Shutdown Shutdown 9 seconds ago
21hlsx81oruek4p8de0ujztxb \_ redis.10 redis:3.2.0-alpine node-01 Shutdown Shutdown 16 minutes ago
03mtra8s2zw2tomwgqsqz4sxa redis.11 redis:3.2.5-alpine node-02 Running Running 25 seconds ago


サービス削除

すごいサービス消したら紐付いてたコンテナ全部消してくれる!


ターミナル1

$ docker service rm nginx

nginx
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES


ターミナル2

$ docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES


まとめ

すげえ


まとめパート2

バックエンドにetcd等を用意しなくて良くなったswarmって感想。

ただファイルでnodeの管理ができないのでつらいかもしれないですが、一度構築したら必要ないので問題無い気がします。

Nginxとかscaleし易いやつで試せって話でした。試そうと思ったときに適当にdockerhubから選んだ僕があれでした。


 おまけ

REPLICASの話をつらつらと書きましたが実はgrobalモードがあります。(やる気が出たら記事に追記なりします)

気になった方は調べてみてください。