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

Docker Swarm を使ってみる

0. はじめに

このアドベントカレンダーで投稿しているのが、Docker の内容が続いていますが、Docker 触るの楽しいのでいいですよね。
前回の記事の、ある意味続きです。
書いててハイになってしまったので、ちょび長めです。

1. Docker Swarm って ?

タイトルにもある通り、今回のテーマは Docker Swarm です。
Docker コンテナを複数ホストにまたがって管理するための機能です。
公式の説明は以下の通り。

Docker Swarm 概要

Docker Swarm は Docker に対応するネイティブなクラスタリング用ツールです。
Docker Swarm は標準 Docker API で操作できます。
そのため、(1-1*) Docker ホスト群を集め、1つの仮想 Docker ホストとして扱えます
既に Docker デーモンと通信可能なツールであれば、Swarm を使うだけで、
(1-2*) 意識せずに複数のホストにスケール可能になります。

ポイントをピックアップすると、Docker Swarm で実現可能なのは以下の機能です。

1-1. クラスタ管理機能

複数台のマシンをネットワーク接続し、一つのまとまりとして管理する機能。
1台のホストだけではなく、複数のホストでひとつのシステムとしてみなすため、「こいつとこいつとあいつが仲間」なことを管理する機能です。

1-2. オーケストレーション機能

複数マシンを自動で管理する機能
詳細は後述しますが、要は生きているホストでだけコンテナを起動するように自動で調節してくれる機能です。

2. 用語解説

docker.png

2-1. Node

  • クラスタを構成するホストマシン
  • Node には MasterWorker の 2 つの種類が存在する

(図中: Docker Host)

2-2. Manager

  • Swarm cluster 内の Node を管理する機能をもつ
  • Worker としても動作可能

(図中: Manager)

2-3. Worker

  • 主にコンテナを実行する機能をもつ

(図中: Worker1 / Worker2)

2-4. Ingress Overlay Network

  • Swarm cluster を作成すると自動で構築されるネットワーク
  • 負荷分散の機能をもち、外部からのリクエストを個々の Node に振り分けることが可能

(図中: Ingress Overlay Network)

3. Docker Swarm の使われ方

例えば、Docker Swarm を使って Web サーバを構築したとします。
大量のアクセスが想定されるために、Cluster 内全体で、3 つの Nginx コンテナを各 Node にひとつずつ配置したと仮定します。
(具体的には、「Cluster で 3 つのコンテナを起動する」と設定で宣言すると、Docker Swarm でいい感じにコンテナを自動で配置してくれます。)

その時に何かしらの原因で Worker2 上のコンテナがダウンしてしまったら、Manager でそれを検知し、代わりに足りない 1 コンテナをWorker1 上で起動させるといったことが可能になります。
ここで注意すべき点は、新しく Worker1 で起動されるコンテナは、Worker2 で起動していたコンテナを移植する訳ではないため、Worker2 のコンテナがダウンする直前まで行なっていた処理を引き継ぐことはできません。
アプリの方で処理の整合性を担保する必要があります。

4. Swarm cluster の構築

ここから、先ほどの図の構成の Swarm cluster を構築していきます。

4-1. Docker Host の作成

// Manager, Worker1, Worker2 の Docker Host を作成
$ docker-machine create manager
$ docker-machine create worker1
$ docker-machine create worker2

// Docker Host の確認
// まだ作成しただけのため、Swarm cluster には参加していない
$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
manager   -        virtualbox   Running   tcp://192.168.99.120:2376           v19.03.5
worker1   -        virtualbox   Running   tcp://192.168.99.119:2376           v19.03.5
worker2   -        virtualbox   Running   tcp://192.168.99.121:2376           v19.03.5

これ以降の説明で操作対象のホストは以下のようにプロンプトで示します。

$           // 自分のローカルマシン
manager:~$  // Manager Node
worker1:~$  // Worker1 Node
worker2:~$  // Worker2 Node

docker コマンドの実行環境を切り替えるには、各ホストに docker-machine ssh で入ってから実行してもいいですが、
eval $(docker-machine env manager) のように実行すると、この場合は Manager Node で docker コマンドが実行されます。

4-2. 使用するポート

Swarm cluster では以下の以下のポートを使用します。
今回のように、各 Node をローカルの Virtual Box で作成した場合は特に気にすることはありませんが、EC2 などのパブリッククラウドの IaaS で環境構築する場合は、Firewall に穴あけする必要があります。
(そもそもの Firewall についてはこちらを参考にしてください。)

用途 ポート
cluster 管理通信 TCP 2377
Node 管理 TCP/UDP 7946
Overlay Network トラフィック UDP 4789

4-3. Master Node 初期化

manager:~$ docker swarm init --advertise-addr 192.168.99.120

--advertise-addr のオプションには、Manager ホストの IP アドレスを指定します。
このコマンドが実行されたホストは、Manager Node として機能するようになります。
実行すると以下のように表示されます。

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

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

    docker swarm join --token SWMTKN-1-3bz9m881m46n2yutt58hed77txrezoygmryetngxnxznuylzpd-8uih7cl56g2pm4wxrak2ssstb 192.168.99.120:2377

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

docker swarm join --token SWMTKN-1-3bz9m881m46n2yutt58hed77txrezoygmryetngxnxznuylzpd-8uih7cl56g2pm4wxrak2ssstb 192.168.99.120:2377 がこの Swarm cluster に Worker Node として参加するためのコマンドです。
コピって、Worker1 / Worker2 で実行します。

もし忘れてしまった場合でも、以下のように実行すれば確認ができます。

manager:~$ docker swarm join-token worker
To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-3bz9m881m46n2yutt58hed77txrezoygmryetngxnxznuylzpd-8uih7cl56g2pm4wxrak2ssstb 192.168.99.120:2377

4-4. Worker Node 初期化

Worker1 / Worker2 を Swarm cluster に参加させます。
先程コピっておいたコマンドを各ホストで実行するだけです。

worker1:~$ docker swarm join --token SWMTKN-1-3bz9m881m46n2yutt58hed77txrezoygmryetngxnxznuylzpd-8uih7cl56g2pm4wxrak2ssstb 192.168.99.120:2377
This node joined a swarm as a worker.

worker2:~$ docker swarm join --token SWMTKN-1-3bz9m881m46n2yutt58hed77txrezoygmryetngxnxznuylzpd-8uih7cl56g2pm4wxrak2ssstb 192.168.99.120:2377
This node joined a swarm as a worker.

これで Swarm cluster に参加することができました。
念の為、Swarm cluster に参加している Node を確認します。
以下のコマンドは、Master Node でしか実行できません。

manager:~$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
zieqitege0jreuax7qq7gtxp7 *   manager             Ready               Active              Leader              19.03.5
owrwun2quwqi78xyybxvmu52g     worker1             Ready               Active                                  19.03.5
zck9aun7xulmx8gutfmbq5bsq     worker2             Ready               Active                                  19.03.5

5. Service / Task

docker (1).png

Docker Swarm には、Service / Task という 2 つの概念があります。

5-1. Service

Service とは、クラスタ全体で管理するコンテナを定義したものです。
コンテナを生成する元となるイメージは何を使うのか? コンテナをいくつ起動するのか? などを定義します。
コンテナをいくつ起動するか? というのをreplicaといいます。

例えば、Swarm を使って Web Service を定義する場合、イメージとして Nginx を使用し、クラスタ全体で 3 つのコンテナを起動する状態を維持するように定義するといった感じです。

5-2. Task

Task とは Service の定義にしたがって実際に実行されるコンテナを表します。
上記の例で言うと、Node 上で実行される Nginx コンテナが Task にあたります。

5-3. Service の定義

manager:~$ docker  service create -d --name nginx --replicas 3 --publish 8080:80 nginx
q72x19ecceeisqk6xijhym5z2

ここでは、Nginx コンテナを Swarm cluster で 3 つ起動するように Service を定義しています。
この Service の定義にしたがって、Task がどこの Node に配置されているか確認します。

manager:~$ docker service ps nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE              ERROR               PORTS
6nxpj7p9p8r7        nginx.1             nginx:latest        worker1             Running             Preparing 43 seconds ago
ihvofbms35i0        nginx.2             nginx:latest        worker2             Running             Preparing 43 seconds ago
1bqz7hyqpnv5        nginx.3             nginx:latest        manager             Running             Preparing 43 seconds ago

NODE のカラムを見ると、3 Node でひとつずつ Task が実行されていることが確認できます。
それぞれの Node で 8080 ポートを公開するように設定しているため、http://<Node の IP アドレス>:8080 にアクセスすると確かに Nginx コンテナが起動していることが確認できます。

ちなみに、サービスをスケールするために、replica を増やす場合は、
docker service scale nginx=6 のように実行すると、replica を再設定することができます。

6. 可用性の確認

Docker Swarm には可用性を Service の可用性を担保する仕組みがあります。
現在、Manager / Worker1 / Worker2 の各 Node で Nginx の Task がひとつずつ実行されている状態になっていると思います。
この状態で、$ docker-machine stop worker2 を実行し、Worker2 のホストを停止してみます。

manager:~$ docker service ps nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
6nxpj7p9p8r7        nginx.1             nginx:latest        worker1             Running             Running 41 minutes ago
4nfc1ijcusq5        nginx.2             nginx:latest        manager             Running             Running 4 seconds ago
ihvofbms35i0         \_ nginx.2         nginx:latest        worker2             Shutdown            Running 21 seconds ago
1bqz7hyqpnv5        nginx.3             nginx:latest        manager             Running             Running 41 minutes ago

nginx Service の状態を確認すると、Worker2 で実行していた Task が新しく Manager で実行されていることがわかります。

$ docker-machine start worker2 でもう一度、Worker2 を起動し、Service の状態を確認してください。
Worker2 が復活したため Worker2 で Task が実行されると思いきや、そうではありません。
Task の再配置を行います。

// Task の再配置
manager:~$ docker service update -d --force nginx
nginx

manager:~$ docker service ps nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
6nxpj7p9p8r7        nginx.1             nginx:latest        worker1             Running             Running 54 minutes ago
4nfc1ijcusq5        nginx.2             nginx:latest        manager             Running             Running 13 minutes ago
ihvofbms35i0         \_ nginx.2         nginx:latest        worker2             Shutdown            Shutdown 12 minutes ago
0vl9k79xr2n0        nginx.3             nginx:latest        worker2             Ready               Ready 2 seconds ago 
1bqz7hyqpnv5         \_ nginx.3         nginx:latest        manager             Shutdown            Running 2 seconds ago

また、各 Node にひとつずつ Task が割り振られていることがわかります。

ちなみに、Worker2 に Task が割り振られていない状態で、Worker2 の 8080 ポートにブラウザからアクセスしてもちゃんと Nginx の Welcome ページが表示されます。
これは、Worker2 へのリクエストを他の Node に流しているためです。
ここらへんを、Ingress Overlay Network がいい感じにしてくれています。

さいごに

参考
Docker Swarm 入門
Swarm モードの重要な概念

Docker Swarm について解説しましたが、めちゃめちゃ調べながら書いたので間違っている部分あるかもしれませんがご了承ください。
現状、コンテナのオーケストレーションシステムは Google が開発した Kubernetes(K8s) がデファクトスタンダードになっています。
K8s について詳しくないのでなんとも言えないですが、K8s を学ぶ際に Swarm の知識がきっと活かせる部分があると思うので書いてみました。

K8s、使えるようになりたいですね。
以上!!

てか、X年目以下の若手でも会社にそこそこの人数いるはずなのに投稿している人、超限られているこの現状がいまいちイケてないよね。別に仕事ではないから絶対やれってことではないけど。
その大きな原因が会社で Qiita 見れないことだと思う。
" Proxy Fuxx !! "

話->変、アドベントカレンダー投稿した人飲み会とかしたいですね。
ただ、誰が誰なのかわかんないし、連絡もどうやってしたらいいか分からないから、難しいか? ピエン

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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした