概要
Docker Engine 1.12 RC1 (リリース候補版)から Docker Swarm の機能が swarm モード として統合されました。このチュートリアルは3台のサーバを使い、swarm(クラスタ)の形成と、その上で Nginx サービスとタスク(コンテナ)を起動、スケールアップ、スケールダウン、削除を試します。
所要時間は15分程度です。
注意事項
Docker Engine 1.12 RC2 現在の情報に基づいています。将来的な仕様変更や、バグを含む可能性があります。そのため、用途は新しいモードの検証/体験用とお考えいただければと思います。
環境の準備
新しい3台のサーバを準備します。RC 版の Docker Engine は既存の環境と共存できません。そのため、既にお使いの環境ではなく、新しい検証用環境を作ることを強くお薦めします。
3台のサーバは、次の役割を持ちます。 manager (マネージャ)はクラスタのサービスの受け入れと、タスクの割り振りを行います。 worker (ワーカ)はマネージャからの命令を受け取り、タスク(としてのコンテナ)を実行します。
名前 | 役割 |
---|---|
node-01 |
manager, worker |
node-02 |
worker |
node-03 |
worker |
今回は manager が 1 台かつ 3 台ともコンテナを実行する worker です。設定により、3 台とも manager と worker を兼ねられますし、manager 専用にすることも可能です。
なお、環境は、ローカルの仮想化環境やリモートのどちらでも構いません。私は DigitalOcean 上の以下の環境で動作確認を行いました。
- 512MB / 1 CPU / 20 GB SSD の最小環境を三台
- Ubuntu 16.04 x64, CentOS 7.2 x64
- Private Networking を有効化(クラスタ用通信のため)
ファイアウォールなど、パケットがフィルタされている環境では、次の接続を許可する必要があります。
-
2377(TCP)
クラスタ管理の通信用 -
7496(TCP,UDP)
ノード間の通信用 -
4789(TCP,UDP)
オーバレイ・ネットワークの通信
RC 版の Docker Engine のセットアップ
サーバにログイン後、以下のコマンドを実行すると、自動的に RC 版に対応したリポジトリとパッケージをセットアップします。
# curl -fsSL https://test.docker.com/ | sh
CentOS 7.2 では Docker が自動起動しないため、次のコマンドで起動します。
# systemctl enable docker
# systemctl start docker
動作確認は docker version
を実行し、クライアントとサーバ両方の情報を表示するのを確認します。
root@node-01:~# docker version
Client:
Version: 1.12.0-rc2
API version: 1.24
Go version: go1.6.2
Git commit: 906eacd-unsupported
Built: Fri Jun 17 21:21:56 2016
OS/Arch: linux/amd64
Server:
Version: 1.12.0-rc2
API version: 1.24
Go version: go1.6.2
Git commit: 906eacd-unsupported
Built: Fri Jun 17 21:21:56 2016
OS/Arch: linux/amd64
swarm クラスタの初期化
Docker Engine の swarm mode を使うには、まず docker swarm init
コマンドを使い、クラスタの初期化を行います。このコマンドを実行したサーバが manager となります。かつ、一番始めに実行したサーバが manager の Leader(リーダ)となります。
ここでは node-01
にログインし、次の watch
コマンドを実行します。
watch -n 1 'echo "$ docker node ls"; docker node ls; echo; echo "$ docker service ls"; docker service ls; echo ; echo "$ docker service tasks mynginx"; docker service tasks mynginx'
これは、毎秒画面上に次の情報を表示します。
- swarm クラスタのノード一覧(
docker node ls
) - サービス一覧(
docker service ls
) -
mynginx
サービスのタスク一覧(docker service tasks mynginx
)
こうすると、以降のチュートリアルでノードの状態やサービスの状態を、リアルタイムで把握できます。
次に、クラスタを初期化(managerの起動)します。
root@node-01:~# docker swarm init --listen-addr <node-01のIPアドレス>:2377
Swarm initialized: current node (3cmtfzqo9vqysc9htzm1adepf) is now a manager.
画面上の docker node ls
は、次のように1台のノードがクラスタに存在しているのが分かります。
$ docker node ls
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
3cmtfzqo9vqysc9htzm1adepf * node-01 Accepted Ready Active Leader
また、 docker info
コマンドからも、クラスタの情報を確認できます。
$ docker info
(省略)
Swarm: active
NodeID: 3cmtfzqo9vqysc9htzm1adepf
IsManager: Yes
Managers: 1
Nodes: 1
ここでは node-01
自身がマネージャ( IsManager: Yes )であり、現時点ではマネージャが1つ、ノードが1つと分かります。
次に、 node-02
node-03
をクラスタに追加します。
root@node-02:~# docker swarm join <node-01のIPアドレス>:2377
This node joined a Swarm as a worker.
root@node-03:~# docker swarm join <node-01のIPアドレス>:2377
This node joined a Swarm as a worker.
画面上にはワーカとして追加したと表示されます。 docker node ls
の情報を見ると、次のように3つのノードが swarm クラスタに参加しているのが分かります。
$ docker node ls
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
3cmtfzqo9vqysc9htzm1adepf * node-01 Accepted Ready Active Leader
6xzla3yzemtnx0iotqxvad3qn node-02 Accepted Ready Active
8tn1a8u5qeh2ohcq3l9uxo2y0 node-03 Accepted Ready Active
以上で swarm モードを使ってサービスを実行する準備が整いました。
サービスの作成
swarm モード上でコンテナを実行するには docker service create
コマンドを使います。このコマンドを実行できるのはマネージャ・ノードの node-01
上でのみです。
$ docker service create --replicas <タスク数> \
--name <サービス名> \
-p <公開ポート>:<コンテナのポート> \
<イメージ名>:<タグ>
ここでは Nginx コンテナでコンテナ ID を表示する zembutsu/docker-sample-nginx:1.0 イメージを使います。
$ docker service create --replicas 1 --name mynginx -p 80:80 zembutsu/docker-sample-nginx:1.0
次のようにサービスが追加され、タスクとしてのコンテナが実行されるのが分かります。
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
dc52legcse3q mynginx 1/1 zembutsu/docker-sample-nginx:1.0
$ docker service tasks mynginx
ID NAME SERVICE IMAGE LAST STATE
DESIRED STATE NODE
12kmzbiirvsq8rli1gqjhbgjz mynginx.1 mynginx zembutsu/docker-sample-nginx:1.0 Running 10
seconds Running node-01
タスクはコンテナの実行単位であり、注目すべきは LAST STATE
(現在の状態)と DESIRED STATE
(期待状態)です。コマンド時刻時、 --replicas 1
を指定したのは、このサービスは指定したイメージを常時1つ実行するという意味があります。しかし、実際にはイメージのダウンロードや起動に時間がかかるため、今どのような状況にあるかが LAST STATE
に表示されます( Preparing
-> Starting
--> Running
と遷移)。
また、 docker servie ls
の REPLICAS
も同様です。タスク数が 0/1
(現在の数/期待数)から 1/1
に変わります。
この例では node-01
でタスク(としてのコンテナ)を実行しました。このコンテナの情報は docker ps
コマンドでも確認できます。
root@node-01:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6095b5af72ba zembutsu/docker-sample-nginx:1.0 "nginx -g 'daemon off" About a minute ago Up About a minute 80/tcp, 443/tcp mynginx.1.12kmzbiirvsq8rli1gqjhbgjz
あとは curl
やブラウザでこのサーバにアクセスします。実行すると、画面上にコンテナ ID を表示します。
$ curl http://<host_ip>
<html>
<body>
<h1>Host: 6095b5af72ba</h1>
</body>
</html>
サービスのスケールアップ・スケールダウン
サービスの状態を変更するには docker service update
コマンドを使います。ここでは mynginx
サービスの数を3つに増やします。
root@node-01:~# docker service update --replicas 3 mynginx
コマンドを実行して暫くすると、タスクが3つに増えるのが確認できます。
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
dc52legcse3q mynginx 3/3 zembutsu/docker-sample-nginx:1.0
$ docker service tasks mynginx
ID NAME SERVICE IMAGE LAST STATE
DESIRED STATE NODE
12kmzbiirvsq8rli1gqjhbgjz mynginx.1 mynginx zembutsu/docker-sample-nginx:1.0 Running 5
minutes Running node-01
3nyxsldx8wciwvu5r0o5nachl mynginx.2 mynginx zembutsu/docker-sample-nginx:1.0 Running 25
seconds Running node-03
1miyrnvmg5i3czmq65sio6ped mynginx.3 mynginx zembutsu/docker-sample-nginx:1.0 Running 25
seconds Running node-02
この例では Preparing
(準備中)に時間がかかりますが、各ノード上に Docker イメージをダウンロードしているからです。イメージのダウンロード後は迅速にコンテナを開始できるようになるため、開始までのタイムラグを短縮したい場合は、あらかじめ各ノード上にイメージをダウンロード( docker pull
)しておくのがおすすめです。
また、swarm モードはデフォルトで spread(スプレッド;拡散の意味)ストラテジが適用されるため、各コンテナは全てのノードで均等に起動しようと(実行中コンテナの数が釣り合うように)します。
この状態で、再びサーバ側のホストに curl
でアクセスすると、コンテナIDが毎回切り替わります。各ノード上のコンテナは ingress
という名前のオーバレイ・ネットワークでつながっています。そして、サービスに対するアクセスは、各タスク(コンテナ)に対して自動的に負荷分散します。
curl
やブラウザの接続先を node-01
だけでなく、 node-02
node-03
で実行しても、負荷分散されるのを確認します。
自動復旧
swarm モードのサービスは、常に期待状態(desire state)を維持し続けます。そのため、あるノードで障害が起これば、自動的に別ノードで追加タスクを実行しなおす仕組みが働きます。
ここでは node-03
上の Docker Engine を停止します。
root@node-03:~# systemctl stop docker
Warning: Stopping docker.service, but it can still be activated by:
docker.socket
暫く待つと、 docker node ls
で node-03
の状態が Down
になります。
$ docker node ls
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
3cmtfzqo9vqysc9htzm1adepf * node-01 Accepted Ready Active Leader
6xzla3yzemtnx0iotqxvad3qn node-02 Accepted Ready Active
8tn1a8u5qeh2ohcq3l9uxo2y0 node-03 Accepted Down Active
そして、その瞬間、別のノードでタスクが再開されるのが分かります。
$ docker service tasks mynginx
ID NAME SERVICE IMAGE LAST STATE
DESIRED STATE NODE
12kmzbiirvsq8rli1gqjhbgjz mynginx.1 mynginx zembutsu/docker-sample-nginx:1.0 Running 6
minutes Running node-01
68vay29xunr8cawwyuhoza2lm mynginx.2 mynginx zembutsu/docker-sample-nginx:1.0 Accepted 4
seconds Accepted node-02
1miyrnvmg5i3czmq65sio6ped mynginx.3 mynginx zembutsu/docker-sample-nginx:1.0 Running 2
minutes Running node-02
swarm クラスタのノードは常にマネージャが監視していますので、 node-03
の Docker Engine を再開したら、自動的にクラスタに復旧します。
root@node-03:~# systemctl start docker
コマンドを実行すると、再び node-03
は Active
になります。
$ docker node ls
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
3cmtfzqo9vqysc9htzm1adepf * node-01 Accepted Ready Active Leader
6xzla3yzemtnx0iotqxvad3qn node-02 Accepted Ready Active
8tn1a8u5qeh2ohcq3l9uxo2y0 node-03 Accepted Ready Active
ローリング・アップデート
docker service update
はタスク数の変更だけでなく、実行中のイメージの差し替えも可能です。具体的には起動中のコンテナを停止し、新しいイメージのダウンロードと起動を自動的に行います。
先ほどの mynginx
サービスが使うイメージのタグを latest
に切り替えます。
$ docker service update \
--update-delay 5s \
--update-parallelism 1 \
--image zembutsu/docker-sample-nginx:latest
mynginx
-
--update-delay
ノードごとの更新タイミングの遅延指定 -
--update-arallelism
並列に処理するノード数
暫く待つと、自動的にタグが latest
に切り替わります。
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
3y37oegkuv4l mynginx 3/3 zembutsu/docker-sample-nginx:latest
$ docker service tasks mynginx
ID NAME SERVICE IMAGE LAST STATE DESIRED STATE NODE
0803qlg3o9cxmu2h5tp1od51t mynginx.1 mynginx zembutsu/docker-sample-nginx:latest Running 11 seconds Running node-03
3tsojfojtzngpip1qbct64q8b mynginx.2 mynginx zembutsu/docker-sample-nginx:latest Running 29 seconds Running node-01
8f2ch2bbuegbakzjegi8fp1gy mynginx.3 mynginx zembutsu/docker-sample-nginx:latest Running 20 seconds Running node-03
curl
やブラウザで確認すると、新しく Version: 1.1
の文字列が入っているのが分かります。
$ curl http://139.59.243.63
<html>
<body>
<h1>Host: 87f7fec795da</h1>
Version: 1.1
</body>
</html>
サービスの削除
docker service rm
コマンドでサービスを削除します。
root@node-01:~# docker service rm mynginx
mynginx
$ docker node ls
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
3cmtfzqo9vqysc9htzm1adepf * node-01 Accepted Ready Active Leader
6xzla3yzemtnx0iotqxvad3qn node-02 Accepted Ready Active
8tn1a8u5qeh2ohcq3l9uxo2y0 node-03 Accepted Ready Active
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
$ docker service tasks mynginx
Error: No such service: mynginx
あとは、任意のイメージ実行などをお試しください。おつかれさまでした。
おまけ:global モード
デフォルトではタスクはノードに分散されますが、global モードを指定すると、全ノード上でコンテナを均等に起動できます。ただし、スケールアップやスケールダウンはできません。
実行するには、 service create
や service update
で --mode
オプションを使用します。
例:
docker service create --name mynginx -p 80:80 --mode global zembutsu/docker-sample-nginx
du6211e72ml4g3f744a389ui4
結果:
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
du6211e72ml4 mynginx global zembutsu/docker-sample-nginx
$ docker service tasks mynginx
ID NAME SERVICE IMAGE LAST STATE DESIRED STATE NODE
a8lh89jjgf5icezfrgaduxwyk mynginx mynginx zembutsu/docker-sample-nginx Running 6 seconds Running node-03
3o29jqb02owmftfjb9hl4464n mynginx mynginx zembutsu/docker-sample-nginx Running 6 seconds Running node-02
9j3h6mx1mqa3j9v076aa7g4ip mynginx mynginx zembutsu/docker-sample-nginx Running 6 seconds Running node-01
さらに詳しく
- Swarm モード概要 — Docker-docs-ja 1.12.RC ドキュメント
- http://docs.docker.jp/engine/swarm/index.html
- Docker 1.12: swarm モードと Ingress Load Balancing 概要 · Pocketstudio Technology Log
- https://pocketstudio.net/2016/06/23/docker-1-12-swarm-mode-and-ingress-load-balancing/
- Docker 1.12 & Swarm Mode Introduction ~ Docker の新しい技術と swarm モードの紹介
- http://www.slideshare.net/zembutsu/docker-112-rc-introduction-to-swarm-mode