LoginSignup
2
2

More than 5 years have passed since last update.

Swarm cluster with multiple Consul nodes

Last updated at Posted at 2016-05-02

この投稿 (Docker Swarm Cluster without docker-machine)を書いている時に思った。SwarmプロセスをHAで複数立ち上げても、この構成ではConsulプロセスが一つしかないからConsulが死んだらサービス停止だと。Consul自体は複数ノードで運用できる (詳しくはこちら)ので、今回は複数ノードで立ち上がっているConsulとSwarmをどのように組み合わせるか実験してみた。

結論から言ってしまうと、Swarmプロセスを起動時に紐付けるConsulノードは一つしか記述できないようだ。Docker Swarm Discoveryの例にEtcdはswarm join --advertise=<node_ip:2375> etcd://<etcd_addr1>,<etcd_addr2>/<optional path prefix>とあるのに対し、Consulではswarm join --advertise=<node_ip:2375> consul://<consul_addr>/<optional path prefix>とあり、いかにも複数ノード記述できなそう。実際にdocker/libkv/store/consul/consul.goに次のような記述がある。

var (
    // ErrMultipleEndpointsUnsupported is thrown when there are
    // multiple endpoints specified for Consul
    ErrMultipleEndpointsUnsupported = errors.New("consul does not support multiple endpoints")

    // ErrSessionRenew is thrown when the session can't be
    // renewed because the Consul version does not support sessions
    ErrSessionRenew = errors.New("cannot set or renew session for ttl, unable to operate on sessions")
)
<snip>
func New(endpoints []string, options *store.Config) (store.Store, error) {
    if len(endpoints) > 1 {
        return nil, ErrMultipleEndpointsUnsupported
    }

ということで、Swarm起動時に紐付けたConsulノードが行方不明になった場合、そのノードを利用していたSwarmプロセスはService Discoveryを出来なくなってしまう。これでは話が終わってしまうので、ConsulノードをServerとClientの組合せとし、ConsulのClientノードをproxyとして見立ててSwarmプロセスと紐付けることを試してみた。proxyが落ちれば、そのproxyと紐付けられたSwarmももちろんサービス停止となる。構成図は次の通り。

swarm-consul2.PNG

7つのVMを利用する。Consul用に10.0.1.0/24のアドレスを割り当てた。一覧は次の通り。

VM name IP address IP address for consul
consul-server1 192.168.209.168 10.0.1.129
consul-server2 192.168.209.169 10.0.1.130
consul-server3 192.168.209.171 10.0.1.134
consul-client 192.168.209.170 10.0.1.131
swarm-mgr 192.168.209.138 10.0.1.128
swarm-node1 192.168.209.166 10.0.1.132
swarm-node2 192.168.209.167 10.0.1.133

(ああ、めんどくさい。)

では、早速Consulクラスターを立ち上げる。

consul-server1
$ docker run --rm progrium/consul cmd:run 10.0.1.129 -d
eval docker run --name consul -h $HOSTNAME      -p 10.0.1.129:8300:8300         \
-p 10.0.1.129:8301:8301         -p 10.0.1.129:8301:8301/udp     -p 10.0.1.129:8302:8302 \
-p 10.0.1.129:8302:8302/udp      -p 10.0.1.129:8400:8400         -p 10.0.1.129:8500:8500 \
-p 172.17.0.1:53:53     -p 172.17.0.1:53:53/udp         -d      progrium/consul \
-server -advertise 10.0.1.129 -bootstrap-expect 3

progrium/consul cmd:runでこのようにevalな形で実行形式の文字列を返してくれる。以下を実際には実行する。

consul-server1
$ docker run --name consul1 -p 10.0.1.129:8300:8300 \
                            -p 10.0.1.129:8301:8301 \
                            -p 10.0.1.129:8301:8301/udp \
                            -p 10.0.1.129:8302:8302 \
                            -p 10.0.1.129:8302:8302/udp \
                            -p 10.0.1.129:8400:8400 \
                            -p 10.0.1.129:8500:8500 \
                            -p 172.17.0.1:53:53 \
                            -p 172.17.0.1:53:53/udp \
                            -d progrium/consul -server -advertise 10.0.1.129 \
                            -bootstrap-expect 3

consul-server2consul-server3をConsulクラスターにjoinさせる。

consul-server2
$ docker run --name consul2 -p 10.0.1.130:8300:8300 \
                            -p 10.0.1.130:8301:8301 \
                            -p 10.0.1.130:8301:8301/udp \
                            -p 10.0.1.130:8302:8302 \
                            -p 10.0.1.130:8302:8302/udp \
                            -p 10.0.1.130:8400:8400 \
                            -p 10.0.1.130:8500:8500 \
                            -p 172.17.0.1:53:53 \
                            -p 172.17.0.1:53:53/udp \
                            -d progrium/consul -server -advertise 10.0.1.130 \
                            -join 10.0.1.129
consul-server3
$ docker run --name consul3 -p 10.0.1.134:8300:8300 \
                            -p 10.0.1.134:8301:8301 \
                            -p 10.0.1.134:8301:8301/udp \
                            -p 10.0.1.134:8302:8302 \
                            -p 10.0.1.134:8302:8302/udp \
                            -p 10.0.1.134:8400:8400 \
                            -p 10.0.1.134:8500:8500 \
                            -p 172.17.0.1:53:53 \
                            -p 172.17.0.1:53:53/udp \
                            -d progrium/consul -server -advertise 10.0.1.134 \
                            -join 10.0.1.129

最後にconsul-clinetをクライアントとしてjoinさせる。-serverの指定がなくなっただけ。

consul-client
$ docker run --name consul-cli -p 10.0.1.131:8300:8300 \
                               -p 10.0.1.131:8301:8301 \
                               -p 10.0.1.131:8301:8301/udp \
                               -p 10.0.1.131:8302:8302 \
                               -p 10.0.1.131:8302:8302/udp \
                               -p 10.0.1.131:8400:8400 \
                               -p 10.0.1.131:8500:8500 \
                               -p 172.17.0.1:53:53 \
                               -p 172.17.0.1:53:53/udp \
                               -d progrium/consul -advertise 10.0.1.131 \
                               -join 10.0.1.129

Consulクラスターのmemberを確認してみる。大丈夫そう。

consul-server1
$ docker exec consul1 consul members
Node          Address          Status  Type    Build  Protocol  DC
1011d34dc1c5  10.0.1.129:8301  alive   server  0.5.2  2         dc1
b0d93c5dd007  10.0.1.130:8301  alive   server  0.5.2  2         dc1
c277ab2f8165  10.0.1.134:8301  alive   server  0.5.2  2         dc1
375a31f7fb52  10.0.1.131:8301  alive   client  0.5.2  2         dc1

ではいよいよSwarm Managerを立ち上げる。Consulのbindingにはconsul-client (10.0.1.131)を指定する。

swarm-manager
$ docker run --restart=unless-stopped -d -p 3375:2375 swarm manage \
--replication --advertise 192.168.209.138:3375 consul://10.0.1.131:8500
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
6461f48b1b04        swarm               "/swarm manage --repl"   4 seconds ago       Up 3 seconds        0.0.0.0:3375->2375/tcp   tiny_raman

最後にswarm nodeを追加する。docker infoの結果からきちんと追加されたことが分かる。

swarm-manager
$ docker -H=tcp://192.168.209.166:2375 run -d swarm join \
--advertise=192.168.209.166:2375 consul://10.0.1.131:8500
$ docker -H=tcp://192.168.209.167:2375 run -d swarm join \
--advertise=192.168.209.167:2375 consul://10.0.1.131:8500
$ DOCKER_HOST=192.168.209.138:3375 docker info
Containers: 27
 Running: 2
 Paused: 0
 Stopped: 25
Images: 14
Server Version: swarm/1.2.0
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 2
 ubu-swarm-node1: 192.168.209.166:2375
  └ Status: Healthy
  └ Containers: 15
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 1 GiB / 4.047 GiB
  └ Labels: executiondriver=, kernelversion=3.13.0-85-generic, operatingsystem=Ubuntu 14.04.4 LTS, storagedriver=aufs
  └ Error: (none)
  └ UpdatedAt: 2016-05-02T14:49:12Z
  └ ServerVersion: 1.11.0
 ubu-swarm-node2: 192.168.209.167:2375
  └ Status: Healthy
  └ Containers: 12
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 1 GiB / 4.047 GiB
  └ Labels: executiondriver=, kernelversion=3.13.0-85-generic, operatingsystem=Ubuntu 14.04.4 LTS, storagedriver=aufs
  └ Error: (none)
  └ UpdatedAt: 2016-05-02T14:48:49Z
  └ ServerVersion: 1.11.0
Plugins:
 Volume:
 Network:
Kernel Version: 3.13.0-85-generic
Operating System: linux
Architecture: amd64
CPUs: 4
Total Memory: 8.094 GiB
Name: 6461f48b1b04
Docker Root Dir:
Debug mode (client): false
Debug mode (server): false
WARNING: No kernel memory limit support

適当にコンテナを起動してみる。

swarm-manager
$ DOCKER_HOST=192.168.209.138:3375 docker run -dit ubuntu /bin/bash
$ DOCKER_HOST=192.168.209.138:3375 docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9bd2e4eccc01        ubuntu              "/bin/bash"         5 seconds ago       Up 4 seconds                            ubu-swarm-node2/hungry_archimedes
$ DOCKER_HOST=192.168.209.138:3375 docker exec -it ubu-swarm-node2/hungry_archimedes bash
root@9bd2e4eccc01:/#

consul-server1のconsulを落としてみる。

consul-server1
$ docker stop consul1

次のように、落とした直後はErrorが返ってくるが、leader electionが実行されると処理を継続することができた。ちなみにConsulサーバーが2台構成の場合、1つを落とすとleader electionが出来ずswarmの処理は停止してしまう。3台以上のサーバーが必要らしい。

swarm-manager
$ DOCKER_HOST=192.168.209.138:3375 docker ps
Error response from daemon: No elected primary cluster manager
$ DOCKER_HOST=192.168.209.138:3375 docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
66a76e873e51        ubuntu              "/bin/bash"         56 seconds ago      Up 55 seconds                           ubu-swarm-node2/drunk_galileo

consul-cliのconsulを落としてみる。

consul-cli
$ docker stop consul-cli

冒頭に述べたようにこの場合はswarmの処理を継続できない。

swarm-manager
$ DOCKER_HOST=192.168.209.138:3375 docker ps
Error response from daemon: No elected primary cluster manager

おしまい。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2