[v8.7] Elasticsearch multinode/dedicaded masterをdocker-composeでインストールする手順（試用用途）

# はじめに
`docker-compose`でElasticsearchクラスタを作成する記事を２つ書いてきました。
- 最もシンプルなシングルノード構成
    - https://qiita.com/takeo-furukubo/items/c2f194679afadc06a4e9
- Fleetを追加した構成
    - https://qiita.com/takeo-furukubo/items/591617ea57e537046fb8

今回は下記の２点を試してみます。
- Elasticsearchをmultinodeにする
- dedicated master nodeにする

## dedicated masterとは
dedicated masterというのは、master nodeの役割に専念させるノードのことです。
大規模構成でmasterをdata nodeに兼任させた場合、dataの処理にCPU・メモリを取られてしまうと、masterとしての処理が遅くなり、クラスタへの影響が出ることがあります。
それを避けるために、弊社クラウドサービスでも６ノードを超えると自動的にdedicated masterとなります。
参考のドキュメントはこちらです。
https://www.elastic.co/guide/en/elasticsearch/reference/8.7/modules-node.html#dedicated-master-node
### クラウドサービスでの例
クラウドのPricing Calculatorでもこのようになります。
※[Pricing Calculator](https://cloud.elastic.co/pricing)
Hot Nodeを６ノード以上に設定すると、以下のようにMaster instancesというのが自動的に追加されます。
Hot: 2ノード/Warm: 2ノード/Frozen: 2ノードの合計６ノードとかでも同様です。
![スクリーンショット 2023-05-23 10.37.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2603229/702b38a8-6013-1b7e-4560-3f02472ebfbe.png)
### オンプレミスは？
本番環境ではオンプレミスでも同様にdedicated masterを持つことをお勧めしますので、それをお気軽にテストするために本記事を書いています。

# 本手順を試した環境

- クラウド：GCP
- OS: Ubuntu 18.04.6 LTS
- スペック: e2-standard-2インスタンス (2 vCPU, 8GB mem)
- Docker version 23.0.5, build bc4487a
- docker-compose version 1.29.2, build 5becea4c

# ドキュメント
基本はこれです。
https://www.elastic.co/guide/en/elasticsearch/reference/8.7/docker.html#docker-compose-file
ここに記載されている構成は３ノード構成でmasterはdata nodeに共存しています。
これをdedicated masterを設定できるように変更します。

# 設定ファイル
Gitからクローンしてください。
https://github.com/legacyworld/elasticstack

singlenodeとmultinodeの２つのディレクトリができますが、今回はmultinode/8.xです。

## 弊社ドキュメントからの変更点
`docker-compose.yml`のみ変更します。
### 証明書関係
masterもクラスタに参加するので、証明書を作成します。
これはコピペするだけです。
`es01`の部分を名前を変えてるだけです。
`setup`の`command`部分に以下を追加します。(master02/03も)
```
          "  - name: master01\n"\
          "    dns:\n"\
          "      - master01\n"\
          "      - localhost\n"\
          "    ip:\n"\
          "      - 127.0.0.1\n"\
```
### masterノードの設定を追記
`es01`を丸々コピーして"es01"を全て"master01","master02","master03"に変更します。
```
  master01:
    depends_on:
      setup:
        condition: service_healthy
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    volumes:
      - certs:/usr/share/elasticsearch/config/certs
      - masterdata01:/usr/share/elasticsearch/data
    environment:
      - node.name=master01
      - cluster.name=${CLUSTER_NAME}
      - cluster.initial_master_nodes=master01,master02,master03
      - discovery.seed_hosts=master01,master02,master03
      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
      - bootstrap.memory_lock=true
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=true
      - xpack.security.http.ssl.key=certs/master01/master01.key
      - xpack.security.http.ssl.certificate=certs/master01/master01.crt
      - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.http.ssl.verification_mode=certificate
      - xpack.security.transport.ssl.enabled=true
      - xpack.security.transport.ssl.key=certs/master01/master01.key
      - xpack.security.transport.ssl.certificate=certs/master01/master01.crt
      - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.transport.ssl.verification_mode=certificate
      - xpack.license.self_generated.type=${LICENSE}
      - node.roles=[master]
    mem_limit: ${MEM_LIMIT}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120
```
### master関係のパラメータ
`discovery.seed_hosts`,`cluster.initial_master_nodes`の２つがあります。
違いはここに説明があります。
https://www.elastic.co/guide/en/elasticsearch/reference/8.7/_discovery_configuration_check.html
https://discuss.elastic.co/t/discovery-seed-hosts-and-cluster-initial-master-nodes/330945
まぁ、どちらもdedicated masterを書いておけば良さそうです。
なので両方ともmaster01/master02/master03に変更します
kibana以外の`environment`の以下の部分を変更します
```
      - cluster.initial_master_nodes=master01,master02,master03
      - discovery.seed_hosts=master01,master02,master03
```

### node role
node roleはそのノードがどのような役割をするかを設定するパラメータです。
ドキュメントはこちら
https://www.elastic.co/guide/en/elasticsearch/reference/8.7/modules-node.html#node-roles

何も設定しないと全てのroleが設定されます。
今回はmasterとdataを分けるので以下のように記載します。
- master01/02/03
    - `environment`に` - node.roles=[master]`を追加
- es01/02/03
    - `environment`に` - node.roles=[data,ingest]`を追加

### volumes
こちらは増えたノード分だけ追記するだけです。

# 起動
multinode/8.xディレクトリで`docker-compose up -d`と実行します。
かなり時間がかかります（今回の環境では８分ほど）
`docker-compose logs -f`を眺めておきましょう。

# Kibanaへのアクセス
これまでと同じです。
`https://<IP address>:5601`

# 確認
Kibana -> Management -> Dev Toolsをクリックして、以下のように入力してみましょう。
`GET _cat/nodes?v=true`
以下のような結果が得られます。
```
ip         heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
172.20.0.7           28          95   5    2.07    2.24     1.00 di        -      es02
172.20.0.5           31          97   5    2.07    2.24     1.00 m         -      master03
172.20.0.6           52         100   5    2.07    2.24     1.00 di        -      es01
172.20.0.8           24          93   5    2.07    2.24     1.00 di        -      es03
172.20.0.4           40          99   5    2.07    2.24     1.00 m         *      master02
172.20.0.3           33          97   5    2.07    2.24     1.00 m         -      master01
```
`node.role`の`di`は"data,ingest"、`m`は"master"なのでちゃんとdedicated masterを設定できています。

# 停止
`docker-compose.yml`ファイルのある場所で`docker-compose down -v`
Volumeも消します

# 削除
全てのコンテナイメージやボリュームなどまとめて消したい場合は停止後に`docker system prune -a`
勿論Elasticsearch以外も消してしまいますのでご注意を。

# 最後に
これまでの３つの記事で様々な構成を`docker-compose`で簡単に作成できます。
簡単に作って破棄することができるので、いろんな試験をしたい際にご利用ください。

### Elastic Cloud 無料トライアル
こちらからElastic Cloudの14日間無料トライアルを是非お試しください
[Elastic Cloud 無料トライアル](https://cloud.elastic.co/)

手順は下記リンクをご参照ください
[Elastic Cloud について　〜実際にデプロイメントを作ってみよう〜](https://qiita.com/tomo_s_el/items/3584d0b1fabb0bafa4fa)