Docker Swarm (Swarm Mode) のチュートリアル Getting started with swarm mode をAWS上でやってみたので日本語でまとめです。
何がうれしいの?
- ノード (サーバー) を跨いで Dockerサービス のデプロイ/アップデートができます
- 各ノードへの公開アクセスを Swarm Load Balancer が適切なノードのコンテナにリクエストを振り分けてくれます
- たとえ コンテナが一つも動いていないノードにアクセス しても、別のノードのコンテナがレスポンスを返してくれます
- 内部のサービス間のオーケストレーションも Swarm Load Balancer がしてくれている様です
- サービスの Rolling Update が出来ます
- (他の似たOSSと比べて) 非常にシンプルで扱いやすいです
※ docker.com 公式より, Swarm Load Balancer の図。
分からなかったこと
Rollling Update は処理中のリクエストが全て完了するのを待ってからアップデートを開始してくれるか?
AWSで言うところの ELB > Connection Draining の動きになるか?
誰か教えて下さい〜 m(_ _)m
チュートリアルまとめ
Getting started with swarm mode を色々と端折って説明します。
- 全てAWS上 Amazon Linux 2017.03.1 (ami-bbf2f9dc) で確認しました
- sudoが面倒なので
alias docker='sudo docker'
してあります。
ポートを開ける (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のポート) へのアクセスは適切なコンテナに自動的に割り振りされます。
※ 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>
...