Docker swarmでサービスを動かす & スケールインを試す


**(注意)Docker engineのバージョンは1.12**

# 概要

swarm上でnginxのサービス(nginx_sample)を実行しつつ、
スケールイン(docker service scaleコマンド)を試してみる。

# コマンドリスト

|コマンド|内容|
|---|---|
|docker service create|新規サービスを立ち上げる|
|docker service scale|既存サービスをスケールアウト・インさせる|
|docker service ls|swarmクラスタ内で動作しているサービスのリストを表示する|
|docker service ps|サービス内に含まれるタスク(コンテナ)の一覧を表示する|
|docker service rm|サービスを削除する|

今回主に用いるコマンドは前半の二つ。

# 新規サービスを起動する

```bash:新規サービス(nginxサービス)を起動する
docker service create -p 80:80 --name="nginx_sample" --replicas=3 nginx
```

swarmノードのTCP80番(HTTP)とnginx_sampleサービスのTCP80番(HTTP)を紐づける。
nginxイメージはTCP443番(HTTPS)も利用できるが、今回はあくまでもサンプルのため設定しない。

## 起動中確認

```bash:起動中のサービスの状態
docker service ls
ID            NAME          REPLICAS  IMAGE  COMMAND
8ejer8lok06o  nginx_sample  0/3       nginx
```

REPLICASの値が0/3なので、まだ一つもコンテナは起動していない。


```bash:起動中のサービス内タスク(コンテナ)の状態
docker service ps nginx_sample
ID                         NAME            IMAGE  NODE        DESIRED STATE  CURRENT STATE             ERROR
6tns1opze4dtzjdq7la1rgpvj  nginx_sample.1  nginx  ubuntu-001  Running        Preparing 25 seconds ago  
ei2hww2pdqo4rd114d6sl0tvn  nginx_sample.2  nginx  ubuntu-002  Running        Preparing 25 seconds ago  
b9tvhzi6ln5hcjhnsia6y5uyp  nginx_sample.3  nginx  ubuntu-003  Running        Preparing 25 seconds ago
```

DESIRED STATEがRunningなのに対してCURRENT STATEがPreparingであるため、
まだ起動していない。

docker service inspect サービス名 で詳細な情報を取得できる。

```bash:サービスの詳細情報の取得(inspect)
docker service inspect nginx_sample
[
    {
        "ID": "1uzck4r361lxi8u3zyaqa6zhf",
        "Version": {
            "Index": 91
        },
        "CreatedAt": "2016-08-13T14:47:54.266023526Z",    # 作成が指示された時刻
        "UpdatedAt": "2016-08-13T14:47:54.269125202Z",　# 更新は行っていないのでCreatedAtに等しい
        "Spec": {
            "Name": "nginx_sample",
            "TaskTemplate": {
                "ContainerSpec": {
                    "Image": "nginx"
                },
                "Resources": {
                    "Limits": {},
                    "Reservations": {}
                },
                "RestartPolicy": {
                    "Condition": "any",
                    "MaxAttempts": 0
                },
                "Placement": {}
            },
            "Mode": {
                "Replicated": {
                    "Replicas": 3                                    # 指定したレプリカ数
                }
            },
            "UpdateConfig": {
                "Parallelism": 1,
                "FailureAction": "pause"
            },
            "EndpointSpec": {
                "Mode": "vip",
                "Ports": [
                    {
                        "Protocol": "tcp",
                        "TargetPort": 80,
                        "PublishedPort": 80
                    }
                ]
            }
        },
        "Endpoint": {
            "Spec": {
                "Mode": "vip",
                "Ports": [
                    {
                        "Protocol": "tcp",
                        "TargetPort": 80,
                        "PublishedPort": 80
                    }
                ]
            },
            "Ports": [                   # 指定したポートがオープンされている
                {
                    "Protocol": "tcp",
                    "TargetPort": 80,
                    "PublishedPort": 80
                }
            ],
            "VirtualIPs": [
                {
                    "NetworkID": "27szphefusnj2bdpq0itpfpat",
                    "Addr": "10.255.0.6/16"
                }
            ]
        },
        "UpdateStatus": {
            "StartedAt": "0001-01-01T00:00:00Z",       #サービスが起動中の場合、ここが空に等しいような値になっている
            "CompletedAt": "0001-01-01T00:00:00Z"
        }
    }
]
```

### 注意点
DockerHubなどのインターネットからイメージを取得する場合は、
個別のノードすべてが一斉にインターネットにアクセスするので、ネットワーク流量に注意すること。

## 起動後確認

3つのDockerホストいずれにアクセスしてもnginxの起動画面が表示される。

![image](https://qiita-image-store.s3.amazonaws.com/0/40692/b97e89ac-0ae1-cdea-4ee2-eb1307b9b6b6.png)


```bash:起動済サービスの状態
docker service ls
ID            NAME          REPLICAS  IMAGE  COMMAND
1uzck4r361lx  nginx_sample  3/3       nginx
```

REPLICASが3/3となっており、クラスタ内で指定したとおりに3つのnginxのコンテナが起動している。

```bash:起動済みサービス内タスク(コンテナ)の状態
docker service ps nginx_sample
ID                         NAME            IMAGE  NODE        DESIRED STATE  CURRENT STATE          ERROR
dcdngo5ibombyjuqysst4y3gf  nginx_sample.1  nginx  ubuntu-003  Running        Running 8 minutes ago  
bg39i6hrqksfle0xypkpnoouz  nginx_sample.2  nginx  ubuntu-002  Running        Running 8 minutes ago  
4nutgpvioz91oyubtjb9lgzq6  nginx_sample.3  nginx  ubuntu-001  Running        Running 8 minutes ago
```

ubuntu-001/002/003の各ノードで1つずつのnginxコンテナが起動している。

### 起動後の全体イメージ

![Ingressオーバレイネットワーク(3コンテナ).png](https://qiita-image-store.s3.amazonaws.com/0/40692/b3d071da-07e6-4464-b93d-9c68876161e3.png)

# サービスのスケールを変更する

3台もnginxコンテナは不要だと気付いたのでいったんスケールインする。

1コンテナにしてもどのノードからでもアクセスできることを記述する。

```bash:サービスのスケールイン(3コンテナ->1コンテナ)
docker service scale nginx_sample=1 
nginx_sample scaled to 1
```

レプリカ(REPLICA)数を3から1に変更する。

## スケール変更結果の確認

```bash:lsによる確認
docker service ls
ID            NAME          REPLICAS  IMAGE  COMMAND
1uzck4r361lx  nginx_sample  1/1       nginx 
```
REPLICAの値が1/1になっており期待した通りになっている。

```bash:psによる確認
docker service ps nginx_sample
ID                         NAME            IMAGE  NODE        DESIRED STATE  CURRENT STATE           ERROR
dcdngo5ibombyjuqysst4y3gf  nginx_sample.1  nginx  ubuntu-003  Shutdown       Shutdown 2 minutes ago  
bg39i6hrqksfle0xypkpnoouz  nginx_sample.2  nginx  ubuntu-002  Shutdown       Shutdown 2 minutes ago  
4nutgpvioz91oyubtjb9lgzq6  nginx_sample.3  nginx  ubuntu-001  Running        Running 15 hours ago
```

ubuntu-002(192.168.1.26), ubuntu-003(192.168.1.29)で実行されていたコンテナが停止されている。
nginxのコンテナ事態はubuntu-001(192.168.1.27)でしか動いていないが、
ubuntu-002/ubuntu-003のいずれにアクセスしてもnginxコンテナにルーティングされる。
これはIngressオーバレイネットワークのおかげ。

![image](https://qiita-image-store.s3.amazonaws.com/0/40692/503a8bbf-d526-6515-612f-26ff68cf860f.png)

![image](https://qiita-image-store.s3.amazonaws.com/0/40692/9e75a48f-8610-6ab2-e188-0a67a3b1bcac.png)

![image](https://qiita-image-store.s3.amazonaws.com/0/40692/12f86549-8dd8-b304-88b7-d85a55460ac4.png)

### スケール変更後の全体イメージ

![Ingressオーバレイネットワーク(1コンテナ).png](https://qiita-image-store.s3.amazonaws.com/0/40692/f726c2d6-1111-0c68-aa3a-f618239f98cd.png)

# まとめ

- swarm上でサービスを構成し、swarm外からアクセスすることができた。(-p 80:80)
- swarm上でサービスを構成するタスクが一つでも動作していれば各ノードを介してアクセスできた。(Ingressオーバレイネットワーク)
- swarm上でコマンド(docker service scale)を用いてサービスをスケールインさせることができた。