Docker1.12のSwarmを試す


cloudpack大阪の佐々木です。

話題のDocker1.12を試してみようと思います。
まず、一番の目玉機能と思われるswarmの統合を試してみます。
チュートリアルを参考に(そのままですが・・・)、swarmの構築、サービスの追加、ローリングアップデートを試してみました。

# Docker Swarmとは

Dockerノードを束ねてクラスタを作る機能です。
以前からありましたが、先日発表された1.12からDocker本体に統合され、使いやすくなっているようです。

# 環境

Docker for AWSのPrivate Beatに申し込んでいますが、まだ返答はなく、Docker for Macではクラスタ感がいまいち味わえないので、EC2に1.12のDockerをインストールして試してみました。

# インストール

Amazon Linuxにインストールする方法がいまいち分からなかったので、下記を参照にCentOS7にインストールしてみます。

https://docs.docker.com/engine/installation/linux/centos/

ただ、ここに記載されているリポジトリのURLでは1.11がインストールされるので、下記のように修正します。

```bash:
$ sudo tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/testing/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF
```

```bash:
$ sudo yum install -y docker-engine
$ sudo systemctl enable docker.service
$ sudo systemctl start docker.service
```

docker1.12をインストールしたCentOSを3台構築し、ホスト名を
+ manager1
+ worker1
+ worker2
にします。
それぞれのインスタンス間で通信できるようにセキュリティグループを設定します。

# チュートリアル

下記のチュートリアルを順番に試してみました。

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

### Swarmクラスタの作成
https://docs.docker.com/engine/swarm/swarm-tutorial/create-swarm/

まずswarmクラスタを作成します。
manager1で下記を実行します。

```bash:
$ docker swarm init
Swarm initialized: current node (eitfugbeu426sulvjboucdidq) is now a manager.
```

helpにあるとおり、Listen IP/portを指定する場合は、
--listen-addr 10.1.1.1:2377 という感じで指定します。
指定しない場合は、0.0.0.0:2377 になります。

自身がノードとして追加されていることを確認します。

```bash:
$ docker node ls
ID                           NAME      MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
eitfugbeu426sulvjboucdidq *  manager1  Accepted    Ready   Active        Leader
```

### Swarmにノードの追加
https://docs.docker.com/engine/swarm/swarm-tutorial/add-nodes/

worker1、2で下記を実行し、swarmに参加します。

```bash:
$ docker swarm join (managerのIP):2377
This node joined a Swarm as a worker.
```

manager1で下記を実行し、worker1、2が追加されていることを確認します。

```bash:
docker node ls
ID                           NAME      MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
43mdhg1wi44him1mglr09dxsh    worker1   Accepted    Ready   Active
8zbsnwbz0qg7e76a637ihj311    worker2   Accepted    Ready   Active
eitfugbeu426sulvjboucdidq *  manager1  Accepted    Ready   Active        Leader
```

### Swarmにサービスをデプロイ
https://docs.docker.com/engine/swarm/swarm-tutorial/deploy-service/

manager1で下記を実行します。

```bash:
docker service create --replicas 1 --name helloworld alpine ping docker.com
8oxxbwc3dzgtpuq3de5kkik88
```
Alpine Linuxのコンテナ1台で ping docker.comを実行すると意味になります。

サービスが稼働していることを確認します。

```bash:
docker service ls
ID            NAME        REPLICAS  IMAGE   COMMAND
8oxxbwc3dzgt  helloworld  1/1       alpine  ping docker.com
```

### サービスのインスペクト
https://docs.docker.com/engine/swarm/swarm-tutorial/inspect-service/

下記のようなコマンドでサービスの状態が確認できます。

```bash:
docker service inspect --pretty helloworld
ID:		8oxxbwc3dzgtpuq3de5kkik88
Name:		helloworld
Mode:		Replicated
 Replicas:	1
Placement:
 Strategy:	Spread
UpdateConfig:
 Parallelism:	0
ContainerSpec:
 Image:		alpine
 Args:		ping docker.com
Resources:
Reservations:
Limits:
```

--prettyを省略するとjson形式で出力されます。

```bash:
docker service inspect helloworld
[
    {
        "ID": "8oxxbwc3dzgtpuq3de5kkik88",
        "Version": {
            "Index": 22
        },
        "CreatedAt": "2016-06-27T15:22:14.396375971Z",
        "UpdatedAt": "2016-06-27T15:22:14.396375971Z",
        "Spec": {
            "Name": "helloworld",
            "TaskTemplate": {
                "ContainerSpec": {
                    "Image": "alpine",
                    "Args": [
                        "ping",
                        "docker.com"
                    ]
                },
                "Resources": {
                    "Limits": {},
                    "Reservations": {}
                },
                "RestartPolicy": {
                    "Condition": "any",
                    "MaxAttempts": 0
                },
                "Placement": {}
            },
            "Mode": {
                "Replicated": {
                    "Replicas": 1
                }
            },
            "UpdateConfig": {},
            "EndpointSpec": {
                "Mode": "vip"
            }
        },
        "Endpoint": {
            "Spec": {}
        }
    }
]
```

どのノードでコンテナが稼働しているかの確認

```bash:
$ docker service tasks helloworld
ID                         NAME          SERVICE     IMAGE   LAST STATE         DESIRED STATE  NODE
4hf91p8moi7gdvwx22c917gsf  helloworld.1  helloworld  alpine  Running 6 minutes  Running        manager1
```
稼働しているノードで下記を実行し、コンテナの詳細を確認

```bash:
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
a3fc9cf7c874        alpine:latest       "ping docker.com"   7 minutes ago       Up 7 minutes                            helloworld.1.4hf91p8moi7gdvwx22c917gsf
```

### サービスのスケール

https://docs.docker.com/engine/swarm/swarm-tutorial/scale-service/

helloworldを5台にスケールさせます。

```bash:
docker service scale helloworld=5
helloworld scaled to 5
```

確認

```bash:
docker service tasks helloworld
ID                         NAME          SERVICE     IMAGE   LAST STATE          DESIRED STATE  NODE
4hf91p8moi7gdvwx22c917gsf  helloworld.1  helloworld  alpine  Running 9 minutes   Running        manager1
4tarsvkte3of71o7755yclvlv  helloworld.2  helloworld  alpine  Running 42 seconds  Running        worker1
bjzw5mhnb1lwga1ycecfetfv2  helloworld.3  helloworld  alpine  Running 42 seconds  Running        worker2
2ip9tit3pupoj8fyjlw5y4t03  helloworld.4  helloworld  alpine  Running 42 seconds  Running        worker2
0zfhyhrqk114cj11xguvsrzvz  helloworld.5  helloworld  alpine  Running 42 seconds  Running        manager1
```
3台のノードに分散されています。

### サービスの削除

https://docs.docker.com/engine/swarm/swarm-tutorial/delete-service/

helloworldを削除します。

```bash:
$ docker service rm helloworld
helloworld
```

確認

```bash:
$ docker service inspect helloworld
[]
Error: no such service: helloworld
```

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

https://docs.docker.com/engine/swarm/swarm-tutorial/rolling-update/

バージョン3.0.6のredisコンテナでサービスをつくり、3.0.7にローリングアップデートします。

```bash:
docker service create --replicas 5 --name redis --update-delay 10s --update-parallelism 1 redis:3.0.6
236f4wpbfv07ocl1kebe4wh1j
```
redis3.0.6のコンテナを５つつくり、updateの間隔を１０秒、同時にアップデートする数を1にしています。

確認

```bash:
docker service inspect redis --pretty
ID:		236f4wpbfv07ocl1kebe4wh1j
Name:		redis
Mode:		Replicated
 Replicas:	5
Placement:
 Strategy:	Spread
UpdateConfig:
 Parallelism:	1
 Delay:		10s
ContainerSpec:
 Image:		redis:3.0.6
Resources:
Reservations:
Limits:
```

3.0.7へのアップデートを実行します。

```bash:
docker service update --image redis:3.0.7 redis
redis
```

確認

```
docker service inspect --pretty redis
ID:		236f4wpbfv07ocl1kebe4wh1j
Name:		redis
Mode:		Replicated
 Replicas:	5
Placement:
 Strategy:	Spread
UpdateConfig:
 Parallelism:	1
 Delay:		10s
ContainerSpec:
 Image:		redis:3.0.7
Resources:
Reservations:
Limits:
```

順番にアップデートされていきます。

```bash:
$ docker service tasks redis
ID                         NAME     SERVICE  IMAGE        LAST STATE            DESIRED STATE  NODE
5hrzferlm1pfo3t18fj8h0ks3  redis.1  redis    redis:3.0.7  Preparing 1 seconds   Running        worker2
cy8xapvck5nj7mi71m5oj09xk  redis.2  redis    redis:3.0.7  Preparing 11 seconds  Running        worker2
4772bv6zlwp2c42botcvph4eg  redis.3  redis    redis:3.0.6  Running 4 minutes     Running        worker1
cdppq5w50jkkp1cdiwbmxf7o2  redis.4  redis    redis:3.0.6  Running 4 minutes     Running        worker1
4j5azfbmkmtjcjdwq3mrcih26  redis.5  redis    redis:3.0.6  Running 4 minutes     Running        manager1

$ docker service tasks redis
ID                         NAME     SERVICE  IMAGE        LAST STATE            DESIRED STATE  NODE
3y2675vxi4vfwtt0za7zfh98w  redis.1  redis    redis:3.0.7  Preparing 12 seconds  Running        manager1
cy8xapvck5nj7mi71m5oj09xk  redis.2  redis    redis:3.0.7  Preparing 27 seconds  Running        worker2
41o9qbw1rdxo0e25c4myl45wy  redis.3  redis    redis:3.0.7  Preparing 2 seconds   Running        worker2
cdppq5w50jkkp1cdiwbmxf7o2  redis.4  redis    redis:3.0.6  Running 4 minutes     Running        worker1
4j5azfbmkmtjcjdwq3mrcih26  redis.5  redis    redis:3.0.6  Running 4 minutes     Running        manager1

$ docker service tasks redis
ID                         NAME     SERVICE  IMAGE        LAST STATE            DESIRED STATE  NODE
3y2675vxi4vfwtt0za7zfh98w  redis.1  redis    redis:3.0.7  Preparing 35 seconds  Running        manager1
cy8xapvck5nj7mi71m5oj09xk  redis.2  redis    redis:3.0.7  Running 50 seconds    Running        worker2
4ab0mvl9vyhund6d7p6r5lunz  redis.3  redis    redis:3.0.7  Preparing 18 seconds  Running        worker1
cdppq5w50jkkp1cdiwbmxf7o2  redis.4  redis    redis:3.0.6  Running 5 minutes     Running        worker1
2mhtbzsjvful0kit3i4j7qnkl  redis.5  redis    redis:3.0.7  Ready 8 seconds       Running        worker2

$ docker service tasks redis
ID                         NAME     SERVICE  IMAGE        LAST STATE              DESIRED STATE  NODE
3y2675vxi4vfwtt0za7zfh98w  redis.1  redis    redis:3.0.7  Running 50 seconds      Running        manager1
cy8xapvck5nj7mi71m5oj09xk  redis.2  redis    redis:3.0.7  Running About a minute  Running        worker2
4ab0mvl9vyhund6d7p6r5lunz  redis.3  redis    redis:3.0.7  Running 33 seconds      Running        worker1
8wr4sactu87ag9cuiojdt7eys  redis.4  redis    redis:3.0.7  Running 4 seconds       Running        manager1
2mhtbzsjvful0kit3i4j7qnkl  redis.5  redis    redis:3.0.7  Running 24 seconds      Running        worker2
```

### ノードの除外

https://docs.docker.com/engine/swarm/swarm-tutorial/drain-node/

メンテナンス等でノードを除外する場合は、下記のdrainコマンドを実行します。

3台のノードにコンテナが分散されていることを確認します。

```bash:
docker service tasks redis
ID                         NAME     SERVICE  IMAGE        LAST STATE         DESIRED STATE  NODE
3y2675vxi4vfwtt0za7zfh98w  redis.1  redis    redis:3.0.7  Running 6 minutes  Running        manager1
cy8xapvck5nj7mi71m5oj09xk  redis.2  redis    redis:3.0.7  Running 7 minutes  Running        worker2
4ab0mvl9vyhund6d7p6r5lunz  redis.3  redis    redis:3.0.7  Running 6 minutes  Running        worker1
8wr4sactu87ag9cuiojdt7eys  redis.4  redis    redis:3.0.7  Running 6 minutes  Running        manager1
2mhtbzsjvful0kit3i4j7qnkl  redis.5  redis    redis:3.0.7  Running 6 minutes  Running        worker2
```

worker1を除外します。

```bash:
$ docker node update --availability drain worker1
worker1
```
worker1のAvailabilityがDrainになりました。

```bash:
$ docker node inspect --pretty worker1
ID:			43mdhg1wi44him1mglr09dxsh
Hostname:		worker1
Status:
 State:			Ready
 Availability:		Drain
Platform:
 Operating System:	linux
 Architecture:		x86_64
Resources:
 CPUs:			1
 Memory:		991.7 MiB
Plugins:
  Network:		overlay, overlay, null, host, bridge
  Volume:		local
Engine Version:		1.12.0-rc2
```

worker1以外の2台に分散されていることを確認します。

```bash:
$ docker service tasks redis
ID                         NAME     SERVICE  IMAGE        LAST STATE          DESIRED STATE  NODE
3y2675vxi4vfwtt0za7zfh98w  redis.1  redis    redis:3.0.7  Running 9 minutes   Running        manager1
cy8xapvck5nj7mi71m5oj09xk  redis.2  redis    redis:3.0.7  Running 9 minutes   Running        worker2
8ilsqn1cidmmtrl7qyrcuyq0u  redis.3  redis    redis:3.0.7  Running 10 seconds  Running        manager1
8wr4sactu87ag9cuiojdt7eys  redis.4  redis    redis:3.0.7  Running 8 minutes   Running        manager1
2mhtbzsjvful0kit3i4j7qnkl  redis.5  redis    redis:3.0.7  Running 8 minutes   Running        worker2
```

worker1をActiveに戻します。

```bash:
$docker node update --availability active worker1
worker1
```

AvailabilityがActiveになりました。

```bash:
$ docker node inspect --pretty worker1
ID:			43mdhg1wi44him1mglr09dxsh
Hostname:		worker1
Status:
 State:			Ready
 Availability:		Active
Platform:
 Operating System:	linux
 Architecture:		x86_64
Resources:
 CPUs:			1
 Memory:		991.7 MiB
Plugins:
  Network:		overlay, overlay, null, host, bridge
  Volume:		local
Engine Version:		1.12.0-rc2
```

# まとめ

1.12で統合されたswarmを使うと、非常に簡単にクラスタ環境が構築できました。
その他の機能も試したみたいと思います。