【Dockerの最新機能を使ってみよう】 Docker SwarmによるDockerクラスタ環境の構築 2ページ

Swarm Managerの起動

 Docker SwarmのインストールおよびEtcdの設定が完了したら、「swarm manage」コマンドを実行してSwarm Managerを起動する。

$ swarm manage -H tcp://<ホストのIPアドレス>:3375 etcd://<Etcdを稼働させているホストのIPアドレス>:2379

 今回は3375番ポートを使用してSwarm ManagerがDockerクライアント(dockerコマンド)からの接続を受け付けるよう設定している。そのため、外部から3375番ポートへの接続を許可するようファイアウォールの設定を変更しておく。たとえばfirewalldを使用している場合、以下のように実行すれば良い。

# firewall-cmd --add-port 3375/tcp

 なお、今回は検証目的なのでシェルから直接Swarm Managerを起動させているが、運用環境では適切な起動スクリプトを用意し、サービスとして起動させるようにすることをおすすめする。

 Swarm Managerを起動させたら、次のように「docker info」コマンドを「-H」オプション付きで実行してSwarm Managerに接続できるかを確認しておこう。この時点ではコンテナを実行させるためのノードを登録していないため、「Nodes」は0になっているはずだ。

$ docker -H tcp://<Swarm Managerを実行させているホストのIPアドレス>:3375 info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: swarm/1.2.2
Role: primary
Strategy: spread
Filters: health, port, containerslots, dependency, affinity, constraint
Nodes: 0
Plugins: 
 Volume: 
 Network: 
Kernel Version: 4.4.6-300.fc23.x86_64
Operating System: linux
Architecture: amd64
Number of Docker Hooks: 0
CPUs: 0
Total Memory: 0 B
Name: fedora01
Registries: 

コンテナを実行するノードでの設定

 コンテナを実行するノードでは、以下の設定が必要となる。

  • ホスト外からAPI経由で操作できるようDocker Daemonの起動オプションを追加
  • ファイアウォールの設定
  • Docker Swarmの起動

 まず、ホスト外からDocker Daemonを操作できるようにするため、Docker Daemonの起動オプションに「-H tcp://<ノードのIPアドレス>:2375」を追加する。Red Hat Enterprise LinuxやCentOSなどその互換OS、Fedoraでは/etc/sysconfig/dockerファイル内に、Ubuntuでは/etc/default/dockerファイル内にこの設定を記述する。

 Red Hat Enterprise LinuxやCentOS、Fedoraの場合、/etc/sysconfig/dockerファイル内の「OPTIONS=」行に以下のようにオプションを追加すれば良い。

OPTIONS='-H <ノードのIPアドレス>:2375 --selinux-enabled --log-driver=journald'

 また、Ubuntuでは/etc/default/dockerファイル内でコメントアウトされている「DOCKER_OPTS」にこのオプションを記述する。

DOCKER_OPTS="-H <ノードのIPアドレス>:2375 "

 なおこれらの設定を行った場合、各ホスト内でdockerコマンドを実行する際に「-H <ノードのIPアドレス>:2375」オプションを使用して明示的に接続先を指定する必要がある点に注意したい。

 また、ホスト外から2375番ポートへの接続を許可するようファイアウォールの設定を変更しておく。たとえばfirewalldを使用している場合、以下のように実行すれば良い。

# firewall-cmd --add-port 2375/tcp

 今回の設定ではDocker Daemonへのアクセスに対するセキュリティ保護を行っていない点には注意してほしい。この場合、外部からDocker Daemonに自由にアクセスできてしまうことになる。そのため、第三者からのアクセスが制限されたローカルネットワーク内のIPアドレスをDocker Daemonが使用するIPアドレスとして割り当てることを推奨する。

 以上の設定が完了したらDocker Daemonを再起動し、問題がなければ続けて「swarm join」コマンドを実行してノードをクラスタに追加する。

$ swarm join --advertise=<ノードのIPアドレス>:2375 etcd://<Etcdを稼動させているホストのIPアドレス>:2379

 この状態で「docker info」コマンドを実行すると、ノードが追加されていることを確認できる。

 

$ docker -H tcp://<Swarm Managerを稼動させているホストのIPアドレス>:3375 info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 5
Server Version: swarm/1.2.2
Role: primary
Strategy: spread
Filters: health, port, containerslots, dependency, affinity, constraint
Nodes: 1
 fedora02: <ノードのIPアドレス>:2375
  └ ID: HLMS:WYP5:EKY4:BNHZ:VHZE:NF6Z:SCJR:F3VO:IIFC:TR4Z:64JX:Y2BN
  └ Status: Healthy
  └ Containers: 0
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 1.018 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=4.4.6-300.fc23.x86_64, operatingsystem=Fedora 23 (Twenty Three), storagedriver=devicemapper
  └ Error: (none)
  └ UpdatedAt: 2016-05-29T11:13:24Z
  └ ServerVersion: 1.10.3
Plugins: 
 Volume: 
 Network: 
Kernel Version: 4.4.6-300.fc23.x86_64
Operating System: linux
Architecture: amd64
Number of Docker Hooks: 0
CPUs: 1
Total Memory: 1.018 GiB
Name: fedora01
Registries: 

 ここでノードが追加されないと言ったトラブルが発生した場合は、Docker Managerを実行しているホストからそのノードのDocker Daemonにアクセスできるかどうか、以下のようにして確認してみよう。

$ docker -H tcp://<コンテナを実行させるノードのIPアドレス>:2375 version
Client:
 Version:         1.10.3
 API version:     1.22
 Package version: docker-1.10.3-4.gitf8a9a2a.fc24.x86_64
 Go version:      go1.6
 Git commit:      f8a9a2a/1.10.3
 Built:           
 OS/Arch:         linux/amd64

Server:
 Version:         1.10.3
 API version:     1.22
 Package version: docker-1.10.3-4.gitf8a9a2a.fc24.x86_64
 Go version:      go1.6
 Git commit:      f8a9a2a/1.10.3
 Built:           
 OS/Arch:         linux/amd64

コンテナの起動

 Docker Swarmを使って構成したクラスタ上でコンテナを起動するには、「docker run」コマンドを「-H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375」オプション付きで実行すれば良い。この際、ローカルホスト上で「docker run」コマンドを実行する場合と同様のオプションが指定できる。たとえば次の例は、「httpd」コンテナを実行するものだ。

$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 run -d --name httpd01 httpd

 この状態で稼動しているコンテナを確認する「docker ps」コマンドを実行してみると、コンテナ名の前にそのコンテナを稼動させているホストの名前が付与されていることが分かる。下記の例では、「httpd01」コンテナは「fedora02」というホスト上で稼動している。

$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
4a458cf98650        httpd               "httpd-foreground"   6 seconds ago       Up 6 seconds        80/tcp              fedora02/httpd01

 なお、-Hオプションの代わりに「DOCKER_HOST」環境変数でSwarm Managerの稼動しているホストおよびポートを指定することも可能だ。

$ export DOCKER_HOST=<Swarm Managerを起動させているホストのIPアドレス>:3375

 この環境変数を設定することで、-HオプションなしでDockerクラスタに対する操作を実行できるようになる。

$ docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
4a458cf98650        httpd               "httpd-foreground"   2 minutes ago       Up 2 minutes        80/tcp              fedora02/httpd01

Docker Swarmにおけるコンテナのスケジューリング機構

 Docker Swarmのデフォルト設定では、コンテナがどのノードで起動されるかが自動的に決定される。この際の決定戦略としては「spread」および「binpack」、「random」の3つが用意されており、デフォルト設定ではspread戦略が使われる。

 spread戦略は、各ノードができるだけ同じ数のコンテナを実行するようコンテナ実行先ノードを決定するもので、新たにコンテナを実行する際は最も稼動しているコンテナが少ないノードが選択される。また、binpack戦略では1つのノードにできるだけ多くのコンテナを稼動させるように実行先ノードが選択される。random戦略では完全にランダムで実行先ノードが選択される。

 これらのうちどの戦略が使われているかは、docker infoコマンドで確認できる。

$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 info
Nontainers: 2
 Running: 2
 Paused: 0
 Stopped: 0
Images: 10
Server Version: swarm/1.2.2
Role: primary
Strategy: spread
Filters: health, port, containerslots, dependency, affinity, constraint


 たとえばデフォルトのspread戦略の場合、2つのコンテナを実行すると、それぞれは別のコンテナで稼動する。

↓1つめのコンテナを起動
$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 run -d --name httpd01 httpd
↓2つめのコンテナを起動
$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 run -d --name httpd02 httpd
↓「fedora02」と「fedora03」の2つのホストでそれぞれコンテナが稼動する
$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
08ea1f436980        httpd               "httpd-foreground"   30 minutes ago      Up 30 minutes       80/tcp              fedora03/httpd02
4a458cf98650        httpd               "httpd-foreground"   34 minutes ago      Up 34 minutes       80/tcp              fedora02/httpd01

 なお、Docker Swarmでは指定された条件を満たすようにコンテナを稼動させるノードを決定させる「フィルタ」という機能も用意されている。詳しくはDocker Swarmのドキュメントを参照して欲しいが、条件としてはホスト名やホストに指定したラベル、OS、特定のDocker設定などを指定できる。また、「指定したコンテナが稼動しているノード」や「指定したポートが利用できるノード」といった指定も可能だ。

 たとえば「docker run」コマンドの引数として「-e constraint:node==<ホスト名>」というオプションを追加することで、指定したホスト名を持つノード上でコンテナを実行できる。たとえば次の例は、「fedora03」というノード上でhttpdコンテナを実行するものだ。

$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 run -e constraint:node==fedora03 -d --name httpd04 httpd

コンテナのリスケジューリング

 Docker Swarmでは、なんらかの原因でコンテナが停止した際にコンテナを再起動するリスケジューリング機能が用意されている。この機能はデフォルト設定では無効になっているため、利用するにはコンテナの起動時に明示的にリスケジューリングを行うよう指定する必要がある。

 リスケジューリングを有効にするには、コンテナに与える「reschedule」環境変数に「on-node-failure」という値をセットするか、もしくは「com.docker.swarm.reschedule-policy」ラベルに「on-node-failure」を指定れば良い。具体的には、「docker run」コマンド時に前者の場合は「-e reschedule:on-node-failure」オプションを、後者の場合は「-l ‘com.docker.swarm.reschedule-policy=[“on-node-failure”]’」というオプションを追加すれば良い。

 たとえば以下の例では、reschedule環境変数を設定する方法でリスケジューリングを有効にしてhttpdコンテナを起動している。

$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 run -e reschedule:on-node-failure -d --name httpd01 httpd

 続いて「docker ps」コマンドで確認すると、この例ではfedora02というノード上でこのコンテナが起動していることが分かる。

$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 ps
CONTAINER ID        IMAGE               COMMAND              CREATED              STATUS              PORTS               NAMES
69d5a01f0647        httpd               "httpd-foreground"   About a minute ago   Up About a minute   80/tcp              fedora02/httpd01

 この状態でfedora02ノードを停止させてみると、Swarm Managerで次のようなログが表示され、ノードが利用できなくなったことを認識すると同時に、コンテナを別のノードで再起動させていることが分かる。

INFO[5462] Removed Engine fedora02
INFO[5463] Rescheduled container 69d5a01f0647990750d426d141a0fa540ecaba47181b0f4f4571de7c08cf960a from fedora02 to fedora03 as 7f7d42b986cff4225de9f9f5f2f3a17fee8a6d3ed2a6ff171f3bdaf4cffdd551
INFO[5463] Container 69d5a01f0647990750d426d141a0fa540ecaba47181b0f4f4571de7c08cf960a was running, starting container 7f7d42b986cff4225de9f9f5f2f3a17fee8a6d3ed2a6ff171f3bdaf4cffdd551

 この状態で「docker ps」コマンドでコンテナの稼働状況を確認すると、httpd01コンテナがfedora03ノードで再起動されていることが分かる。

$ docker -H tcp://<Swarm Managerを起動させているホストのIPアドレス>:3375 ps
CONTAINER ID        IMAGE               COMMAND              CREATED              STATUS              PORTS               NAMES
7f7d42b986cf        httpd               "httpd-foreground"   About a minute ago   Up About a minute   80/tcp              fedora03/httpd01