以前にDocekrをクラスタ管理するためにDocker Swarmを使ってオーケストレーションしてみたことが過去あったのですが、Docker Swarmを使った構築は、ConsulなどのKVSを別途用意したり大変だったりで、クラスタ構築が大変だったのですが、
最近はSwarmモードというのが追加されているらしく、結構簡単にできるとのことだったので、ホントに簡単にSwarmモードなるものでクラスタを簡単構築できるか調査してみました。
以下は、その時のメモになります。
ちなみに、現在では「Docker Swarm」というと、一般的にはSwarmモードのことを指すらしいです。
クラスタ環境の構成
- Managerノード
- 仮想マシンのホスト名: manager1, manager2
- CentOS7
- Workerノード
- 仮想マシンのホスト名: worker1, worker2
- CentOS7 ## 仮想マシンの準備とDockerのインストール
Vagrantfile
をこんな感じで用意しておきました。
IPアドレスやらホスト名やらはお好みで。
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
# Managerサーバ#1
config.vm.define "manager1" do |node|
node.vm.provider "virtualbox" do |vm|
vm.name = "manager1"
vm.customize ["modifyvm", :id, "--memory", "512"]
end
node.vm.box = "centos/7"
node.vm.hostname = "manager1"
node.vm.network "private_network", ip: "192.168.33.41"
end
# Managerサーバ#2 (あとでクラスタを追加したいために用意)
config.vm.define "manager2" do |node|
node.vm.provider "virtualbox" do |vm|
vm.name = "manager2"
vm.customize ["modifyvm", :id, "--memory", "512"]
end
node.vm.box = "centos/7"
node.vm.hostname = "manager2"
node.vm.network "private_network", ip: "192.168.33.42"
end
# Workerサーバ#1
config.vm.define "worker1" do |node|
node.vm.provider "virtualbox" do |vm|
vm.name = "worker1"
vm.customize ["modifyvm", :id, "--memory", "512"]
end
node.vm.box = "centos/7"
node.vm.hostname = "worker1"
node.vm.network "private_network", ip: "192.168.33.51"
end
# Workerサーバ#2
config.vm.define "worker2" do |node|
node.vm.provider "virtualbox" do |vm|
vm.name = "worker2"
vm.customize ["modifyvm", :id, "--memory", "512"]
end
node.vm.box = "centos/7"
node.vm.hostname = "worker2"
node.vm.network "private_network", ip: "192.168.33.52"
end
end
仮想マシンを起動
$ vagrant up
$ vagrant ssh-config >> ~/.ssh/config
Docker CEのインストール
コミュニティエディションでインストールします。
Managerサーバ、Workerサーバで以下のコマンドを実行してインストールします。
$ sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install -y docker-ce
バージョンでも確認しておきます。
$ docker -v
Docker version 18.03.1-ce, build 9ee9f40
Dockerの起動
Managerサーバ、Workerサーバで以下のコマンドを実行して起動します。
$ sudo systemctl start docker
$ sudo systemctl enable docker
ここまででインストール完了したので、
次はSwarmでクラスタを構築します。
Docker Swarmでクラスタを構築
クラスタの初期化
$ sudo docker swarm init --advertise-addr 192.168.33.41
Swarm initialized: current node (7i9tnczzu1usm5bijr532j7ou) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4ieqe6ymrsxevbyo0875l8h20q54ma80lddvmrqwep0nib51dd-ele3qb3mxsioopz2fqcjteux3 192.168.33.41:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
上記に記載のコマンドによって、あとでワーカーノード(Worker#1, Worker#2)をクラスタに追加します。トークンは実行環境によって異なるので注意してください。
また、注意が必要ですが、マネージャノード(Manager#2)をクラスタに追加する際のトークンが異なります。
マネージャをクラスタに追加するためのトークンは以下のコマンドで確認できます。
$ sudo docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4ieqe6ymrsxevbyo0875l8h20q54ma80lddvmrqwep0nib51dd-02ym4vkgpi7r895buzxne1sl3 192.168.33.41:2377
$ sudo docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
7i9tnczzu1usm5bijr532j7ou * manager1 Ready Active Leader 18.03.1-ce
クラスタに追加
ワーカーノードをクラスタに追加
ワーカーノードをクラスタに追加します。
Worker#1, Worker#2で実行してください。
$ sudo docker swarm join --token SWMTKN-1-4ieqe6ymrsxevbyo0875l8h20q54ma80lddvmrqwep0nib51dd-ele3qb3mxsioopz2fqcjteux3 192.168.33.41:2377
This node joined a swarm as a worker.
マネジャーノードをクラスタに追加
今度は、Manager#2をマネジャノードとしてクラスタに追加します。
トークンがワーカーノードで実行した時のものと異なっていることに注意してください。
$ sudo docker swarm join --token SWMTKN-1-4ieqe6ymrsxevbyo0875l8h20q54ma80lddvmrqwep0nib51dd-02ym4vkgpi7r895buzxne1sl3 192.168.33.41:2377
This node joined a swarm as a manager.
クラスタ構築できたか確認する
クラスタのどこかのノードで実行して確認してください。
以下のようになっていればOKです。
[vagrant@manager1 ~]$ sudo docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
7i9tnczzu1usm5bijr532j7ou * manager1 Ready Active Leader 18.03.1-ce
woryol5l22uwaw20cgkdeni8c manager2 Ready Active Reachable 18.03.1-ce
y2ix3jsrefb46u4ibvhxzsvhz worker1 Ready Active 18.03.1-ce
gs5bzrxb76glo40wn92psl0f3 worker2 Ready Active 18.03.1-ce
*
がついているのノードがこのコマンドを実行しているノードです。
デプロイ
Alpine Linuxからdocker.comにpingを行うサービスを追加します。起動するコンテナ数は1つです。
$ sudo docker service create --replicas 1 --name helloworld alpine ping docker.com
rr5zwn0fyamykt79ihr08c5te
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
起動しているサービス一覧にhelloworldが追加されている事を確認します。
$ sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
rr5zwn0fyamy helloworld replicated 1/1 alpine:latest
サービス内(helloworld)でどのようなコンテナを実行しているかを確認するためには、以下のコマンド。
$ sudo docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
wxjc7ttz1u3h helloworld.1 alpine:latest worker1 Running Running about a minute ago
スケールアウト
サービスを1から5に変更します。
$ sudo docker service scale helloworld=5
helloworld scaled to 5
overall progress: 5 out of 5 tasks
1/5: running
2/5: running
3/5: running
4/5: running
5/5: running
verify: Service converged
$ sudo docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
wxjc7ttz1u3h helloworld.1 alpine:latest worker1 Running Running 4 minutes ago
2wiqq5ff537d helloworld.2 alpine:latest manager1 Running Running about a minute ago
ah46fj4uwq5k helloworld.3 alpine:latest manager2 Running Running about a minute ago
o6om7iyhtf5e helloworld.4 alpine:latest manager2 Running Running about a minute ago
22ptlffc7bmd helloworld.5 alpine:latest worker2 Running Running about a minute ago
備忘録
Docker Swarmは過半数のマネージャーを失うとタスクを評価できなくなり自動的に回復できなくなる。
そのため、マネージャーノードは奇数台で構築するのがよさそう。
用語
- ノード
- Swarm内に参加する Docker Engineインスタンス。
- マネージャーノード
- アプリケーションをswarmにデプロイするには、マネージャノード(manager node)にサービス定義を送信します。マネージャはワーカーノードへタスクと呼ばれる単位を送ります。
- マネージャノードはswarmの期待状態(desired state)を維持するために、オーケストレーションと管理機能を処理。マネージャはオーケストレーションタスクを処理するため、単一のリーダーを選出(elect)する。
- ワーカーノード
- ワーカ・ノード(worker nodes) はマネージャ・ノードから送られてきたタスクの受信して処理する。
- デフォルトでは、マネージャノードはワーカーノードも兼ねるが、マネージャのみのノード(manager-only node)としてもマネージャを設定可能。割り当てられたタスクの現在の状況をマネージャノードに伝えることによって、マネージャは期待状態を維持できます。
- サービス
- アプリケーションを作り上げるための様々なタスクを、どのように実行するかという定義
- サービスの作成時に指定するのは、どのコンテナのイメージを使い、コンテナ内でどのようなコマンドを実行するか
- 以下のサービスがある。
- 複製サービス
- 期待状態の指定に基づき、swarm マネージャがノード間に複製タスク(replica task)を指定した数だけ分散する
- グローバル・サービス
- 特定のタスクをクラスタ内の全ノード上で利用可能になるようにswarmが実行する。
- 複製サービス
- タスク
- Dockerコンテナを運び、コンテナ内でコマンドを実行する。swarmにおける最小スケジューリング単位です。
- マネージャノードはワーカノードに対してタスクを割り当てる。割り当てる数はサービスのスケールで設定されたレプリカ数に応じる。