Help us understand the problem. What is going on with this article?

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

More than 3 years have 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>
...
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away