docker swarm 1.12.xのmanager1台/worker1台構成でクラスタ手動フェールオーバ/フェールバックして再起動する手順

# はじめに

先日swarm manager1台/worker1台の構成で、おもむろにmanagerノードのOS再起動したらクラスタがぶっ壊れて悲しい思いをしたので、ちゃんとswarmクラスタのメンテナンス手順を調べました。

クラスタ運用する場合はスプリットブレインを避けるためにmanagerノードを3台以上立てるのが理想的ではありますが、開発環境などではそこまでリソースを割けないのでmanager1台運用にしてます。で、おもむろにmanagerを止めるとクラスタが壊れるので、安全にやるには一旦workerをmanagerに昇格してフェールオーバさせて、managerノードを再起動し、フェールバックさせるという手順を踏む必要があります。

# 前提となる構成
docker swarmは現在アクティブに開発されているので、バージョンによってコマンドやオプションが変わる可能性があります。
稼働確認したdockerバージョンは以下のとおりです。

```
$ docker version
Client:
 Version:      1.12.3
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   6b644ec
 Built:        Wed Oct 26 21:49:51 2016
 OS/Arch:      linux/amd64
 Experimental: true

Server:
 Version:      1.12.3
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   6b644ec
 Built:        Wed Oct 26 21:49:51 2016
 OS/Arch:      linux/amd64
 Experimental: true

```


manager1台でworker1台構成

```
$ docker node ls
ID                           HOSTNAME                          STATUS  AVAILABILITY  MANAGER STATUS
8whfywtdhji3dthpn8v0aymjx    swarm-worker-i-058bd84d2dd57b5d2  Ready   Active
codakltgk6yjnjoscffa8yh94 *  swarm-manager                     Ready   Active        Leader
```

# フェールオーバ
`docker node promote (workerノードID)` でworkerをmanagerに昇格します。

```
$ docker node promote 8whfywtdhji3dthpn8v0aymjx
Node 8whfywtdhji3dthpn8v0aymjx promoted to a manager in the swarm.

$ docker node ls
ID                           HOSTNAME                          STATUS  AVAILABILITY  MANAGER STATUS
8whfywtdhji3dthpn8v0aymjx    swarm-worker-i-058bd84d2dd57b5d2  Ready   Active        Reachable
codakltgk6yjnjoscffa8yh94 *  swarm-manager                     Ready   Active        Leader
```

`docker node update --availability drain (managerノードID)` で起動中のコンテナを他のノードに寄せます。

```
$ docker node update --availability drain codakltgk6yjnjoscffa8yh94
codakltgk6yjnjoscffa8yh94

$ docker node ls
ID                           HOSTNAME                          STATUS  AVAILABILITY  MANAGER STATUS
8whfywtdhji3dthpn8v0aymjx    swarm-worker-i-058bd84d2dd57b5d2  Ready   Active        Reachable
codakltgk6yjnjoscffa8yh94 *  swarm-manager                     Ready   Drain         Leader
```

ちなみにAVAILABILITYにpauseというのもありますが、新規のコンテナを振り分けなくなるだけで、pauseでは既存のコンテナは移動しないようです。

起動中のコンテナがいなくなるまで待ちます。

```
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

# メンテナンス実施
OS再起動などメンテナンスを実施します。

```
$ sudo shutdown -r -h now
```

# フェールバック
`docker node update --availability active (managerノードID)` でnodeのAVAILABILITYをactiveに戻します

```
$ docker node update --availability active codakltgk6yjnjoscffa8yh94
codakltgk6yjnjoscffa8yh94
$ docker node ls
ID                           HOSTNAME                          STATUS  AVAILABILITY  MANAGER STATUS
8whfywtdhji3dthpn8v0aymjx    swarm-worker-i-058bd84d2dd57b5d2  Ready   Active        Leader
codakltgk6yjnjoscffa8yh94 *  swarm-manager                     Ready   Active        Reachable
```

`docker node demote (workerノードID)` で一時的にmanagerに昇格していたノードをworkerに降格します

```
$ docker node demote 8whfywtdhji3dthpn8v0aymjx
Manager 8whfywtdhji3dthpn8v0aymjx demoted in the swarm.

$ docker node ls
ID                           HOSTNAME                          STATUS  AVAILABILITY  MANAGER STATUS
8whfywtdhji3dthpn8v0aymjx    swarm-worker-i-058bd84d2dd57b5d2  Ready   Active
codakltgk6yjnjoscffa8yh94 *  swarm-manager                     Ready   Active        Leader
```

以上。

負荷をリバランスしたい場合は、現状コンテナを個別に再起動するしかなさそうです。

# まとめ
swarm managerが1台しかなくても安全にフェールオーバ/フェールバックしてメンテナンスが実施できるようになりました。
これでクラスタがぶっ壊れて泣きながら再構築しなくても済むはず。dockerのバグを踏まなければね。。。