Docker ( 10 ) ~ 複数コンテナの連携 4 ~

November 07, 2017

Docker Swarm

Docker Swarm とは複数の Docker ホストをまとめて、クラスタを作るためのツール。
Swarm クラスタでは Swarm マネージャが Docker ホストと同様に Docker サーバーとして動作する。Docker クライアントからは Swarm マネージャにコンテナ実行などのコマンドを送信でき、Swarm マネージャは送られた Docker コマンドを適切な Docker ホストに振り分けて実行する。
Swarm クラスタは外部からは 1 大の Docker ホストとして見えるため、Docker ホストに対応したツールとの連携が容易となる。
Swarm クラスタ内で独自のネットワークを構築することが可能であり、異なる Docker ホスト上のコンテナでもお互いに通信できるようになっている。

Docker Swarm クラスタの構成

Docker Swarm は以下の要素から構成されている。

  • Swarm マネージャ: クラスタ全体を管理
  • Swarm エージェント: 個々の Docker ホストを管理
  • key-value ストア: クラスタの状態を保持する

Swarm マネージャや Swarm エージェントという Swarm ツール自体も Docker コンテナとして動作する。

f:id:shiro_kochi:2018××××××××:plain:w100:left

Docker Swarm クラスタの構築

以下では実際に Docker Swarm クラスタを構築してみる。
Swarm クラスタは Docker ホストで直接動作させることもできるが、今回は Docker Machine で構築する。
key-value ストアは Consul を利用。

key-value ストア (Consul) の構築

Consul はコンテナ ( “progrium/consul” ) として提供されているので、Docker ホストを構築し、その上で Consul を稼働させる。
まずは Docker ホストを swarm-keystore という名前で作成。

$ docker-machine create -d amazonec2 --amazonec2-region ap-northeast-1 \
    --amazonec2-zone a \
    --amazonec2-instance-type t2.large \
    --amazonec2-root-size "50" \
    --amazonec2-vpc-id vpc-xxxxxxxxx \
    --amazonec2-subnet-id subnet-xxxxxxxx \
    --amazonec2-security-group YourSecurityGroupName \
    swarm-keystore

上記で起動した Docker ホスト上に progrium/consul を用いてコンテナを実行。

$ eval $(docker-machine env swarm-keystore)
$ docker run -d -p 8500:8500 -h consul progrium/consul -server -bootstrap

念の為確認してみる。

$ docker-machine ssh swarm-keystore
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-1020-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

118 packages can be updated.
42 updates are security updates.


Last login: Tue Nov  7 15:16:21 2017 from 13.115.204.186
ubuntu@swarm-keystore:~$ sudo docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                            NAMES
98c35ef0b72f        progrium/consul     "/bin/start -serve..."   18 seconds ago      Up 16 seconds       53/tcp, 53/udp, 8300-8302/tcp, 8400/tcp, 8301-8302/udp, 0.0.0.0:8500->8500/tcp   quizzical_bose

ちゃんと起動している。

Docker ホストの IP アドレスを確認し、Consul が動作しているか確認。
具体的にはキー “key1” に値 “value1” を設定する。

$ docker-machine ip swarm-keystore
13.115.140.247
$ curl -X PUT -d 'value1' http://13.115.140.247:8500/v1/kv/key1
true
$ curl http://13.115.140.247:8500/v1/kv/key1
[{"CreateIndex":13,"ModifyIndex":13,"LockIndex":0,"Key":"key1","Flags":0,"Value":"dmFsdWUx"}]
$ echo "dmFsdWUx" | base64 --decode
value1

なお、ブラウザからもアクセス可能。

f:id:shiro_kochi:2018××××××××:plain:w100:left

Docker ホストの構築

docker-machine create コマンドに --swarm オプションを指定することで、Docker ホストを Swarm クラスタとして構築する。
Swarm マネージャーを動作させる Docker ホストでは --swarm-master オプションも指定し、Swarm マネージャーのコンテナを実行する。
key-value ストアには先ほど構築した Consul を指定。
なお、docker-machine で AWS 上に Docker ホストを起動した際は基本的に Public IP を Docker ホストの IP アドレスとして認識するっぽい…

[ Swarm マネージャー用ホスト ]

$ docker-machine create -d amazonec2 \
    --amazonec2-region ap-northeast-1 \
    --amazonec2-zone a \
    --amazonec2-instance-type t2.large \
    --amazonec2-root-size "50" \
    --amazonec2-vpc-id vpc-xxxxxxxx \
    --amazonec2-subnet-id subnet-xxxxxxxx \
    --amazonec2-security-group YourSecurityGroup \
    --swarm \
    --swarm-master \
    --swarm-discovery="consul://13.115.140.247:8500/" \
    --engine-opt="cluster-store=consul://13.115.140.247:8500" \
    --engine-opt="cluster-advertise=eth0:2376" \
    swarm-manager

Running pre-create checks...
Creating machine...
(swarm-manager) Launching instance...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with ubuntu(systemd)...
Installing Docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Configuring swarm...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env swarm-manager

[ Swarm Node ]

# Node 1
$ docker-machine create -d amazonec2 \
    --amazonec2-region ap-northeast-1 \
    --amazonec2-zone a \
    --amazonec2-instance-type t2.large \
    --amazonec2-root-size "50" \
    --amazonec2-vpc-id vpc-xxxxxxxx \
    --amazonec2-subnet-id subnet-xxxxxxxx \
    --amazonec2-security-group YourSecurityGroup \
    --swarm \
    --swarm-discovery="consul://13.115.140.247:8500/" \
    --engine-opt="cluster-store=consul://13.115.140.247:8500" \
    --engine-opt="cluster-advertise=eth0:2376" \
    swarm-node1

# Node 2
$ docker-machine create -d amazonec2 \
    --amazonec2-region ap-northeast-1 \
    --amazonec2-zone c \
    --amazonec2-instance-type t2.large \
    --amazonec2-root-size "50" \
    --amazonec2-vpc-id vpc-xxxxxxxx \
    --amazonec2-subnet-id subnet-xxxxxxxx \
    --amazonec2-security-group YourSecurityGroup \
    --swarm \
    --swarm-discovery="consul://13.115.140.247:8500/" \
    --engine-opt="cluster-store=consul://13.115.140.247:8500" \
    --engine-opt="cluster-advertise=eth0:2376" \
    swarm-node2

構築した Swarm クラスタの確認

$ docker-machine ls
NAME             ACTIVE   DRIVER      STATE     URL                         SWARM                    DOCKER        ERRORS
swarm-keystore   *        amazonec2   Running   tcp://13.115.140.247:2376                            v17.10.0-ce   
swarm-manager    -        amazonec2   Running   tcp://13.112.139.104:2376   swarm-manager (master)   v17.10.0-ce   
swarm-node1      -        amazonec2   Running   tcp://13.230.3.210:2376     swarm-manager            v17.10.0-ce   
swarm-node2      -        amazonec2   Running   tcp://52.68.237.52:2376     swarm-manager            v17.10.0-ce  

-> 全て Public IP なのが気になる…

$ docker-machine ssh swarm-manager
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-1020-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

118 packages can be updated.
42 updates are security updates.

swarm-manager の待ち受けポートを確認する。

ubuntu@swarm-manager:~$ sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 10.1.11.136:7946        0.0.0.0:*               LISTEN      10221/dockerd   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1330/sshd       
tcp6       0      0 :::2376                 :::*                    LISTEN      10221/dockerd   
tcp6       0      0 :::3376                 :::*                    LISTEN      10482/docker-proxy
tcp6       0      0 :::22                   :::*                    LISTEN      1330/sshd 

2376 で Docker ( dockerd ) が、3376 で Swarm マネージャー ( docker-proxy ) が待ち受けている。
Docker クライアントは 3376 番の Swarm マネージャーに接続することで、Swarm クラスタを利用できる。

consul でも node の情報に関する key が登録されている。

f:id:shiro_kochi:2018××××××××:plain:w100:left

-> ここではなぜか Private IP が指定されている…。どこかのレイヤーがよしなにやってくれているようだが、そこまでは追求しないでおくか。

Docker Swarm を利用する

以下のコマンドで Swarm クラスタの状態を確認できる。

$ eval $(docker-machine env --swarm swarm-manager)
$ docker info
Containers: 4
 Running: 4
 Paused: 0
 Stopped: 0
Images: 3
Server Version: swarm/1.2.8
Role: primary
Strategy: spread
Filters: health, port, containerslots, dependency, affinity, constraint, whitelist
Nodes: 3
 swarm-manager: 13.112.139.104:2376
  └ ID: 72NB:ROJB:MVQ5:5626:BDNQ:6PVS:IGCF:Y6LE:LT3H:WBPN:43CZ:DYGK|13.112.139.104:2376
  └ Status: Healthy
  └ Containers: 2 (2 Running, 0 Paused, 0 Stopped)
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 8.185 GiB
  └ Labels: kernelversion=4.4.0-1020-aws, operatingsystem=Ubuntu 16.04.2 LTS, ostype=linux, provider=amazonec2, storagedriver=aufs
  └ UpdatedAt: 2017-11-07T17:00:42Z
  └ ServerVersion: 17.10.0-ce
 swarm-node1: 13.230.3.210:2376
  └ ID: EKS3:RI3Y:R2OU:4RM7:7PZV:5SST:5HYI:GFVM:LYTT:GFMX:3NGU:TS5I|13.230.3.210:2376
  └ Status: Healthy
  └ Containers: 1 (1 Running, 0 Paused, 0 Stopped)
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 8.185 GiB
  └ Labels: kernelversion=4.4.0-1020-aws, operatingsystem=Ubuntu 16.04.2 LTS, ostype=linux, provider=amazonec2, storagedriver=aufs
  └ UpdatedAt: 2017-11-07T17:00:27Z
  └ ServerVersion: 17.10.0-ce
 swarm-node2: 52.68.237.52:2376
  └ ID: B2PQ:KEO6:PF6Q:GZCN:GPQL:MRPA:YZM5:DEW3:SZLF:O5QE:K7KS:NJCH|52.68.237.52:2376
  └ Status: Healthy
  └ Containers: 1 (1 Running, 0 Paused, 0 Stopped)
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 8.185 GiB
  └ Labels: kernelversion=4.4.0-1020-aws, operatingsystem=Ubuntu 16.04.2 LTS, ostype=linux, provider=amazonec2, storagedriver=aufs
  └ UpdatedAt: 2017-11-07T17:00:40Z
  └ ServerVersion: 17.10.0-ce
Plugins: 
 Volume: 
 Network: 
 Log: 
Swarm: 
 NodeID: 
 Is Manager: false
 Node Address: 
Kernel Version: 4.4.0-1020-aws
Operating System: linux
Architecture: amd64
CPUs: 6
Total Memory: 24.56GiB
Name: d128bd6f0925
Docker Root Dir: 
Debug Mode (client): false
Debug Mode (server): false
Experimental: false
Live Restore Enabled: false

WARNING: No kernel memory limit support

swarm-manager 、swarm-node1 、swarm-node2 で構成されるクラスタであることが確認できる。
コンテナも確認。

docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                     NAMES
af344e852149        swarm:latest        "/swarm join --adv..."   21 minutes ago      Up 21 minutes       2375/tcp                                  swarm-node2/swarm-agent
7e37c2f772e2        swarm:latest        "/swarm join --adv..."   21 minutes ago      Up 21 minutes       2375/tcp                                  swarm-node1/swarm-agent
c366400e9c30        swarm:latest        "/swarm join --adv..."   23 minutes ago      Up 23 minutes       2375/tcp                                  swarm-manager/swarm-agent
d128bd6f0925        swarm:latest        "/swarm manage --t..."   23 minutes ago      Up 23 minutes       2375/tcp, 13.112.139.104:3376->3376/tcp   swarm-manager/swarm-agent-master

-> Swarm クラスタ周りのコンテナが確認できる。

試しに nginx コンテナを 6 個動かす。

$ docker run -d nginx
b81c5abe67ed956a61b0a0dda98bcd0399dca6116ed5d99d9f35212bc2763683
$ docker run -d nginx
9dc4c90e580e036f80a947e7a0b8cc408b05ed58ed2590a644a276fa7c44ff99
$ docker run -d nginx
631f5867b08e75f9723f2d9800d0601929276f2301a5f15c4e844395932fa52e
$ docker run -d nginx
9e6fbf5ff31484789a9baadbe8bafe5b58557239701517da1430c341cc80c78e
$ docker run -d nginx
10e8c8859a62c14f0a62fc8ff905e9a875502968d853c46804567ee276fa2b8e
$ docker run -d nginx
6a1bfbf4af43ef31a7a7a7c17fea6951aa2fbf7a6a3131566c18cafe54b85834
$ docker run -d httpd

この際最初の三つはそれぞれの Docker ホストのローカルにイメージが存在しないため、ちょっと時間がかかる。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
6a1bfbf4af43        nginx               "nginx -g 'daemon ..."   2 minutes ago       Up 2 minutes        80/tcp              swarm-node1/eager_ride
10e8c8859a62        nginx               "nginx -g 'daemon ..."   2 minutes ago       Up 2 minutes        80/tcp              swarm-node2/lucid_murdock
9e6fbf5ff314        nginx               "nginx -g 'daemon ..."   2 minutes ago       Up 2 minutes        80/tcp              swarm-node1/focused_einstein
631f5867b08e        nginx               "nginx -g 'daemon ..."   2 minutes ago       Up 2 minutes        80/tcp              swarm-manager/zen_franklin
9dc4c90e580e        nginx               "nginx -g 'daemon ..."   3 minutes ago       Up 3 minutes        80/tcp              swarm-node2/nervous_northcutt
b81c5abe67ed        nginx               "nginx -g 'daemon ..."   3 minutes ago       Up 3 minutes        80/tcp              swarm-node1/suspicious_stallman

-> 三つのノードに分散されていることがわかる。


 © 2023, Dealing with Ambiguity