Docker Swarmで何気なくデプロイしたserviceのIPアドレスとかネットワークを確認してみる

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

この記事では、以下の記事で構築したDocker Swarm環境上でデプロイしたservice（nginxとredis）のIPアドレスやネットワーク環境がどうなっているかを確認してみたいと思います。

https://qiita.com/ohtsuka-shota/items/314ed4a8a2bb6c6d92df

# 復習

Docker Swarmクラスタに所属しているnodeは以下となります。
hostnameがdockerとなっているnodeがLeaderで、その他2つのnodeがworker nodeとなっており、計3つのnodeがSwarmクラスタを形成しています。
```
root@docker:~# docker node ls
ID                            HOSTNAME         STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
624so5sshxf30h6bgde3mr9kl *   docker           Ready     Active         Leader           23.0.3
ru8v94326h4pdghg0h1vifljy     swarm-worker01   Ready     Active                          23.0.4
pnmvavvon0hfrciinwn7w4pe3     swarm-worker02   Ready     Active                          23.0.4
```

networkは以下となります。
```
root@docker:~# docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
92d578e12a26   bridge            bridge    local
da8e681f4aa2   docker_gwbridge   bridge    local
e80bd3a263ec   host              host      local
5d0wz7me1k3q   ingress           overlay   swarm
93abcdf649c5   none              null      local
```

このSwarm環境に以下のコマンドを実行してnginx serviceをデプロイ
```
root@docker:~# docker service create --replicas 3 --name nginx nginx:latest
q3mg1bd2cjq125n8evhu2fsv2
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Service converged

root@docker:~# docker service ps nginx
ID             NAME      IMAGE          NODE             DESIRED STATE   CURRENT STATE                ERROR     PORTS
7cjbdf9htcgw   nginx.1   nginx:latest   swarm-worker02   Running         Running about a minute ago
nwbn4sewf7ug   nginx.2   nginx:latest   docker           Running         Running 5 minutes ago
g7t4p8ketaer   nginx.3   nginx:latest   swarm-worker01   Running         Running about a minute ago
```
またportainerを使ってGUIベースでredis serviceをデプロイしています。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333231393338352f30656533386464302d303135332d633936652d353036642d6130343166616536353738332e706e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/0e5780cb-d4d2-a3ef-13e3-3c4a5a339a0a.png)

ここまでのざっくりとしたイメージ図は以下となります。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333231393338352f64613265343462372d626332662d646634362d373734312d3634663266316538653736392e706e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/92724b56-a94b-1c5d-6f2d-b3b0511b9426.png)

# コンテナとネットワークの確認

早速ですがdocker node（Leader）上で以下から取得したシェルスクリプトを実行し、コンテナのIPアドレス一覧を出力してみたいと思います。

https://www.opensourcetech.tokyo/entry/2018/11/22/Docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

django-conやportainerは今回関係ありませんので無視ししてもらって構いません。
nginxコンテナもredisコンテナも172.17.0.0/16のネットワークにいることが分かりますね。
※シェルを用意するのが面倒であればdocker inspect "コンテナ名"でIPアドレスが確認出来ます。
```
root@docker:~/docker-netns# ls -ltr
total 8
-rw-r--r-- 1 root root  280 Apr 19 06:56 README.md
-rwxr-xr-x 1 root root 3972 Apr 19 06:56 docker-netns.sh
root@docker:~/docker-netns# ./docker-netns.sh visible
container's network namespace to visible, you can show container's nemespace by [ip netns] command.
root@docker:~/docker-netns#  ./docker-netns.sh showveth
VETH                 CONTAINER ID         NAMES
vethba234a8          89b3a62cfac9         /django-con
vethabb34ac          788d4fd0762d         /redis.3.stm8yqzn2pe9y5sf82uekv3ni
vethbe55e07          a2430aa7323e         /nginx.2.nwbn4sewf7ugnnbctw3qukcvk
vethbb9bfd9          8240d0af95a3         /portainer
root@docker:~/docker-netns# ./docker-netns.sh showip
CONTAINER ID    IP                                       NAMES
89b3a62cfac9    inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0 /django-con
788d4fd0762d    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0 /redis.3.stm8yqzn2pe9y5sf82uekv3ni
a2430aa7323e    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 /nginx.2.nwbn4sewf7ugnnbctw3qukcvk
8240d0af95a3    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 /portainer
```

このネットワークはどのbridge,ingressが担当しているのか確認してみます。
Leader上での出力結果の一部を以下に記載しておりますが、結果からも分かるように、Docker Swarmを作成した際に自動生成されるingressやdocker_gwbridgeにserviceが自動的にデプロイされるわけではなく、dockerをインストールした際に自動生成されるbridge(docker0)に紐づいていることが分かります。
serviceはDocker Swarmの話だと思っていたので、デフォルトでingressかdocker_gwbridgeにデプロイされると思ったのですが違うようですね。。。
```
root@docker:~# docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
92d578e12a26   bridge            bridge    local
da8e681f4aa2   docker_gwbridge   bridge    local
e80bd3a263ec   host              host      local
5d0wz7me1k3q   ingress           overlay   swarm
93abcdf649c5   none              null      local

root@docker:~# docker network inspect docker_gwbridge
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },

root@docker:~# docker network inspect ingress
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
                }
            ]
        },

root@docker:~# docker network inspect bridge
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
```

worker01とworker02でも同様にコンテナのIPアドレスとネットワークを確認してみようと思います。
まずはworker01
```
root@swarm-worker01:~/docker-netns# ./docker-netns.sh showveth
VETH                 CONTAINER ID         NAMES
vetha6d09e8          7ebc11d3fea6         /redis.1.evg1blajwa49alzu6j8kcorqk
veth21699f0          1adc34f9c814         /nginx.3.g7t4p8ketaerk0r3dwmdxsxde
root@swarm-worker01:~/docker-netns# ./docker-netns.sh showip
CONTAINER ID    IP                                       NAMES
7ebc11d3fea6    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 /redis.1.evg1blajwa49alzu6j8kcorqk
1adc34f9c814    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 /nginx.3.g7t4p8ketaerk0r3dwmdxsxde

root@swarm-worker01:~/docker-netns# docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
99685a25d3bd   bridge            bridge    local
2bd0158eceaa   docker_gwbridge   bridge    local
9d0f7be57db6   host              host      local
5d0wz7me1k3q   ingress           overlay   swarm
a79ea157cf94   none              null      local

root@swarm-worker01:~/docker-netns# docker network inspect docker_gwbridge
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
root@swarm-worker01:~/docker-netns# docker network inspect ingress
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
                }
            ]
        },

root@swarm-worker01:~# docker network inspect bridge
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
```

続いてworker02
```
root@swarm-worker02:~/docker-netns# ./docker-netns.sh showveth
VETH                 CONTAINER ID         NAMES
vethf515806          53ff2c1f517a         /redis.2.0pymeevizsisahqrlzxcgtx9t
veth28c2242          3d8f68d6a776         /nginx.1.7cjbdf9htcgw74s9x35yuuy1j
root@swarm-worker02:~/docker-netns# ./docker-netns.sh showip
CONTAINER ID    IP                                       NAMES
53ff2c1f517a    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 /redis.2.0pymeevizsisahqrlzxcgtx9t
3d8f68d6a776    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 /nginx.1.7cjbdf9htcgw74s9x35yuuy1j

root@swarm-worker02:~/docker-netns# docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
485e81c1074f   bridge            bridge    local
f0dc62496a89   docker_gwbridge   bridge    local
e8edf1bca875   host              host      local
5d0wz7me1k3q   ingress           overlay   swarm
ed360f541d18   none              null      local

root@swarm-worker02:~/docker-netns# docker network inspect docker_gwbridge
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },

root@swarm-worker02:~/docker-netns# docker network inspect ingress
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
                }
            ]
        },

root@swarm-worker02:~# docker network inspect bridge
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
```

上記の出力を鑑みるに、たぶんイメージとしては以下の様な状態であると言えると思います。
bridge(docker0)にコンテナがぶら下がっているので、どのホストに接続してもnginxやredisに接続出来ますが、負荷分散が出来ているわけではない状態と言えると思います。
また、ホストを跨いだコンテナ間通信も勿論出来ておりません。

![docker-ページ20.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/15caaf10-9442-8eaa-4d04-d6a0137c7dba.png)


この後、ログは無いのですがdocker_gwbridgeやingressにコンテナをアタッチ出来ないかいろいろ試してみたのですが、不発。
~~docker公式のドキュメント【Use the default overlay network】を見てみても、デフォルトで作成されるingressではなく、別途overlayを作ってそこにアタッチしている様でした、、、良くわからぬ。。。~~
デフォルトで作成されるingressにserviceをアタッチする為にはserviceデプロイ時に--publishオプションを指定してあげると良いっぽいです。
以下のその手順なり検証なりを書いています。

https://qiita.com/ohtsuka-shota/items/abc80328e83543dd09cc