IDCFクラウドのDebian JessieでMulti-Host Docker Networking - Part 2: Docker Swarmクラスタの作成


　[前回](http://qiita.com/masato/items/6a1fa797b6c25d4c5745)構築したDocker1.9のOverlayネットワークに[Docker Swarm](https://docs.docker.com/swarm/)クラスタを作成します。AWSやDigitalOceanなど[Docker Machine](https://docs.docker.com/machine/)の例が多いですが、今回はIDCFクラウド上に[Consul](https://www.consul.io/)を使いシンプルなSwarmクラスタをセットアップしてみます。

## このシリーズ

* [IDCFクラウドのDebian JessieでMulti-Host Docker Networking - Part 1: Overlayネットワークの作成](http://qiita.com/masato/items/6a1fa797b6c25d4c5745)
* [IDCFクラウドのDebian JessieでMulti-Host Docker Networking - Part 2: Docker Swarmクラスタの作成](http://qiita.com/masato/items/a047798e48ccc1e56eb8)
* [IDCFクラウドのDebian JessieでMulti-Host Docker Networking - Part 3: OverlayネットワークとDocker SwarmとDocker ComposeでRethinkDBをスケールさせる](http://qiita.com/masato/items/bd3d50b31f16a00eac47)

## 参考

　以下のサイトを参考にしました。

* [Create a swarm for development](https://docs.docker.com/swarm/install-manual/)
* [Docker cluster swarm with consul](http://blog.tfm.ro/docker-cluster-swarm-with-consul/)
* [docker networkでマルチホストネットワークを試してみた(docker-1.9.0)](http://qiita.com/irotoris/items/8c62b11624319e3f19f4)


## 仮想マシン

　[前回](http://qiita.com/masato/items/6a1fa797b6c25d4c5745)と同じ仮想マシンを使います。`minion-[1-3]`に`Swarm Agent`をインストールします。また`minion-1`には`Swarm Manager`もインストールします。

|Dockerホストのhostname|Dockerホストのeth0| Docker Swarm |
|:--|:--|:--|
|minion-1|10.3.0.101| Swarm Manager/Agent |
|minion-2|10.3.0.102| Swarm Agent |
|minion-3|10.3.0.103| Swarm Agent |


### Dockerデーモンの起動オプション

　`minion-[1-3]`のDockerデーモンはOverlayネットワークの設定に加えて`-H tcp://0.0.0.0:2375`フラグをつけて起動します。これにより`Swarm agent`のリモートAPIをTCPから`Swarm manager`が利用できるようになります。また`-H unix:///var/run/docker.sock`フラグをつけてデフォルトのUNIXソケットも使えるようにします。

```bash:/etc/default/docker
#DOCKER_OPTS="--cluster-store=consul://localhost:8500 --cluster-advertise=eth0:2376"
DOCKER_OPTS="--cluster-store=consul://localhost:8500 --cluster-advertise=eth0:2376 -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"
```

## Swarm Managerコンテナ
 
　`minion-1`のDockerホストに`Swarm Manager`コンテナをインストールします。Swarmは[Dockerイメージ](https://hub.docker.com/_/swarm/)で公開されています。`Swarm Manager`はネットワーク上の他のDockerホストから`-H`フラグをつけてアクセスできるようにポートをマップします。ここではデフォルトの`2375`と区別するために`3333`にしました。

```bash
$ docker pull swarm
$ docker run -d \
  --name swarm-manage \
  -p 3333:2375 \
  swarm \
  manage \
  consul://10.3.0.101:8500/swarm
```

## Swarm Agentコンテナ

### minion-1

　Swarmクラスタへ`join`するために`minion-[1-3]`の各Dockerホストに`Swarm Agent`をインストールします。DockerイメージはManagerもAgentも同じ[Dockerイメージ](https://hub.docker.com/_/swarm/)を使います。最初に`Swarm Manager`と同じ`minion-1`です。

　`--addr`フラグは`Swarm Manager`がアクセスできるIPアドレスを指定します。`minion-1`は`Swarm Manager`と`Swarm Agent`の両方のコンテナを起動しますが、`localhost`ではなくeth0のプライベートIPアドレスを指定します。またSwarmクラスタの情報管理する分散KVSはOverlayネットワーク構築のバックエンドと同じConsulクラスタを使います。

```bash
$ docker run -d \
  swarm \
  join \
  --addr=10.3.0.101:2375 \
  consul://10.3.0.101:8500/swarm
```

　`minion-1`のDockerホストから`-H`フラグをつけてDockerデーモンを`Docker Manager`に指定してから`info`コマンドを実行してみます。`Docker Swarm`が正常に起動しているようです。

```bash
$ docker -H tcp://10.3.0.101:3333 info
Containers: 2
Images: 2
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 1
 minion-1: 10.3.0.101:2375
  └ Status: Healthy
  └ Containers: 2
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 8.202 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.16.0-4-amd64, operatingsystem=Debian GNU/Linux 8 (jessie), storagedriver=aufs
CPUs: 2
Total Memory: 8.202 GiB
Name: 397912e89a4d
```


### minion-[2-3]

　`minion-2`と`minion-3`のDockerホストには`Swarm Agent`だけインストールします。以下は`minion-2`の例です。

```bash
$ docker pull swarm
$ docker run -d \
  swarm \
  join \
  --addr=10.3.0.102:2375 \
  consul://10.3.0.102:8500/swarm
```

　`minion-2`から`minion-1`の`Swarm Manager`をDockerデーモンに指定して`info`コマンドを実行してみます。Swarmクラスタは`Nodes: 2`になり`minion-1`と`minion-2`が参加したことがわかります。

```bash
$ docker -H tcp://10.3.0.101:3333 info
Containers: 3
Images: 4
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 2
 minion-1: 10.3.0.101:2375
  └ Status: Healthy
  └ Containers: 2
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 8.202 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.16.0-4-amd64, operatingsystem=Debian GNU/Linux 8 (jessie), storagedriver=aufs
 minion-2: 10.3.0.102:2375
  └ Status: Healthy
  └ Containers: 1
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 8.202 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.16.0-4-amd64, operatingsystem=Debian GNU/Linux 8 (jessie), storagedriver=aufs
CPUs: 4
Total Memory: 16.4 GiB
Name: 397912e89a4d
```

　同様に`minion-3`にも`Swarm Agent`コンテナをインストールします。

```bash
$ docker run -d \
  swarm \
  join \
  --addr=10.3.0.103:2375 \
  consul://10.3.0.103:8500/swarm
```

　`minion-3`から`minion-1`の`Swarm Manager`をDockerデーモンに指定して`info`コマンドを実行してみます。Swarmクラスタは`Nodes: 3`になり、IDCFクラウドの[standard.M8 (2 CPU 8GB RAM)](http://www.idcf.jp/cloud/price.html#price-section)の3台分が合計されています。

* CPU: 6 CPU
* メモリー: 24.61 GiB

```bash
$ docker -H tcp://10.3.0.101:3333 info
Containers: 4
Images: 6
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 3
 minion-1: 10.3.0.101:2375
  └ Status: Healthy
  └ Containers: 2
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 8.202 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.16.0-4-amd64, operatingsystem=Debian GNU/Linux 8 (jessie), storagedriver=aufs
 minion-2: 10.3.0.102:2375
  └ Status: Healthy
  └ Containers: 1
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 8.202 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.16.0-4-amd64, operatingsystem=Debian GNU/Linux 8 (jessie), storagedriver=aufs
 minion-3: 10.3.0.103:2375
  └ Status: Healthy
  └ Containers: 1
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 8.202 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.16.0-4-amd64, operatingsystem=Debian GNU/Linux 8 (jessie), storagedriver=aufs
CPUs: 6
Total Memory: 24.61 GiB
Name: 397912e89a4d
```

## docker network

　Docker Swarmクラスタでは`docker network`をリストすると以下のようになります。`dn`はOverlayネットワークなので`minion-[1-3]`で共通の`NETWORK ID`を持っています。

```bash
$ docker -H tcp://10.3.0.101:3333 network ls
NETWORK ID          NAME                       DRIVER
b68b118036d2        minion-1/bridge            bridge
f10c0f7978af        dn                         overlay
636664a4f746        minion-1/docker_gwbridge   bridge
5d0368bb1be6        minion-3/host              host
d839af5031ca        minion-3/bridge            bridge
bc09b464b0c5        minion-1/host              host
a67f3a364d5b        minion-2/bridge            bridge
63b1b125bd29        minion-2/docker_gwbridge   bridge
b29394e7420d        minion-2/none              null
1d85b701a383        minion-2/host              host
8a4889033015        minion-3/none              null
87ac747fad87        minion-3/docker_gwbridge   bridge
6e0cf0387184        minion-1/none              null
```


## テスト用コンテナの作成


### minion-1

　`minion-1`のDockerホストからテスト用のコンテナを2つ起動します。`amb1`コンテナは`-H`フラグをつけて`Swarm Manager`をDockerデーモンに指定しします。


```bash
$ docker -H tcp://10.3.0.101:3333 \
  run -d -it \
  --name amb1 \
  -h amb1 \
  --net dn \
  debian:jessie
```

　`amb2`コンテナはlocalhostのDockerデーモンで起動します。

```bash
$ docker \
  run -d -it \
  --name amb2 \
  -h amb2 \
  --net dn \
  debian:jessie
```

　`ps`コマンドで確認するとlocalhost(`minion-1`)のDockerデーモンで起動している`amb2`が表示されます。

```bash
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
adb34e982686        debian:jessie       "/bin/bash"              40 seconds ago      Up 39 seconds                                amb2
7c328c08df7a        swarm               "/swarm join --addr=1"   20 minutes ago      Up 20 minutes       2375/tcp                 dreamy_liskov
397912e89a4d        swarm               "/swarm manage consul"   24 minutes ago      Up 24 minutes       0.0.0.0:3333->2375/tcp   swarm-manage
```

　`-H`フラグで`Swarm Manager`を指定して`ps`コマンドを実行すると、`minion-2`ホストで起動した`amb1`も表示されます。

```bash
$ docker -H tcp://10.3.0.101:3333 ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
adb34e982686        debian:jessie       "/bin/bash"         7 seconds ago       Up 6 seconds                            minion-1/amb2
b505e4526019        debian:jessie       "/bin/bash"         4 minutes ago       Up 4 minutes                            minion-2/amb1
```

　`amb1`コンテナは`minion-1`のDockerデーモンで起動していないので`Swarm Manager`を指定しないと見つかりません。

```bash
$ docker exec amb1 cat /etc/hosts
Error response from daemon: no such id: amb1
```

　`-H`フラグを指定して`amb1`コンテナの`/etc/hosts`を確認します。`amb1`と`amb2`の名前解決ができるようになっています。

```bash
$ docker -H tcp://10.3.0.101:3333 exec amb1 cat /etc/hosts
192.168.0.2     amb1
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.0.3     amb2
192.168.0.3     amb2.dn
```

　`amb2`の`/etc/hosts`には`amb1`のエントリーがありません。

```bash
$ docker exec amb2 cat /etc/hosts
192.168.0.3     amb2
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.0.2     amb1
192.168.0.2     amb1.dn
```

　まとめるとテスト用のコンテナは以下のように起動しました。

|コンテナのhostname|コンテナのIPアドレス|Dockerホスト| DockerホストのIPアドレス |
|:--|:--|:--|:--|
|amb1|192.168.0.2|minion-2|10.3.0.102|
|amb2|192.168.0.3|minion-1|10.3.0.101|


### minion-2

　次に`minion-2`にログインしてコンテナの状態を調べてみます。`amb2`コンテナは`minion-2`のDockerデーモンで起動しました。

```bash
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
b505e4526019        debian:jessie       "/bin/bash"              About a minute ago   Up About a minute                       amb1
ce9217effebd        swarm               "/swarm join --addr=1"   15 minutes ago       Up 15 minutes       2375/tcp            furious_leakey
```

　`-H`フラグをつけて`Swarm Manager`をDockerデーモンに指定すると、`minion-1`で起動した`amb2`も合わせて表示されます。

```bash
$ docker -H tcp://10.3.0.101:3333 ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
adb34e982686        debian:jessie       "/bin/bash"         2 minutes ago       Up 2 minutes                            minion-1/amb2
b505e4526019        debian:jessie       "/bin/bash"         6 minutes ago       Up 5 minutes                            minion-2/amb1
```



### minion-3

　最後に`minion-3`のDockerホストにログインして確認します。`minion-3`では`Swarm Agent`コンテナ以外起動していません。

```bash
$  docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
62458254ec86        swarm               "/swarm join --addr=1"   15 minutes ago      Up 15 minutes       2375/tcp            awesome_babbage
```

　`Swarm Manager`を指定すると`minion-[1-3]`はすべて同じ結果が表示されました。

```bash
$ docker -H tcp://10.3.0.101:3333 ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
adb34e982686        debian:jessie       "/bin/bash"         2 minutes ago       Up 2 minutes                            minion-1/amb2
b505e4526019        debian:jessie       "/bin/bash"         6 minutes ago       Up 6 minutes                            minion-2/amb1
```