はじめに
生産技術部で製品の検査工程を担当しているエンジニアです。Elastic Stackを実際に運用していくために、ローカル環境にElastic Stackのクラスタを構築し検証を行っています。
本記事では、Swarmモードを利用し、Docker Machineでクラスタを構築するための事前準備から、構築手順、動作検証用のログ生成、運用方法についてまとめましたので紹介します。
go言語で記述したログ生成ツールを作成し、生成したログをElastic Stackに取り込み、Kibana上で正しく表示されていることを確認しましたので、合わせてツールも紹介します。
リポジトリに、作成したファイル一式を追加しました。
https://gitlab.com/iyama_yuki/elastic-stack-swarm
環境
$ docker -v
Docker version 20.10.5, build 55c4c88
$ docker-compose -v
docker-compose version 1.28.5, build c4eb3a1f
$ docker-machine -v
docker-machine version 0.16.2, build bd45ab13
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
elasticsearch-data-01 - virtualbox Running tcp://192.168.99.111:2376 v19.03.12
elasticsearch-data-02 - virtualbox Running tcp://192.168.99.112:2376 v19.03.12
elasticsearch-data-03 - virtualbox Running tcp://192.168.99.113:2376 v19.03.12
elasticsearch-master-01 - virtualbox Running tcp://192.168.99.106:2376 v19.03.12
elasticsearch-master-02 - virtualbox Running tcp://192.168.99.107:2376 v19.03.12
elasticsearch-master-03 - virtualbox Running tcp://192.168.99.108:2376 v19.03.12
filebeat-01 - virtualbox Running tcp://192.168.99.117:2376 v19.03.12
filebeat-02 - virtualbox Running tcp://192.168.99.118:2376 v19.03.12
kibana - virtualbox Running tcp://192.168.99.119:2376 v19.03.12
local * virtualbox Running tcp://192.168.99.105:2376 v19.03.12
logstash-01 - virtualbox Running tcp://192.168.99.114:2376 v19.03.12
logstash-02 - virtualbox Running tcp://192.168.99.115:2376 v19.03.12
logstash-03 - virtualbox Running tcp://192.168.99.116:2376 v19.03.12
- ハードウェアリソース
$ system_profiler SPHardwareDataType
Hardware:
Hardware Overview:
Model Name: MacBook Pro
Model Identifier: MacBookPro15,1
Processor Name: 8-Core Intel Core i9
Processor Speed: 2.4 GHz
Number of Processors: 1
Total Number of Cores: 8
L2 Cache (per Core): 256 KB
L3 Cache: 16 MB
Hyper-Threading Technology: Enabled
Memory: 32 GB
事前準備
Swarmモードを利用してクラスタの構築を行っていきますが、まずはDocker Machineの準備と、Swarmクラスタへノードを参加させる必要があります。
Swarmモードとは
SwarmモードはDocker Engine1 1.12以降に組み込まれたクラスタ管理及びオーケストレーション機能のことで、オーケストレーション・ソフトウェアを別途インストールする必要はありません。Swarmモードで動作する複数のDockerホストによって、Swarm(クラスタ)を構成し、各ノードはManagerもしくはWorkerの役割を持ちます。Managerとして設定したノードはWorkerノードの管理を行い、Workerとして設定したノードはサービス2を実行します。今回は、検証のためにMasterノードが1台で構成しましたが複数台用意する必要があります。Managerノードが故障した場合に、サービスは稼働し続ける事ができますが再度クラスタを作成する必要があります。3つのManagerノードを用意しておく事で1つのManagerノードの故障に耐える事ができます。N
個のノードでは、(N-1)/2
個のManagerノードの故障に耐える事ができます。
Docker Machineの作成
Docker Machineは、仮想マシン上にDocker Engineをインストールするツールであり、複数のDockerホストの起動、停止、再起動等を行う事が出来ます。ローカル、クラウドに関わらずDockerが利用できるホストであれば、同様に管理する事ができます。
以下のコマンドは、virtualboxをドライバとして利用し、elasticsearch-data-01
という名称のホストを用意します。ディストリビューションはDocker Engineを実行するための最小の機能を有するboot2docker
が利用されています。今回は13台のマシンを利用するため、13台分作成し1台はlocalと言う名前のManagerノードとしました。実運用では耐故障性を向上させるために、前述の通り3台以上のManagerノードを追加する必要性があります。
$ docker-machine create --driver virtualbox elasticsearch-data-01 # workerノード
追加したマシンの一覧を確認することができます。
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
elasticsearch-data-01 - virtualbox Running tcp://192.168.99.111:2376 v19.03.12
作成したマシンに対して、Docker CLIを利用するためには、envを設定する必要があります。設定することでACTIVEの項目が*
となり、elasticsearch-data-01に対してDocker CLIが実行できるようになります。
$ eval "$(docker-machine env elasticsearch-data-01)"
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
elasticsearch-data-01 * virtualbox Running tcp://192.168.99.111:2376 v19.03.12
Swarmクラスタへの参加
以下のコマンドを実行する事で、直近に作成したクラスタ上のManagerノードになることが出来ます。
$ eval "$(docker-machine env local)"
$ docker swarm init
Managerノードで発行したトークンを設定することで、SwarmクラスタにWorkerノードとして参加することが出来ます。
# Managerノードでトークンを確認
$ eval "$(docker-machine env local)"
$ docker swarm join-token worker # workerをmanagerとすることで、managerノードとして参加出来ます。
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-1xopvt9ri58lpbp9poi9bg3du70om35k6mwfctn7cnodjnmbne-cgz0z3783of0o3ftslt4pdbn3 192.168.99.105:2377
# Workerノードに切り替える
$ eval "$(docker-machine env elasticsearch-data-01)"
$ docker swarm join --token SWMTKN-1-1xopvt9ri58lpbp9poi9bg3du70om35k6mwfctn7cnodjnmbne-cgz0z3783of0o3ftslt4pdbn3 192.168.99.105:2377
Managerノードから、参加しているノード一覧を確認する事が出来ます。MANAGER STATUSのLeader
はManagerノードである事を意味します。
$ eval "$(docker-machine env local)"
% docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
x1bdzf22dk9rarffbplaimeyn elasticsearch-data-01 Ready Active 19.03.12
y201dtu6z4eb722e04xidm9ol * local Ready Active Leader 19.03.12
クラスタ構築
必要なノードを追加が完了すると、サービスをデプロイする事が可能な状態になります。早速、Composeファイルを利用し、サービスをデプロイします。
Composeファイルを利用
サービスをデプロイする方法の一つとして、Composeファイルを利用する方法があります。この方法を用いることによって、一台のホストマシンにデプロイするのと同じように、複数台のホストマシンに対してデプロイする事が可能になります。これは、Docker ComposeとDocker Swarmは完全な統合を目指しているからです。ただし、現状はいくつかの制約があり、完全には統合されていません。
- まず、Composeファイルのバージョンによって利用できる設定が異なります。
- Dockerfileを使ったイメージの構築は出来ません。
- さらに以下のドキュメントで、「swarm」を検索すると複数の制約が確認できます。
- https://docs.docker.com/compose/compose-file/compose-file-v3/
デプロイ方法について各種設定をします。
-
endpoint_mode
- vip(デフォルト)、dnsrrから選択します。
- https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/compose-file-v3/#endpoint_mode
- vipはサービスに対して仮想IPを割り当てます。これは、外部のクライアントからアクセスするためのフロントエンドとして機能します。
- dnsrrはDNSラウンドロビンの事です。外部のロードバランサを利用する場合に利用される方式で、単一の仮想IPを扱いません。代わりに、Dockerはサービスに対するDNSエントリを準備し、サービス名のDNSクエリに対してIPアドレスのリストを返し、クライアントが直接そのIPアドレスにアクセスできるようにします。
-
mode
- global、replicatedから選択します。
- globalは、ノードごとに1つのコンテナをサービスとしてデプロイします。
- replicatedは、指定した数のサービスをデプロイします。replicasに複製する数を設定します。
-
resources
- 利用するハードウェアリソースの制限を設定する事ができます。cpus:"0.50"とすると、CPUの使用率を50%に制限できます。
-
placement
- max_replicas_par_nodeは、ノードごとに複製するサービスの数の最大値を設定します。
- constraintsは、デプロイする先のノードを指定したり、デプロイ先を制限します。ノードのラベルを利用して制限をかける場合には、ノードに対して予めラベルを設定しておく必要があります。以下の例では、デプロイ対象のノードにesというキーとtrueというバリューの組みを追加しています。
deploy:
endpoint_mode: dnsrr
mode: replicated
replicas: 3
resources:
limits:
cpus: "0.50"
memory: 512M
placement:
max_replicas_per_node: 1
constraints: [node.labels.es == true]
サービスのデプロイおよび削除
サービスは1つずつデプロイすることもできますが、スタックを利用すれば一斉にデプロイすることが出来ます。この方法では、Composeファイルを作成しサービスのデプロイを行います。どのマシンに対してデプロイするかは、ComposeファイルのConstraintsを設定することで決定します。ノードに対してラベルを設定しておく事でホストマシンを指定します。複数のノードに同一のラベルを設定することも可能です。
# デプロイ
$ docker stack deploy --compose-file docker-compose.yml mystack
# スタックの削除
$ docker stack rm mystack
デプロイされたサービスの一覧を確認することができます。REPLICASの数字が複製された数を示し、max 1 per node
は1つのノードに対して最大1つまでという制約が設定されていることを確認できます。
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
vu39p5h1ciu8 mystack_es-data replicated 3/3 (max 1 per node) docker.elastic.co/elasticsearch/elasticsearch:7.12.0
9l06iajhebor mystack_es-master replicated 3/3 (max 1 per node) docker.elastic.co/elasticsearch/elasticsearch:7.12.0
iv446tehe3oc mystack_kibana replicated 1/1 docker.elastic.co/kibana/kibana:7.12.0 *:5601->5601/tcp
tjaen6ecqdmc mystack_logstash replicated 3/3 (max 1 per node) docker.elastic.co/logstash/logstash:7.12.0
vkse7irszqmw mystack_metricbeat replicated 1/1 docker.elastic.co/beats/metricbeat:7.12.0
lslw1vi4poae mystack_portainer_master global 1/1 portainer/portainer:latest
Elasticsearchのメモリ設定
Elasticsearchは、コンテナの起動前にmemlockを設定する必要があります。公式では、Composeファイルに設定しコンテナごとに制御していますが、この方法はSwarmで利用する事ができません。そこで、Docker Machineで起動したシステムに対して設定します。Docker Machineのディストリビューションであるboot2dockerに設定します。
$ vi /var/lib/boot2docker/profile
EXTRA_ARGS='
--label provider=virtualbox
--default-ulimit memlock=-1
'
CACERT=/var/lib/boot2docker/ca.pem
DOCKER_HOST='-H tcp://0.0.0.0:2376'
DOCKER_STORAGE=overlay2
DOCKER_TLS=auto
SERVERKEY=/var/lib/boot2docker/server-key.pem
SERVERCERT=/var/lib/boot2docker/server.pem
また、Elasticsearchは、vm.max_map_count
の値も変更する必要があります。Docker Machineに対して設定する場合、sshを利用します。設定したホスト名を指定しsshを実行する事で、マシンにリモートログインします。値を変更しリモートログインから抜けた後に、再起動を実施することで反映されます。
$ docker-machine ssh elasticsearch-data-01
worker $ sudo vi /var/lib/boot2docker/profile
worker $ sudo sysctl -w vm.max_map_count=262144
$ exit
$ docker-machine restart elasticsearch-data-01
動作検証用のログを生成
go言語でログジェネレータを作成
ログを正しく追加できていることを確認するために、ログを定期的に生成するツール「log-generator」をgo言語で作成しました。log-generatorは、ログの生成を継続する期間と、周期を選択する事ができます。使い方は以下の通りです。
$ cd beats/filebeat/helper
$ go run log-generator.go -h
Usage of log-generator:
-d int
duration (default 60)
-p int
period (default 1)
実行すると、動いていることを確認できるログが標準出力されます。
$ cd beats/filebeat/helper
$ go run log-generator.go -d 10
[2021-03-28 20:34:33]create log.
[2021-03-28 20:34:34]create log.
[2021-03-28 20:34:35]create log.
[2021-03-28 20:34:36]create log.
[2021-03-28 20:34:37]create log.
[2021-03-28 20:34:38]create log.
[2021-03-28 20:34:39]create log.
[2021-03-28 20:34:40]create log.
[2021-03-28 20:34:41]create log.
[2021-03-28 20:34:42]create log.
運用方法
Nodeの管理ツール
Portainerを利用しました。コンテナの管理だけでなく、swarmの管理にも対応しています。管理画面からノードのラベルを編集したり、コンテナのスケールの調整、イメージを指定して、新たにサービスを追加することも可能です。実際に管理画面から、elasticsearchのmasterノードをスケールし、3台から2台に変更し、2台から3台に戻した時に正常に復帰する事を確認しました。
最後に
DockerのSwarmモードを利用し、初めて複数台の仮想マシンを使ったクラスタの構築を行いました。Docker Composeは普段から利用しており、スムーズに構築する事ができました。今後は、AWSを使ったクラスタの構築やk8sを試していきたいと思っています。