概要
前記事(http://kakts-tec.hatenablog.com/entry/2018/02/12/220716)に引き続き, Docker公式ドキュメントのPart4 Swarmsの内容を整理します.
Part4 Swarms
Introduction
Part3ではPart2で作成したアプリケーションを取り上げ,Serviceを用いてproduction環境の定義を行い,プロセスのスケールアップも行いました.
Part4では,アプリケーションをクラスタ上にデプロイし,複数マシン上で実行させます.
マルチコンテナ,マルチマシンアプリケーションは複数のマシンをswarmと呼ばれるDockernizedされたクラスタにジョインすることで可能となります.
Understanding Swarm clusters
swarm はDockerを実行し,クラスタに参加するマシンのグループのことです.
クラスタにジョインしたあと,今までどおりdockerコマンドを使いますが,swarm manager によってクラスタ上で実行されます.
swarm内のマシンは物理マシンや仮想マシンです. swarmにジョイン後,それらのマシンはnodesと呼ばれます.
swarm manager はコンテナを実行するために複数のストラテジーを利用可能で,たとえば emptiest node と呼ばれるコンテナが一番起動されていないマシンを選んで起動する方式などがあります.
そしてglobal と呼ばれるストラテジーは, 各マシンが特定のコンテナを1つのみ持つことを保証するものです.
ユーザはcomposeファイル内でどのストラテジーを使うか定義できます.
swarm managerはswarm内でユーザのコマンドを実行できる唯一のマシンで, 他のマシンがworker としてswarmにジョインするのを認証します.
workerはキャパシティーを担保するもので, 他のマシンとやりとりする権限をもちません.
今までの章では,dockerをローカルマシン上でシングルホストモードで使用していました.
しかしDockerはswarmを使用できるswarmモードにも切り替えることができます.
swarmモードを有効にするということは,現在使用しているマシンをswarm managerにするということです.
モードの変更後, Dockerは現在使っているマシンのみというよりも,ユーザが管理するswarmクラスタ上でコマンドが実行されます.
Set up your swarm
swarmは複数のnodeで構成され,各nodeは物理マシンでも仮想マシンでも可能です. 基本的なコンセプトはシンプルで, docker swarm init を実行しswarm modeを有効にし,現在使っているマシンをswarm managerにした上で, 他のホスト上でdocker swarm join を実行させ,workerとしてswarmにジョインさせます.
Create a cluster
まず,クラスターを作成する前に,複数のVMマシンを立ち上げます.
Virtualbox環境を用意した上で話しをすすめます.
まず,docker-machineコマンドを使ってマシンを作ります.
docker-machine create --driver virtualbox node01 docker-machine create --driver virtualbox node02
LIST THE VMS AND GET THEIR IP ADDRESSES
実行後 docker-machine ls で作成したマシンの状態を確認できます.
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS node01 - virtualbox Running tcp://192.168.99.100:2376 v18.02.0-ce node02 - virtualbox Running tcp://192.168.99.101:2376 v18.02.0-ce
INITIALIZE THE SWARM AND ADD NODES
最初のマシンはmanagerとして稼働し,管理用コマンドを実行したり,swarmにジョインしたworkerの管理を行います.
2台目のマシンはworkerとなります.
docker-machine ssh コマンドでマシン名を指定するとVMに対してコマンドを実行できます.
ここではnode01に対してdocker swarm initを実行し,swarm managerにします.
$ docker-machine ssh node01 "docker swarm init --advertise-addr 192.168.99.100" Swarm initialized: current node (q9gndi1k8qfwtbusob9jmav2j) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-4ow9k02pfkb84fyd3jdwke0r0p0qigiac7rutprt3thn5jzrgj-590v3ftz0e5225ibrn7klensx 192.168.99.100:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
注意点
Port2377と2376について
常にdocker swarm init と docker swarm joinは2377ポートに対して行います. docker-machine ls で表示される2366ポートはDockerのdaemonポートです. このポートに対して操作を行うとエラーになります.
先程のnode01に対するdocker swarm initを実行したときに,以下の文言が表示されました.
ここに書いてあるとおり, node01はswarm managerになったので,swarmに対してジョインさせたいときはdocker swarm joinを実行すると可能になります.
To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-4ow9k02pfkb84fyd3jdwke0r0p0qigiac7rutprt3thn5jzrgj-590v3ftz0e5225ibrn7klensx 192.168.99.100:2377
今回はnode02をworkerにしたいのでnode02に対して実行させます.
$ docker-machine ssh node02 "docker swarm join --token SWMTKN-1-4ow9k02pfkb84fyd3jdwke0r0p0qigiac7rutprt3thn5jzrgj-590v3ftz0e5225ibrn7klensx 192.168.99.100:2377" This node joined a swarm as a worker
これでnode02をworkerに追加できました. node01上で確認するとnode01がswarm leaderになっているのがわかります.
$ docker-machine ssh node01 "docker node ls" ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS q9gndi1k8qfwtbusob9jmav2j * node01 Ready Active Leader s31768g3n99fev0sabf2i0q0g node02 Ready Active
Deploy your app on the swarm cluster
一通りswarmに対する操作は終わりあとはPart3とほぼ同じ操作を行うのみです.
前述しましたが,注意点として, swarm managerであるnode01のみがdockerコマンドを実行でき,残りのworkerでは実行できません.
Configure a docker-machine shell to the swarm manager
今まで, Dockerコマンドを実行するのにdocker-machine ssh を使ってVMとやり取りしていました. 別のやり方として,docker-machine env
このやり方は非常に便利で,なぜならローカル環境のdocker-compose.ymlを使うことができ,マシンに直接コピーせずともリモートでアプリケーションをデプロイできるからです.
さっそくdocker-machine env node01 を実行して見ます. これにより,node01に対する設定項目が出力されます.
$ docker-machine env node01 export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://192.168.99.100:2376" export DOCKER_CERT_PATH="/Users/username/.docker/machine/machines/node01" export DOCKER_MACHINE_NAME="node01" # Run this command to configure your shell: # eval $(docker-machine env node01)
出力結果に書いてあるとおりに実行すると設定が完了します.
eval $(docker-machine env node01)
docker-machine ls コマンドを実行することで,現在のシェルがどのノードに対してアクティブになっているのかを確認できます.
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS node01 * virtualbox Running tcp://192.168.99.100:2376 v18.02.0-ce node02 - virtualbox Running tcp://192.168.99.101:2376 v18.02.0-ce
Deploy the app on the swarm manager
ここでnode01のマシンをswarm managerとして使うことができ,Part3で使ったdocker stack deploy コマンドとdocker-compose.yml でアプリケーションをデプロイできる状態になりました.
このコマンドは実行完了までに数秒かかり,デプロイしたものが利用可能になるまで時間がかかります.
docker service ps <service_name> をswarm managerで実行して全てのサービスがデプロイされていることを確認できます.
$ docker service ps getstartedlab_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS r07ynn2v8bj7 getstartedlab_web.1 username/get-started:part2 node02 Running Running less than a second ago m3lg9lbr23xb getstartedlab_web.2 username/get-started:part2 node01 Running Running 1 second ago pt6ajvyvkbgv getstartedlab_web.3 username/get-started:part2 node02 Running Running less than a second ago aftz97jyv5cq getstartedlab_web.4 username/get-started:part2 node01 Running Running 1 second ago k3vhukabiv5v getstartedlab_web.5 username/get-started:part2 node02 Running Running less than a second ago vzr3ujd6hjif getstartedlab_web.6 username/get-started:part2 node01 Running Running 1 second ago neeh3npk9n7g getstartedlab_web.7 username/get-started:part2 node02 Running Running less than a second ago
これによりservicesのコンテナがnode01とnode02のそれぞれにデプロイされたことがわかります.
Accessing your cluster
これでnode01とnode02のIPアドレスからアプリケーションにアクセスできるようになりました.
作成したネットワークは2つのnodeとロードバランサーに共有されています. docker-machine ls でどちらかのnodeのipへアクセスしてリロードしてみてください.
今回は7つのレプリカを指定したのでアクセスするたびに7つのコンテナにランダムに振り分けられます.
node01とnode02のどちらに対してアクセスしても適切にロードバランシングされます.
これは,swarm内の各nodeがrouting meshに参加しているためです.
これはswarm内の特定のポートに対してデプロイされたserviceが,コンテナがどのようなnode上で動いていても常にポートを持つことを保証するためです.