Edited at

Docker Swarm (Swarm Mode) チュートリアルをしてみる

More than 1 year has passed since last update.

Docker Swarm (Swarm Mode) のチュートリアル Getting started with swarm mode をAWS上でやってみたので日本語でまとめです。


何がうれしいの?


  • ノード (サーバー) を跨いで Dockerサービス のデプロイ/アップデートができます

  • 各ノードへの公開アクセスを Swarm Load Balancer が適切なノードのコンテナにリクエストを振り分けてくれます


    • たとえ コンテナが一つも動いていないノードにアクセス しても、別のノードのコンテナがレスポンスを返してくれます

    • 内部のサービス間のオーケストレーションも Swarm Load Balancer がしてくれている様です



  • サービスの Rolling Update が出来ます

  • (他の似たOSSと比べて) 非常にシンプルで扱いやすいです

ingress-routing-mesh.png


※ docker.com 公式より, Swarm Load Balancer の図。



分からなかったこと

Rollling Update は処理中のリクエストが全て完了するのを待ってからアップデートを開始してくれるか?


AWSで言うところの ELB > Connection Draining の動きになるか?

誰か教えて下さい〜 m(_ _)m



チュートリアルまとめ

Getting started with swarm mode を色々と端折って説明します。


ポートを開ける (Security Groups)

各サーバーのポートを開けます。AWSの Security Groups では以下の様になります。

プロトコル
ポート範囲
ソース
Remarks

TCP
8080
0.0.0.0/0
Nginxコンテナ用の公開ポート

TCP
22
0.0.0.0/0
SSH接続

TCP
2377
{self-group-id}
Swarmクラスタ管理の通信に利用

TCP
7946
{self-group-id}
Routing mesh (Swarm Load Balancer)

UDP
7946
{self-group-id}
Routing mesh (Swarm Load Balancer)

UDP
4789
{self-group-id}
Routing mesh (Swarm Load Balancer)


ノード (サーバー) を起動します

AWS Console から3台のインスタンスを起動します。例えば以下のような感じです。

予めTerminalを3つ開いておき、SSHでログインを済ませておくと後の手順が楽です。

役割
Unix Hostname
IP

manager
ip-172-30-1-100
172.30.1.100

worker1
ip-172-30-1-200
172.30.1.200

worker2
ip-172-30-1-201
172.30.1.201


Hostname は分かりやすさの為に書いています。手順上重要ではないです



managerノードを起動する

managerノード 172.30.1.100 で以下のコマンドを実行します。

$ docker swarm init --advertise-addr 172.30.1.100


Swarm initialized: current node (udhy6l2u7e2tjo3tstmnz6tiu) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join \
--token SWMTKN-1-67w211zr8eu6h86cfdy09liwlbc6id4nlxrwr0d8u8fcn1x95u-93n335bihesdnwz6650y2ynmy \
172.30.1.100:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.


workerノードをmanagerノードにjoinする

worker1ノード 172.30.1.200, worker2ノード 172.30.1.201 で以下のコマンドを実行します。


--token ... が毎回違うと思いますので、前手順でConsole出力された物をコピペして下さい


$ docker swarm join \

--token SWMTKN-1-67w211zr8eu6h86cfdy09liwlbc6id4nlxrwr0d8u8fcn1x95u-93n335bihesdnwz6650y2ynmy \
172.30.1.100:2377

This node joined a swarm as a worker.


Swarmのノード状態を確認する

以下のコマンドでSwarmのノード状態を確認できます。workerノードからも確認が可能で、今いるノードに * が付いています。

$ docker node ls


ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
udhy6l2u7e2tjo3tstmnz6tiu * ip-172-30-1-100 Ready Active Leader
zsj8brmyynj67bqlw4qhvpgn9 ip-172-30-1-200 Ready Active
p2jfiueccxcqmtt1wqe4r5kvd ip-172-30-1-201 Ready Active


サービスをデプロイする

コマンド docker service create {イメージ} でデプロイします。

$ docker service create \

--replicas 3 \
--name redis \
--update-delay 10s \
redis:3.0.6

q9b5a65fkms8oix50bt487j5c

コマンド docker service ps {サービス名} で確認できます。3つのコンテナがそれぞれ別のノードで動いている事が分かります。

$ docker service ps redis


ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
2jwzoi4i2r3d redis.1 redis:3.0.6 ip-172-30-1-100 Running Running about a minute ago
1a402z122056 redis.2 redis:3.0.6 ip-172-30-1-200 Running Running about a minute ago
thhbs8870wnk redis.3 redis:3.0.6 ip-172-30-1-201 Running Running about a minute ago


サービスを Rolling Update する

コマンド docker service update --image {イメージ} {サービス名}Rolling Update をします。

$ docker service update --image redis:3.0.7 redis


redis

古いコンテナが破棄され、新しいコンテナに交換された事が分かります。デフォルトでは1コンテナずつ順にアップデートされます。

$ docker service ps redis

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
imw1jzgdshta redis.1 redis:3.0.7 ip-172-30-1-100 Running Running 24 seconds ago
2jwzoi4i2r3d \_ redis.1 redis:3.0.6 ip-172-30-1-100 Shutdown Shutdown 25 seconds ago
vr5u12jfpe07 redis.2 redis:3.0.7 ip-172-30-1-200 Running Running 36 seconds ago
1a402z122056 \_ redis.2 redis:3.0.6 ip-172-30-1-200 Shutdown Shutdown 36 seconds ago
py37p0ip7mgs redis.3 redis:3.0.7 ip-172-30-1-201 Running Running 12 seconds ago
thhbs8870wnk \_ redis.3 redis:3.0.6 ip-172-30-1-201 Shutdown Shutdown 13 seconds ago


サービスを削除する

コマンド docker service rm {サービス名} でサービスを破棄します。

$ docker service rm redis


redis

なくなっています。

$ docker service ps redis


Error: No such service: redis


実際にコンテナを落とすのには数秒時間がかかるので、docker ps でローカルノードの停止処理中のコンテナを確認できます



Routing mesh (Swarm Load Balancer)

Swarmノード上 では Swarm Load Balancer が動いており、サービスの公開ポート (フォワードしたホストOSのポート) へのアクセスは適切なコンテナに自動的に割り振りされます。

ingress-routing-mesh.png


※ docker.com 公式より。図中のIPと本記事中のIPは異なります。ごめんなさい


Nginxサービスを2コンテナで起動します。ホストOSの :8080 を公開ポートに割り当てています。

$ docker service create \

--name my-web \
--publish 8080:80 \
--replicas 2 \
nginx

utj6pvxbcw7wjlqhlaylf2wyg

3つのノードのうち、2つのノード (worker1, worker2) にコンテナがデプロイされました。

$ docker service ps my-web


ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
rom8aei8b8ye my-web.1 nginx:latest ip-172-30-1-200 Running Running 7 seconds ago
5sd5szh49gvg my-web.2 nginx:latest ip-172-30-1-201 Running Running 7 seconds ago

コンテナがデプロイされたノード (worker1) のNginxに curl でアクセスしてみます。

$ curl 172.30.1.200:8080


<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

コンテナが一切動いていないノード (manager) も同じ様にアクセスしてちゃんとレスポンスが返ります!

$ curl 172.30.1.100:8080


<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...