2019年6月15日土曜日

docker-compose で ElasticSearch7.1 クラスタを構築してみた

概要

公式のドキュメントに docker-compose で立ち上げる YAML があったので試してみました
公式だとうまく動作しない部分があったので少し変更しています
※公式だとノードを追加した際にうまく動作しません

環境

  • macOS 10.14.5
  • docker 18.09.2
  • docker-compose 1.23.2
  • ElasticSearch 7.1.1

P.S 20190621 docker for mac の場合メモリの割り当て上限を増やすこと

デフォルトは 2.0GiB なので 4.0GiB に変更しましょう
そうすれば公式のデフォルトの YAML ファイルでも動作します

docker-compose

  • vim docker-compose.yml
version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.1
    container_name: es01
    hostname: es01
    environment:
      - cluster.name=docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - esdata01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - esnet
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.1
    container_name: es02
    hostname: es02
    environment:
      - cluster.name=docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - esdata02:/usr/share/elasticsearch/data
    networks:
      - esnet

volumes:
  esdata01:
    driver: local
  esdata02:
    driver: local

networks:
  esnet:

2 台構成になっています
ボリュームプラグインは local を使っています
docker on Mac の場合、データ領域は専用の VM になるので注意してください (参考)

ネットワークは esnet という名前の専用ネットワークを作成しています
このネットワーク上では各ノードは services に定義した名前でアクセスできます
あとはクラスタを構成するための環境変数の設定とコンテナの ulimit の設定になります

起動したらクラスタのステータスを確認しましょう
green になっていれば OK です

  • curl http://127.0.0.1:9200/_cat/health
1560309775 03:22:55 docker-cluster green 2 2 2 1 0 0 0 0 - 100.0%
  • curl localhost:9200/_cat/nodes
192.168.160.3 31 89 3 1.13 0.71 0.27 mdi - es02
192.168.160.2 32 89 3 1.13 0.71 0.27 mdi * es01

es01 が master になりました

設定ファイルを確認してみる

環境変数に設定したデータは設定ファイルに反映されています
コンテナとして立ち上げた場合設定ファイルは /usr/share/elasticsearch/config/elasticsearch.yml に配置されています

  • docker-compose exec es01 cat /usr/share/elasticsearch/config/elasticsearch.yml
cluster.name: "docker-cluster"
network.host: 0.0.0.0

中身はほとんど書かれていないようです
では設定した環境変数はどこに渡されているかというとプログラムを実行する引数に渡されています
わかりやすいようにコマンドを工夫しています

  • for i in $(docker exec es01 ps aux); do echo ${i} | grep '^-E'; done
-Ecluster.initial_master_nodes=es01,es02
-Ecluster.name=docker-cluster
-Ediscovery.seed_hosts=es01,es02

こんな感じで渡されていました
おそらく環境変数は上記のようにすべてプログラムに渡すようになっているので他のパラメータも環境変数で渡すことができると思います

テストデータを入れてみる

テストデータも提供してくれているのでそれを使います

  • curl -O https://download.elastic.co/demos/kibana/gettingstarted/7.x/shakespeare.json

まずはマッピングを作成します

curl -X PUT "localhost:9200/shakespeare" -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "properties": {
    "speaker": {"type": "keyword"},
    "play_name": {"type": "keyword"},
    "line_id": {"type": "integer"},
    "speech_number": {"type": "integer"}
    }
  }
}
'

作成できたらデータを投入します
bulk API というのがあるのでこれを使います
データが大きいので少し時間がかかります

  • curl -s -o /dev/null -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/shakespeare/_bulk?pretty' --data-binary @shakespeare.json

成功したら確認しましょう

  • curl -X GET "localhost:9200/_cat/indices?v"
health status index       uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   shakespeare egTnaoHnS3SQ5fWuOZkgfg   1   1     111396            0     39.1mb         19.5mb
  • curl -X GET "localhost:9200/shakespeare/_count"
{"count":111396,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0}}

一度コンテナを削除し立ち上げ直してもデータが残っていることが確認できると思います

  • docker-compose down
  • docker-compose up -d
  • curl -X GET "localhost:9200/shakespeare/_count"

=> 111396

ノードを追加するには

試しにスケールしてみましたがコンテナ名を指定しているため当然アウトでした

  • docker-compose up --scale es02=2

=> ERROR: for es02 Cannot create container for service es02: Conflict. The container name "/es02" is already in use by container

docker-compose.yml に es03 を追記してクラスタに es03 も追加するように記載してみます

  • docker-compose down

一旦コンテナを削除します
-v は付けずにデータボリュームは残します
そして 3 台目のホスト情報を YAML ファイルに記載します

  • vim docker-compose.yml
version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.1
    container_name: es01
    hostname: es01
    environment:
      - cluster.name=docker-cluster
      - discovery.seed_hosts=es01,es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - esdata01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - esnet
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.1
    container_name: es02
    hostname: es02
    environment:
      - cluster.name=docker-cluster
      - discovery.seed_hosts=es01,es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - esdata02:/usr/share/elasticsearch/data
    networks:
      - esnet
  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.1
    container_name: es03
    hostname: es03
    environment:
      - cluster.name=docker-cluster
      - discovery.seed_hosts=es01,es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - esdata03:/usr/share/elasticsearch/data
    networks:
      - esnet

volumes:
  esdata01:
    driver: local
  esdata02:
    driver: local
  esdata03:
    driver: local

networks:
  esnet:

services に es03 が追加になったのとそれに伴い volumes も追加しています
また各ホストの discovery.seed_hostscluster.initial_master_nodes に es03 の情報を追加しています
これで再度コンテナを起動しましょう

  • docker-compose up -d

すると今度は 3 台構成で起動します

  • curl localhost:9200/_cat/health
1560386296 00:38:16 docker-cluster green 3 3 0 0 0 0 0 0 - 100.0%
  • curl localhost:9200/_cat/nodes
192.168.176.3 16 96 88 5.93 2.61 1.03 mdi - es02
192.168.176.4 20 96 88 5.93 2.61 1.03 mdi * es01
192.168.176.2 17 96 88 5.93 2.61 1.03 mdi - es03

master は変わらず es01 でした

failover させてみる

では es01 をダウンさせてみましょう

  • docker-compose stop es01

しばらくしてから es02 に問い合わせると 2 台構成になっているのが確認できると思います

  • docker-compose exec es02 curl localhost:9200/_cat/health
1560386492 00:41:32 docker-cluster green 2 2 0 0 0 0 0 0 - 100.0%
  • docker-compose exec es02 curl localhost:9200/_cat/nodes
192.168.176.2 40 73 3 0.38 1.41 0.85 mdi * es03
192.168.176.3 40 73 3 0.38 1.41 0.85 mdi - es02

master は es01 -> es03 になったようです
これで再度 es01 を起動してみましょう

  • docker-compose start es01

また helth と nodes を確認すると 3 台構成に戻っているのが確認できると思います
また master は変わらず es03 になっていると思います

ポイント解説

過去に Ubuntu 上で ElasticSearch7.1 のクラスタ環境を構築したときとほぼ同じになります
カーネルパラメータ系はイメージ側で対応してくれています
公式の docker-compose.yml で ulimit だけ指定があったのでそのまま使っています
コンテナの hostname を指定し elasticsearch を起動時のオプションで node.name を指定しないようにしました
あと bootstrap.memory_lock=true も不要だったので削除しました

また今回はノードを追加する際に down -> up で追加しましたが down させないで docker-compose.yml を編集して up しても追加できると思います

最後に

docker-compose.yml で ElasticSearch7.1 のクラスタを構築してみました
公式のままだとノード追加がうまくいかなかったので少し修正しています

Kibana や Cerebo と連携するときは同じ docker-compose.yml 内に定義してあげるかホストの 9200 を見に行くようにすれば OK です
ただ今回は es01 しか 9200 を LISTEN していないので es01 がダウンした場合は必ず restart してあげる必要があります
もしくはそれが面倒なら 3 台の ElasticSearch の前に nginx などを立てて 9200 をバランシングしてあげる必要があるかなと思います

参考サイト

0 件のコメント:

コメントを投稿