听说了最大的更新后,我决定试试Docker1.12
ということで、タイトル通り、過去最大のupdateと言われているDocker1.12の気になる機能を試しました。
meetup等でDocker社の人の話を聞いた内容や公式ドキュメントベースで気になった箇所のみ試します。
ちなみに後方互換性は保たれているので、以下で出てくるswarm init等のコマンドを使わない限り今まで通り使えるそうです。
自分が気になったところを試しただけなので、網羅的な更新一覧および、内部の仕組みは公式ページなり、いつも訳して下さっている前佛さんの日本語訳を参考にしてください。
GitHub上のリリース情報
日本語訳
Docker Built-in Orchestration Ready for Production: Docker 1.12 Goes GA
日本語訳
Docker 1.12: Now with Built-in Orchestration!
日本語訳
あとはDockerConの動画とかも沢山あるけど多すぎるので、先日行われたオンラインmeetupの動画がまとまっててオススメです。
というか、このポストはほぼオンラインmeetup及び、ほぼ同じ内容のSanta Claraのmeetupで紹介されてた機能の紹介ですw
环境
以下の環境はLinuxで行いました。dockerはインストール済みと仮定します。dockerrepoを追加していれば、aptでもdnfでも最新版が入るはずです。以下のデモではDigitalOceanを使いますがVirtualBoxでもAWSでも何でも大丈夫かと思います。DigitalOceanの場合はこちらから登録すると今回動かす分くらいのクレジットは貰えます。(私にもクレジットが入るのでそーゆーのがイヤな方は普通にトップから登録してください)
また、以下のポートが開いている必要があります。(DigitalOceanでは設定不要ですが、ipv6有効になってたりするとトラブルかもしれません)
-
- TCP: 2377, 7946, 4789
- UDP: 7946, 4789
尝试完整进行Swarm mode的教程体验一遍。
首先,我会试着用教程中的Swarm Mode功能一一地进行尝试。如果你已经完成了类似的操作,那么你可以不必阅读这部分。
在教程中,每个节点都使用docker命令,但由于繁琐的ssh操作,我想使用docker-machine代替。
curl -L https://github.com/docker/machine/releases/download/v0.8.0/docker-machine-`uname -s`-`uname -m` >~/path/to/docker-machine && chmod +x ~/path/to/docker-machine
首先创建一个节点作为管理节点。请根据需要适当设置DIGITALOCEAN_API_TOKEN。(以后相同)
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} manager
以swarm模式启动。请在”advertise-addr”参数中指定管理者(manager)的IP地址,可通过使用docker-machine ls等命令进行查询。
eval $(docker-machine env manager)
docker swarm init --advertise-addr 192.241.219.207
以下是获得worker和manager的追加方法的输出。
Swarm initialized: current node (djvtufr82caej8ebysdbsj0ov) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-46kek56vwx6f7y9d0tqci7zrly11b2h8u0k31xhx0kaxx4f70o-6k4xdghyave5qci4o94s8b433 \
192.241.219.207:2377
To add a manager to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-46kek56vwx6f7y9d0tqci7zrly11b2h8u0k31xhx0kaxx4f70o-dxsejlrazkr0jaznx4u9o8yl7 \
192.241.219.207:2377
可以通过运行”docker info”命令来确认Swarm模式处于活动状态,并且”IsManager”属性为真。
docker info
Swarm: active
IsManager: true
您可以使用docker node ls命令来确认节点的状态。
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
djvtufr82caej8ebysdbsj0ov * manager Ready Active Leader
接下来,我会制作两台专供工人使用的机器。
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} worker1
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} worker2
参考先前创建经理时得到的结果,我们试着添加一个工人。
eval $(docker-machine env worker1)
docker swarm join --token SWMTKN-1-46kek56vwx6f7y9d0tqci7zrly11b2h8u0k31xhx0kaxx4f70o-6k4xdghyave5qci4o94s8b433 192.241.219.207:2377
eval $(docker-machine env worker2)
docker swarm join --token SWMTKN-1-46kek56vwx6f7y9d0tqci7zrly11b2h8u0k31xhx0kaxx4f70o-6k4xdghyave5qci4o94s8b433 192.241.219.207:2377
我会再次在管理者中运行docker node ls命令并确认结果。
eval $(docker-machine env manager)
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
as3dl417gpz9795aedxa970th worker2 Ready Active
asqs3rls6pc32izn74zkkiysd worker1 Ready Active
djvtufr82caej8ebysdbsj0ov * manager Ready Active Leader
接下来,我们将创建一个服务。
docker service create --replicas 1 --name helloworld alpine ping docker.com
这个服务的名字是helloworld,只有一个容器,使用alpine镜像,执行ping docker.com命令。
使用各种命令来确认结果。
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
16hidqk9zown helloworld 1/1 alpine ping docker.com
$ docker service inspect --pretty helloworld
ID: 16hidqk9zown8qpqt424yzwxc
Name: helloworld
Mode: Replicated
Replicas: 1
Placement:
UpdateConfig:
Parallelism: 1
On failure: pause
ContainerSpec:
Image: alpine
Args: ping docker.com
Resources:
$ docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
bdbz6k194232czgn0rrvkklkw helloworld.1 alpine manager Running Running 2 minutes ago
我尝试调整规模。
$ docker service scale helloworld=5
helloworld scaled to 5
$ docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
bdbz6k194232czgn0rrvkklkw helloworld.1 alpine manager Running Running 7 minutes ago
6qhabtifgay4zzzduqabiiwhe helloworld.2 alpine worker1 Running Running 12 seconds ago
33zyifha6z47dvnve8g48g9dh helloworld.3 alpine manager Running Running 13 seconds ago
7cobt9a7umy33h1flgzor0j1s helloworld.4 alpine worker2 Running Running 11 seconds ago
d8jnt9u5yn85t8bjcfp58cmau helloworld.5 alpine worker1 Running Running 12 seconds ago
我要删除服务。
$ docker service rm helloworld
helloworld
当您尝试检查服务状态时,由于已被删除,将导致出现错误。
$ docker service ps helloworld
Error: No such service: helloworld
接下来,我将尝试滚动更新。
首先,我会运行3个Redis容器,并将更新延迟设置为10秒。
$ docker service create \
--replicas 3 \
--name redis \
--update-delay 10s \
redis:3.0.6
我們需要確認狀態。
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
bq9xwhwbryx7i180fx1zw6pb2 redis.1 redis:3.0.6 worker2 Running Preparing 16 seconds ago
86mgm09e7vb8hzp7aki87fxcd redis.2 redis:3.0.6 worker1 Running Running 4 seconds ago
0aphe5lz4w3mrn9wx2rmdnykh redis.3 redis:3.0.6 manager Running Running 3 seconds ago
$ docker service inspect redis --pretty
ID: 6ue7ncgimxwsnarvvdgw7431d
Name: redis
Mode: Replicated
Replicas: 3
Placement:
UpdateConfig:
Parallelism: 1
Delay: 10s
On failure: pause
ContainerSpec:
Image: redis:3.0.6
Resources:
我打算对Redis 3.0.7进行滚动更新。
$ docker service update --image redis:3.0.7 redis
首先,您可以通过以下内容了解到更新正在进行中。
$ docker service inspect redis --pretty
ID: 6ue7ncgimxwsnarvvdgw7431d
Name: redis
Mode: Replicated
Replicas: 3
Update status:
State: updating
Started: 9 seconds ago
Message: update in progress
Placement:
UpdateConfig:
Parallelism: 1
Delay: 10s
On failure: pause
ContainerSpec:
Image: redis:3.0.7
Resources:
因为每10秒会进行滚动更新,所以请适当间隔一段时间来确认结果,可以看到以下的滚动更新情况。
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
bq9xwhwbryx7i180fx1zw6pb2 redis.1 redis:3.0.6 worker2 Running Running 2 minutes ago
86mgm09e7vb8hzp7aki87fxcd redis.2 redis:3.0.6 worker1 Running Running 2 minutes ago
1kdq4xygokkeeycdhgw1f9zpc redis.3 redis:3.0.7 manager Running Running 4 seconds ago
0aphe5lz4w3mrn9wx2rmdnykh \_ redis.3 redis:3.0.6 manager Shutdown Shutdown 16 seconds ago
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
bq9xwhwbryx7i180fx1zw6pb2 redis.1 redis:3.0.6 worker2 Running Running 2 minutes ago
5tn67yo2r8rdt9sx4tbmk6h3x redis.2 redis:3.0.7 worker2 Running Running 9 seconds ago
86mgm09e7vb8hzp7aki87fxcd \_ redis.2 redis:3.0.6 worker1 Shutdown Shutdown 25 seconds ago
1kdq4xygokkeeycdhgw1f9zpc redis.3 redis:3.0.7 manager Running Running 36 seconds ago
0aphe5lz4w3mrn9wx2rmdnykh \_ redis.3 redis:3.0.6 manager Shutdown Shutdown 47 seconds ago
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
a02h3iatx9dfwnkcl5doqette redis.1 redis:3.0.7 worker1 Running Running about a minute ago
bq9xwhwbryx7i180fx1zw6pb2 \_ redis.1 redis:3.0.6 worker2 Shutdown Shutdown about a minute ago
5tn67yo2r8rdt9sx4tbmk6h3x redis.2 redis:3.0.7 worker2 Running Running about a minute ago
86mgm09e7vb8hzp7aki87fxcd \_ redis.2 redis:3.0.6 worker1 Shutdown Shutdown 2 minutes ago
1kdq4xygokkeeycdhgw1f9zpc redis.3 redis:3.0.7 manager Running Running 2 minutes ago
0aphe5lz4w3mrn9wx2rmdnykh \_ redis.3 redis:3.0.6 manager Shutdown Shutdown 2 minutes ago
在结束之后,我们会再次确认状态。我们会看到更新已经完成。
$ docker service inspect redis --pretty
ID: 6ue7ncgimxwsnarvvdgw7431d
Name: redis
Mode: Replicated
Replicas: 3
Update status:
State: completed
Started: 2 minutes ago
Completed: about a minute ago
Message: update completed
Placement:
UpdateConfig:
Parallelism: 1
Delay: 10s
On failure: pause
ContainerSpec:
Image: redis:3.0.7
Resources:
我会删除该服务。
$ docker service rm redis
redis
$ docker service ps redis
Error: No such service: redis
接下来尝试进行Drain操作。把节点状态设置为Drain后,该节点将不再创建任何容器。
已经创建的容器将被移动到其他节点上。
$ docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.6
6w08p3j5ew7pg4nurc3ywdq2l
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
d4z5lw1sn8uiz21m0s2btgvc5 redis.1 redis:3.0.6 manager Running Running 8 seconds ago
ad3nqvbu357xjcao1wwdow2kf redis.2 redis:3.0.6 worker2 Running Running 7 seconds ago
0yndsykpbfsu4iegpxfuu900q redis.3 redis:3.0.6 worker1 Running Running 8 seconds ago
将工人1调到排水区。
$ docker node update --availability drain worker1
worker1
当确认节点状态时,可以发现它已被标记为”Drian”。
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
as3dl417gpz9795aedxa970th worker2 Ready Active
asqs3rls6pc32izn74zkkiysd worker1 Ready Drain
djvtufr82caej8ebysdbsj0ov * manager Ready Active Leader
serviceの状態を確認するとworker1で動いていたコンテナはmanagerに移動しているのが分かります。
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
d4z5lw1sn8uiz21m0s2btgvc5 redis.1 redis:3.0.6 manager Running Running about a minute ago
ad3nqvbu357xjcao1wwdow2kf redis.2 redis:3.0.6 worker2 Running Running about a minute ago
d8aehr5dad3u61d77iiun8gyj redis.3 redis:3.0.6 manager Running Running 50 seconds ago
0yndsykpbfsu4iegpxfuu900q \_ redis.3 redis:3.0.6 worker1 Shutdown Shutdown 50 seconds ago
我会将worker1重新设为活动状态。
$ docker node update --availability active worker1
worker1
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
as3dl417gpz9795aedxa970th worker2 Ready Active
asqs3rls6pc32izn74zkkiysd worker1 Ready Active
djvtufr82caej8ebysdbsj0ov * manager Ready Active Leader
移动的集装箱将不会返回,但在下次创建时,也将被分配给worker1。
Drainは色々使い方があるようで、例えば、メンテナンスするときなどには当然活用できるでしょう。
また、managerにはコンテナを作りたくないといった場合は、managerをDrainにすれば実現できます(もちろんlabel等を使っても同じことはできますが)。
暂时先删除所有节点。
docker-machine rm manager
docker-machine rm worker1
docker-machine rm worker2
经理的故障切换 de
接下来,我们将试验管理者的故障转移。
コンセンサスにはRaftが使われているので、奇数のmanagerが推奨されています。
ということで、managerとworkerを3台ずつ作ってみます。下記は出力結果を省略しています。
# docker-machineでmanagerとworkerを3台ずつ作成
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} manager1
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} manager2
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} manager3
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} worker1
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} worker2
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} worker3
# manager1でswarmモードを初期化
eval $(docker-machine env manager1)
docker swarm init --advertise-addr 104.236.176.63
# manager2,3を既存のswarmにmanagerとして追加
eval $(docker-machine env manager2)
docker swarm join \
--token SWMTKN-1-3pxkaylj5uubcwiu3a3d7e3zuwqabdbl2y7tf26c1wbbw4xnvy-9ed3sgq2agihmq7aewbvoim4e \
104.236.176.63:2377
eval $(docker-machine env manager3)
docker swarm join \
--token SWMTKN-1-3pxkaylj5uubcwiu3a3d7e3zuwqabdbl2y7tf26c1wbbw4xnvy-9ed3sgq2agihmq7aewbvoim4e \
104.236.176.63:2377
# worker1,2,3を既存のswarmにworkerとして追加
eval $(docker-machine env worker1)
docker swarm join \
--token SWMTKN-1-3pxkaylj5uubcwiu3a3d7e3zuwqabdbl2y7tf26c1wbbw4xnvy-619h8ucg44larxtqszj9080gx \
104.236.176.63:2377
eval $(docker-machine env worker2)
docker swarm join \
--token SWMTKN-1-3pxkaylj5uubcwiu3a3d7e3zuwqabdbl2y7tf26c1wbbw4xnvy-619h8ucg44larxtqszj9080gx \
104.236.176.63:2377
eval $(docker-machine env worker3)
docker swarm join \
--token SWMTKN-1-3pxkaylj5uubcwiu3a3d7e3zuwqabdbl2y7tf26c1wbbw4xnvy-619h8ucg44larxtqszj9080gx \
104.236.176.63:2377
結果を確認しておきます。
$ eval $(docker-machine env manager1)
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
0eapj2cat7ih6973k9ysapwz2 worker2 Ready Active
0inl859a5zuul7peoyjfjx9x8 worker3 Ready Active
6hfv3zrwrd5doma7s6tc7hs61 * manager1 Ready Active Leader
6snxc51snhhjzsin7qg0egobx manager2 Ready Active Reachable
7xj8a2ufn63k38j9aynfzbyl8 manager3 Ready Active Reachable
918ny04ls768sl33rl5n02qal worker1 Ready Active
おもむろにLeaderのmanagerを落としてみます。
docker-machine rm manager1
我会确认领导发生变化。
$ eval $(docker-machine env manager2)
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
0eapj2cat7ih6973k9ysapwz2 worker2 Ready Active
0inl859a5zuul7peoyjfjx9x8 worker3 Ready Active
6hfv3zrwrd5doma7s6tc7hs61 manager1 Down Active Unreachable
6snxc51snhhjzsin7qg0egobx * manager2 Ready Active Reachable
7xj8a2ufn63k38j9aynfzbyl8 manager3 Down Active Leader
918ny04ls768sl33rl5n02qal worker1 Down Active
managerは奇数推奨なのでこのような場合は一台追加するべきです。
managerの追加は先述のdocker swarm joinコマンドでもできますが、docker node promoteというコマンドを使うことでworkerをmanagerにpromoteすることができるようなので、こちらを試してみます。
$ docker node promote worker1
我会确认一下结果。
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
0eapj2cat7ih6973k9ysapwz2 worker2 Ready Active
0inl859a5zuul7peoyjfjx9x8 worker3 Ready Active
6hfv3zrwrd5doma7s6tc7hs61 manager1 Down Active Unreachable
6snxc51snhhjzsin7qg0egobx * manager2 Ready Active Reachable
7xj8a2ufn63k38j9aynfzbyl8 manager3 Ready Active Leader
918ny04ls768sl33rl5n02qal worker1 Ready Active Reachable
使用逆转命令时,还可以将经理降级为员工。
$ docker node demote manager3
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
0eapj2cat7ih6973k9ysapwz2 worker2 Ready Active
0inl859a5zuul7peoyjfjx9x8 worker3 Ready Active
6hfv3zrwrd5doma7s6tc7hs61 manager1 Down Active Unreachable
6snxc51snhhjzsin7qg0egobx * manager2 Ready Active Leader
7xj8a2ufn63k38j9aynfzbyl8 manager3 Ready Active
918ny04ls768sl33rl5n02qal worker1 Ready Active Reachable
ちなみにSTATUSの変化は1分くらいかけて、Unknown、Downと変わってからReadyに変わりました。
为了下一次示威,我会再次彻底肃清。
docker-machine rm manager1
docker-machine rm manager2
docker-machine rm manager3
docker-machine rm worker1
docker-machine rm worker2
docker-machine rm worker3
Routing meshを試す
当创建Routing mesh服务时,即使接收请求的节点上并未运行相应的服务容器,它也可以将请求重定向到正在运行容器的节点。
这次我将再次尝试以一个经理和三个工人的组合进行实验。
通过–engine-label指定标签,将worker1和2设定为env=production,将worker3设定为env=development,以供实验使用。
# docker-machineでノードを作成
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} manager
docker-machine create --engine-label env=production -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} worker1
docker-machine create --engine-label env=production -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} worker2
docker-machine create --engine-label env=development -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} worker3
# swarmの初期化とworkderの追加
eval $(docker-machine env manager)
docker swarm init --advertise-addr 162.243.146.81
eval $(docker-machine env worker1)
docker swarm join \
--token SWMTKN-1-3vh5e65rcvv5vbx10o456ikl6mmab7v5pgpebrilpejictw1kh-c5ewusty0safq5764gvgvknwl \
162.243.146.81:2377
eval $(docker-machine env worker2)
docker swarm join \
--token SWMTKN-1-3vh5e65rcvv5vbx10o456ikl6mmab7v5pgpebrilpejictw1kh-c5ewusty0safq5764gvgvknwl \
162.243.146.81:2377
eval $(docker-machine env worker3)
docker swarm join \
--token SWMTKN-1-3vh5e65rcvv5vbx10o456ikl6mmab7v5pgpebrilpejictw1kh-c5ewusty0safq5764gvgvknwl \
162.243.146.81:2377
创建一个Redis服务,以容器作为管理者启动。
docker service create \
--replicas 1 \
--name redis \
--update-delay 10s \
--publish 6379:6379 \
--constraint node.hostname==manager \
redis:latest
在工作的時候運行應用程式。
所使用的應用程式是之前在一篇文章中使用過的程式碼和容器。
每次访问,只需获取从REDIS访问时可变的计数器的值。
docker service create \
--replicas 2 \
--name app \
--update-delay 10s \
--publish 8000:8000 \
--env REDIS_HOST=162.243.146.81 \
--constraint engine.labels.env==production \
daikikohara/app01:v6
因为需要一些时间,所以我会等待docker service ps app命令执行完成并启动。
# これだとPrepareだからまだ
$ docker service ps app
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
7t31od5tkcey8cri9mbhp7elt app.1 daikikohara/app01:v6 worker2 Running Preparing 53 seconds ago
2s74twgjjxlrxlgz3v5zxy498 app.2 daikikohara/app01:v6 worker1 Running Preparing 53 seconds ago
# こうなればOK
$ docker service ps app
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
7t31od5tkcey8cri9mbhp7elt app.1 daikikohara/app01:v6 worker2 Running Running 3 minutes ago
2s74twgjjxlrxlgz3v5zxy498 app.2 daikikohara/app01:v6 worker1 Running Running 3 minutes ago
顺便提一下,根据上述结果可以看出,只有在将环境标签设为“production”的worker上才会运行容器。
我会使用curl命令访问每个worker节点,以确保能够获取计数器的值。
每个节点的IP地址如下。
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
manager * digitalocean Running tcp://162.243.146.81:2376 v1.12.0
worker1 - digitalocean Running tcp://107.170.250.177:2376 v1.12.0
worker2 - digitalocean Running tcp://107.170.233.85:2376 v1.12.0
worker3 - digitalocean Running tcp://104.131.132.105:2376 v1.12.0
如果向正在运行的worker1和worker2发送请求,自然会得到值。
$ curl http://107.170.250.177:8000
You have visited this page 1 times!
$ curl http://107.170.233.85:8000
You have visited this page 2 times!
使用路由网格,即使容器未在worker3上启动,也可以获取值。
$ curl http://104.131.132.105:8000
You have visited this page 3 times!
嗯,worker3指定了”development”的标签,所以我本以为无法获取它,但在swarm集群的节点上,似乎启用了所有路由网格。
我觉得如果能够设置只能获取指定服务以外的内容会更方便,所以我对未来抱有期望。(也许已经可以设置了吗?)
所以,实际上我只想将production的一个节点进行扩展,以确认反向的production worker也可以正常工作。但从根本上说,我们已经成功验证了,所以就这样结束吧~
健康检查
以上的Dockerfile中添加了HEALTHCHECK指令。使用HEALTHCHECK可以根据自定义逻辑对容器进行健康检查。我已经将名为app01的容器替换为以下内容的Dockerfile,并以v7标签进行发布。
FROM golang:1.6.3
ADD app /app
HEALTHCHECK --interval=10s --timeout=5s --retries=3 CMD curl http://localhost:8000 | grep "You have visited"
CMD /app
如果在上述情况下,以CMD指定的命令每10秒执行一次,在5秒内无法成功获得结果的情况发生连续3次,容器将被视为不健康。
所以,首先启动Redis容器。
docker service create \
--replicas 1 \
--name redis \
--update-delay 10s \
--publish 6379:6379 \
--constraint node.hostname==manager \
redis:latest
接下来启动应用程序。
docker service create \
--replicas 2 \
--name app \
--update-delay 10s \
--publish 8000:8000 \
--env REDIS_HOST=162.243.146.81 \
--constraint engine.labels.env==production \
daikikohara/app01:v7
我要停止redis服务。
docker service rm redis
由于上述的HEALTHCHECK失败,所以在一段时间后进行确认时可以发现,容器在多次尝试重新启动时仍然失败。
$ docker service ps app
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
7u1xdmznc4n1qmxn5m8noeu84 app.1 daikikohara/app01:v7 worker1 Ready Ready 3 seconds ago
82g81zthfgm0o4b8ylbegsvfr \_ app.1 daikikohara/app01:v7 worker1 Shutdown Failed 4 seconds ago "task: non-zero exit (2)"
9wlenwhsht77zcavdpw39ju7m \_ app.1 daikikohara/app01:v7 worker1 Shutdown Failed 10 seconds ago "task: non-zero exit (2)"
51zxip69n196202i0cqelurf5 \_ app.1 daikikohara/app01:v7 worker1 Shutdown Failed 16 seconds ago "task: non-zero exit (2)"
as4vhy7zxh78wj30k3w2b0cdp \_ app.1 daikikohara/app01:v7 worker1 Shutdown Failed 22 seconds ago "task: non-zero exit (2)"
2v1tmjx0qmh0x46pfvklns542 app.2 daikikohara/app01:v7 worker2 Running Starting less than a second ago
eqqdrefs7w63v239tr1gjy85g \_ app.2 daikikohara/app01:v7 worker2 Shutdown Failed 5 seconds ago "task: non-zero exit (2)"
2r17smeo78j1lppbu9n1z5z9h \_ app.2 daikikohara/app01:v7 worker2 Shutdown Failed 11 seconds ago "task: non-zero exit (2)"
5zkes80bq2wtp8h4b3d2qpora \_ app.2 daikikohara/app01:v7 worker2 Shutdown Failed 16 seconds ago "task: non-zero exit (2)"
e4s1lrwc1ainf5jfzfq1iqmg4 \_ app.2 daikikohara/app01:v7 worker2 Shutdown Failed 22 seconds ago "task: non-zero exit (2)"
重新启动Redis后,过一段时间再确认,两个容器都能保持运行状态。
$ docker service ps app
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
d39j1zw2fs2d1bc4o5tzc5q7n app.1 daikikohara/app01:v7 worker1 Running Running 2 minutes ago
9u8nmhwwmkczxqg9pjpcug214 \_ app.1 daikikohara/app01:v7 worker1 Shutdown Failed 2 minutes ago "task: non-zero exit (2)"
4yau7s92c0917penlazl5uuq0 \_ app.1 daikikohara/app01:v7 worker1 Shutdown Failed 2 minutes ago "task: non-zero exit (2)"
581y6jezbpr6cxwyynnqqvw97 \_ app.1 daikikohara/app01:v7 worker1 Shutdown Failed 2 minutes ago "task: non-zero exit (2)"
7u1xdmznc4n1qmxn5m8noeu84 \_ app.1 daikikohara/app01:v7 worker1 Shutdown Failed 3 minutes ago "task: non-zero exit (2)"
at0qqu7xhjz90ujmnmgminn00 app.2 daikikohara/app01:v7 worker2 Running Running 2 minutes ago
f0cq0x7ccq9d88dpspolx78db \_ app.2 daikikohara/app01:v7 worker2 Shutdown Failed 2 minutes ago "task: non-zero exit (2)"
4qpmgm93g899xu9rgr8rrqq30 \_ app.2 daikikohara/app01:v7 worker2 Shutdown Failed 2 minutes ago "task: non-zero exit (2)"
1ce8fu69ua6hnqnomho52vb1t \_ app.2 daikikohara/app01:v7 worker2 Shutdown Failed 2 minutes ago "task: non-zero exit (2)"
a5r6fkpme7elaj0qw3kln5zo3 \_ app.2 daikikohara/app01:v7 worker2 Shutdown Failed 2 minutes ago "task: non-zero exit (2)"
全球模式
在使用复制服务的情况下,每个节点上都会适当地分布式部署容器,并且通过使用全局模式,您可以确保在每个节点上都会运行一个容器。根据官方文档等,似乎假设需要在每个节点上运行必要的监控、病毒扫描等服务。
docker service create \
--name redis \
--mode global \
--publish 6379:6379 \
redis:latest
$ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
1fitx5g74ujssl9bjbhyz5nv3 redis redis:latest worker3 Running Preparing 7 seconds ago
1quo2c3c9fz3wll6cl57dao4b \_ redis redis:latest worker2 Running Preparing 7 seconds ago
5paactsnolafblrz0y6j8rhfs \_ redis redis:latest worker1 Running Preparing 7 seconds ago
coh5zcahl5jedozkqzgcx06g4 \_ redis redis:latest manager Running Running 6 seconds ago
通过这样的方式,我们确认了每个节点上都运行了一个容器。
其他引起注意的事项 tā de
-
- ノード間の通信がデフォルトでTLSになったらしいです。(参考)
pluginコマンドとかも気になるんですが、まだexperimentalな上にドキュメントがよく分からなかったので試してません。。。
如果有其他需要,我会追加和修正以上内容。