Part 4:Swarm¶
必要条件¶
- Docker バージョン 1.13 またはそれ以上をインストールしていること。
- Part 3 の必要条件 で説明した Docker Compose を入手していること。
- Docker Machine を入手していること。 Docker for Mac と Docker for Windows ではインストール済みであるが Linux システムでは 直接インストール が必要。
- Part 1 の概要を読んでいること。
- Part 2 のコンテナの作成方法を理解していること。
- レジストリに送信 して作成した
friendlyhello
イメージが共有可能であることを確認します。ここではその共有イメージを使います。 - デプロイしたコンテナとしてイメージが動作することを確認します。以下のコマンドを実行してください。docker run -p 80:80 username/repo:tag ここで username、repo、tag の部分は各環境に合わせて書き換えてください。そして
http://localhost/
にアクセスします。 - Part 3 で扱った
docker-compose.yml
ファイルが用意できていること。
はじめに¶
Part 3 では、 Part 2 で書いたアプリを元に、本番環境において実行可能なサービスとして調整したものを定義し、プロセス数を5倍にスケールアップしました。
この Part 4 では、デプロイするアプリケーションをクラスタにして、複数のマシン上で実行します。複数コンテナ、複数マシンによるアプリケーションは、各マシンを「Docker化」(Dockerized)したクラスタ、すなわち swarm (スウォーム)と呼ばれるものに集約することによって実現されます。
Swarm クラスタの理解¶
swarm とは Docker の動作するマシンがひとまとまりとなってクラスタを構成するものです。swarm を使うようになると、これまで使ってきた Docker コマンドは引き続き用いることにはなりますが、今度はクラスタに対しての swarm マネージャ として処理操作を行うものとなります。swarm 内のマシンは物理マシン、仮想マシンのいずれでも構いません。マシンを swarm に含めた後は、 ノード として参照されます。
swarm マネージャでは、コンテナの実行にあたってストラテジというものが指定できます。たとえば「emptiest node」(最も空いているノード)です。これは最も使われていないマシンをコンテナに割り当てます。「global」というものは、個々のマシンには、指定されたコンテナの1インスタンスのみを割り当てます。swarm マネージャに対してのストラテジ指定は Compose ファイルにて行います。既に利用してきたファイルです。
swarm マネージャは swarm 内でコマンド実行ができる唯一のマシンです。 そして他のマシンの swarm への参加を認証します。 swarm に参加したマシンは ワーカ (worker)と呼ばれます。 ワーカは処理提供するために加えられたわけですが、他のマシンの機能を制約する権限を持つわけではありません。
これまではローカルマシン上において、シングルホストモードにより Docker を利用してきました。Docker は swarm モード に切り替えることが可能であり、このモードにすることで swarm が利用できるようになります。swarm を有効にした時点で現在のマシンが swarm マネージャとなります。これ以降の Docker に対するコマンドは swarm に対して実行されます。もうそれまでのマシンに対して実行するものではなくなります。
swarm のセットアップ¶
swarm は複数のノードにより構成されます。それは物理マシン、仮想マシンのどちらでも構いません。基本的な考え方はとても簡単です。 docker swarm init
の実行により swarm モードが有効となり、現在のマシンが swarm マネージャになります。その後に他のマシンから docker swarm join
を実行すると、そのマシンはワーカとして swarm に参加できます。この仕組みがさまざまな環境においてどのように動作するか、以下のタブを切り替えて確認してください。以下では仮想環境を用いて、2つのマシンによるクラスタをさっと作り出して、これを swarm に切り替えます。
クラスタの作成¶
ローカルマシン上の仮想マシン(Mac、Linux、Windows 7 および 8)¶
まず、仮想マシンを作成できるハイパーバイザが必要です。そのため、各マシンの OS に対応した VirtualBox をインストール します。
Note: If you’re on a Windows system that has Hyper-V installed, such as Windows 10, there is no need to install VirtualBox and you should use Hyper-V instead. View the instructions for Hyper-V systems by clicking the Hyper-V tab above.
注釈
Windows 10 のように Hyper-V が搭載された Windows システムの場合、VirtualBox のインストールは不要であり、かわりに Hyper-V を利用してください。上記の Hyper-V に関するタブをクリックして Hyper-V システムの手順を参照してください。Docker Toolbox を利用する場合は、その一部としてすでに VirtualBox がインストールされるため、このまま先に進んでください。
次に docker-machine
を使い、2つの仮想マシンを作成します。ここでは VirtualBox ドライバを使います。
$ docker-machine create --driver virtualbox myvm1
$ docker-machine create --driver virtualbox myvm2
ローカルマシン上の仮想マシン(Windows 10)¶
はじめに、仮想マシンが共有する仮想スイッチを作成して、仮想マシンが互いに接続できるようにします。
- Hyper-V マネージャーを起動
- 右側のメニューにある 仮想スイッチ マネージャー をクリック
- 仮想スイッチの作成 のタイプ 外部 をクリック
myswitch
という名称に設定し、ホストマシンのアクティブ・ネットワーク・アダプタとの共有ボックスにチェックを入れる
次にノード管理ツール docker-machine
を使い、2つの仮想マシンを作成します。
$ docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1
$ docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm2
作成¶
このように myvm1
と myvm2
という名前の2つの仮想マシン( docker-machine ls
で表示 )を作成しました。1つめはマネージャとして docker
コマンドを実行し、ワーカを swarm に追加する認証をします。2つめはワーカにします。
仮想マシンには docker-machine ssh
を使ってコマンドを送ります。 myvm1
に対して docker swarm init
で swarm マネージャになるよう命令します。次のような実行結果になるでしょう。
$ docker-machine ssh myvm1 "docker swarm init"
Swarm initialized: current node <node ID> is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token <token> \
<ip>:<port>
ヒント
エラーが出る場合は、 --advertise-addr
を使う必要があるかもしれません
docker-machine ls
を実行し、 myvm1
の IP アドレスをコピーします。それから docker swarm init
コマンドを再び実行しますが、 --advertise-addr
で IP アドレスとポート 2377
を指定(swarm が join に使うポート)します。実行例:
docker-machine ssh myvm1 "docker swarm init --advertise-addr 192.168.99.100:2377"
ご覧の通り、 docker swarm init
の応答があれば、必要なあらゆるノードをあらかじめ調整済みの docker swarm join
で追加できます。 myvm2
を新しい swarm でワーカとして追加するには、次のコマンドをコピーし、 docker-machine ssh
経由で myvm2
に送信します。
$ docker-machine ssh myvm2 "docker swarm join \
--token <token> \
<ip>:<port>"
This node joined a swarm as a worker.
これで初めての swarm (クラスタ)が完成しました。お疲れさまでした。
注釈
別の方法として、 docker-machine ssh myvm2
でコマンドを付与しなければ、仮想マシンに対するターミナル・セッションを開きます。ホスト側のシェル・プロンプトに戻る準備が整えば、 exit
を実行します。場合によっては join コマンドを実行するよりも簡単でしょう。
ssh
を使って接続し( docker-machine ssh myvm1
)、 この swarm のノード一覧を表示するため docker node ls
を実行します。
docker@myvm1:~$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
brtu9urxwfd5j0zrmkubhpkbd myvm2 Ready Active
rihwohkh3ph38fhillhhb84sk * myvm1 Ready Active Leader
exit
を実行し、マシン側に戻ります。
別の方法として、 docker-machine ssh
でコマンドをまとめ、直接ログインしてログアウトもできます。実行例:
docker-machine ssh myvm1 "docker node ls"
アプリをクラスタ上にデプロイ¶
大変な部分は終わりました。次は Part 3 で用いた手順を、新しい swarm 上で繰り返します。 myvm1
のような swarm マネージャは Docker コマンドを実行できるのを思い出してください。ワーカはキャパシティ(収容能力)のためのみです。
part 3 で作成した docker-compose.yml
ファイルを、 swarm マネージャ myvm1
のホームディレクトリ(別名: ~
)に docker-machine scp
コマンドを使ってコピーします。
docker-machine scp docker-compose.yml myvm1:~
これで myvm1
は swarm マネージャの力によりアプリをデプロイできるようになりました。part 3 で使ったのと同じ docker stack deploy
コマンドを docker-machine ssh
コマンドで myvm1
に送信します。
docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab"
これだけの作業で、アプリはクラスタ上にデプロイされました。
part 3 で使った全てのコマンドを docker-machine ssh
で送るだけで、全て期待通りに動作します。今回のケースでは、コンテナは myvm1
と myvm2
の両方に分散したことが分かります。
$ docker-machine ssh myvm1 "docker stack ps getstartedlab"
ID NAME IMAGE NODE DESIRED STATE
jq2g3qp8nzwx test_web.1 username/repo:tag myvm1 Running
88wgshobzoxl test_web.2 username/repo:tag myvm2 Running
vbb1qbkb0o2z test_web.3 username/repo:tag myvm2 Running
ghii74p9budx test_web.4 username/repo:tag myvm1 Running
0prmarhavs87 test_web.5 username/repo:tag myvm2 Running
クラスタにアクセス¶
アプリに対しては myvm1
か myvm2
の どちらか の IP アドレスでアクセスできます。作成したネットワークは双方のホストで共有され、負荷分散できます。 docker-machine ls
を実行して仮想マシンの IP アドレスを確認し、ブラウザでどちらかを表示し、それから再読み込みします(あるいは curl
でも同様です)。読み込み直すたびに、ランダムに5つのコンテナ ID のどれかを表示するでしょう。負荷分散のデモンストレーションです。
どちらの IP アドレスでも動作する理由は、swarm の各ノードが ingress ルーティング・メッシュ(rougint mesh) に所属しているからです。これにより、サービスのデプロイにあたり swarm 上で指定したポートを確保できるよう、コンテナが実際にどのノードで実行中か気にすることなく、ノード自身がポートを予約します。下図は my-web
という名前のサービスが公開するポート 8080
を、3つの swarm ノード上で、どのようにルーティング・メッシュするかの説明です。
ヒント
接続に問題がありますか?
swarm で ingress ネットワークを使うためには、swarm モード有効にする前に、swarm ノード間で以下のポートを開く必要がありますので、ご注意ください。
- Port 7946 TCP/UDP を、コンテナのネットワーク・ディスカバリ用に
- Port 4789UDP をコンテナ ingress ネットワーク用に
アプリの繰り返しとスケーリング¶
ここからは part 3 で学んだ全ての動作を行えます。
アプリのスケールは、docker-compose.yml
ファイルを変更します。
アプリの挙動を変更するには、コードを編集します。
いずれにしろ、変更を反映(デプロイ)するには docker stack deploy
を再び実行するだけです。
物理マシンと仮想マシンのどちらにしても、 myvm2
に対して実行したのと 同じ docker swarm join
コマンドを使って swarm に追加でき、クラスタの収容能力に追加できます。そして docker stack deploy
を実行するだけで、アプリは新しいリソースを利用可能になります。
クリーンアップ¶
スタックは docker stack rm
で解体できます。実行例:
docker-machine ssh myvm1 "docker stack rm getstartedlab"
ヒント
swarm は維持?それとも削除?
後々、必要に応じてワーカを削除したい場合は docker-machine ssh myvm2 "docker swarm leave"
を、マネージャの削除は docker-machine ssh myvm1 "docker swarm leave --force"
で行えます。 ですが、swarm は part 5 でも使いますので、今はこのままにしておいてください。
まとめとチート・シート(オプション)¶
このページで扱ったターミナルの録画 がこちらです。
Part 4 では、swarm とは何か、swarm においてノードをマネージャまたはワーカにする方法、swarm の作成と、そこにアプリケーションをデプロイする方法を学びました。ご覧の通り、主なコマンドは part 3 と変わることはなく、単に実行対象が swarm マネージャになっただけでした。また、Docker ネットワークの力もご覧になったでしょう。コンテナ間で負荷分散(ロードバランサ)を組めるだけでなく、コンテナが異なったマシン上で実行していても可能なのです。最後に、クラスタ上でアプリの繰り返しとスケールを学びました。
ここでは swarm 上で実行すると便利なコマンドをいくつか紹介します。
docker-machine create --driver virtualbox myvm1 # 仮想マシン作成 (Mac, Win7, Linux)
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1 # Win10
docker-machine env myvm1 # ノードに関する基本情報の表示
docker-machine ssh myvm1 "docker node ls" # swarm のノード一覧
docker-machine ssh myvm1 "docker node inspect <node ID>" # ノードの調査
docker-machine ssh myvm1 "docker swarm join-token -q worker" # join トークンの表示
docker-machine ssh myvm1 # 仮想マシンの SSH セッションを開く;"exit" を入力して終了
docker-machine ssh myvm2 "docker swarm leave" # ワーカを swarm から離脱
docker-machine ssh myvm1 "docker swarm leave -f" # マスターを離脱し、swarm を停止
docker-machine start myvm1 # 仮想マシンが起動していなければ、起動
docker-machine stop $(docker-machine ls -q) # 実行中の全ての仮想マシンを停止
docker-machine rm $(docker-machine ls -q) # 全ての仮想マシンとディスク・イメージを削除
docker-machine scp docker-compose.yml myvm1:~ # ファイルをノードのホームディレクトリにコピー
docker-machine ssh myvm1 "docker stack deploy -c <file> <app>" # アプリをデプロイ