Dockerを使用した複数ホストでのElasticsearchクラスタの構築検証

※こちらの記事は2017年にQiitaに投稿した記事を再編集したものです

Elasticsearchは公式でコンテナイメージを提供してくれているのでそれを利用してクラスタを組みたいと思います。
ドキュメントにはdocker-compose.ymlも公開されていますが、docker-composeということはコンテナホストはひとつになるから可用性的にNGだなー、と感じました。(Swarm modeとか使うと解決できるのかな?)
コンテナホストは複数台に分散したいと考えたので、検証してみました。

検証環境

  • Mac OS X El Capitan(10.11.6)
  • docker-machine version 0.10.0, build 76ed2a6
  • VirtualBox 5.1.14 r112924 (Qt5.6.2)

ポイント

  • docker-machineを利用してVirtualBox上に3つのコンテナホストを起動
  • 各コンテナホストに公式のコンテナイメージをデプロイ
  • Dockerのネットワークドライバはhostモードを利用する

検証手順

コンテナホストの準備

コンテナホストの作成

VirtualBox上にコンテナホストを3つ起動します。

$ docker-machine create --driver virtualbox elasticsearch1
$ docker-machine create --driver virtualbox elasticsearch2
$ docker-machine create --driver virtualbox elasticsearch3

コンテナホストのメモリマップ上限の引き上げ

公式にも書いてある通り、設定しないとコンテナが起動しない(開発者モードなら起動するかも)ので設定します。

$ docker-machine ssh elasticsearch1 sudo sysctl -w vm.max_map_count=262144
$ docker-machine ssh elasticsearch2 sudo sysctl -w vm.max_map_count=262144
$ docker-machine ssh elasticsearch3 sudo sysctl -w vm.max_map_count=262144

Elaticsearchの起動〜動作確認

Elasticsearchコンテナの起動

Elasticが独自に公開しているコンテナレジストリよりイメージを取得して起動します。
環境変数(-e)でパラメータを渡すとElasticsearchの設定を上書きできるのでいきなり起動できます。
検証で渡したパラメータは以下の通り。

環境変数名パラメータに渡す値説明
network.host_eth1:ipv4_hostモードでコンテナを起動するとホストのNICが全部マッピングされますが、このオプションを指定しないとElasticsearchはeth0のIPアドレスをデフォルトで指定するようです。
eth0のIPアドレスはプライベートなIPアドレスが割り当てられていて外部と通信できないのでeth1を明示しています。
discovery.zen.ping.unicast.hosts自分自身以外のコンテナホストのIPアドレスをカンマ区切りクラスタに参加させるホストを明示します。
discovery.zen.minimum_master_nodes2ノード数/2+1を設定するようドキュメントにも記載されているので従います。
xpack.security.enabledfalse今回の検証には不要なのでX-PackのSecurityを無効化します。
xpack.monitoring.enabledfalse今回の検証には不要なのでX-PackのMonitoringを無効化します。
xpack.watcher.enabledfalse今回の検証には不要なのでX-PackのWatcherを無効化します。
xpack.graph.enabledfalse今回の検証には不要なのでX-PackのGraphを無効化します。
xpack.ml.enabledfalse今回の検証には不要なのでX-PackのMachine Learningを無効化します。
ES_JAVA_OPTS-Xms512m -Xmx512mElasticsearchが使用するjavaのヒープサイズを指定します。
コンテナホストのメモリを増やすという方法もありますが、3台も2GB以上のホストを起動したらこのMacがゲロ重になるのでこうしました。

その他にコンテナに渡したオプションは以下の通り

オプション説明
-dデタッチドモードでコンテナを起動。
説明はいらないですよね?
–network=”host”コンテナのネットワークモードをhostに設定します。
コンテナホストのネットワークインターフェースがそのままコンテナ上でも利用されます。
-p 9200:9200Elasticsearchのサービスポートを公開します。
-P(大文字)でもよかったかも。
-p 9300:9300Elasticsearchがノード間のコミュニケーションで使用するポートを公開します。
-P(大文字)でもよかったかも。
$ eval $(docker-machine env elasticsearch1)
$ docker run -d \
  -e "network.host=_eth1:ipv4_" \
  -e "discovery.zen.ping.unicast.hosts=$(docker-machine ip elasticsearch2),$(docker-machine ip elasticsearch3)" \
  -e "discovery.zen.minimum_master_nodes=2" \
  -e "xpack.security.enabled=false" \
  -e "xpack.monitoring.enabled=false" \
  -e "xpack.watcher.enabled=false" \
  -e "xpack.graph.enabled=false" \
  -e "xpack.ml.enabled=false" \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  --network="host" \
  -p 9200:9200 \
  -p 9300:9300 \
  docker.elastic.co/elasticsearch/elasticsearch:5.4.0
$ eval $(docker-machine env elasticsearch2)
$ docker run -d \
  -e "network.host=_eth1:ipv4_" \
  -e "discovery.zen.ping.unicast.hosts=$(docker-machine ip elasticsearch1),$(docker-machine ip elasticsearch3)" \
  -e "discovery.zen.minimum_master_nodes=2" \
  -e "xpack.security.enabled=false" \
  -e "xpack.monitoring.enabled=false" \
  -e "xpack.watcher.enabled=false" \
  -e "xpack.graph.enabled=false" \
  -e "xpack.ml.enabled=false" \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  --network="host" \
  -p 9200:9200 \
  -p 9300:9300 \
  docker.elastic.co/elasticsearch/elasticsearch:5.4.0
$ eval $(docker-machine env elasticsearch3)
$ docker run -d \
  -e "network.host=_eth1:ipv4_" \
  -e "discovery.zen.ping.unicast.hosts=$(docker-machine ip elasticsearch1),$(docker-machine ip elasticsearch2)" \
  -e "discovery.zen.minimum_master_nodes=2" \
  -e "xpack.security.enabled=false" \
  -e "xpack.monitoring.enabled=false" \
  -e "xpack.watcher.enabled=false" \
  -e "xpack.graph.enabled=false" \
  -e "xpack.ml.enabled=false" \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  --network="host" \
  -p 9200:9200 \
  -p 9300:9300 \
  docker.elastic.co/elasticsearch/elasticsearch:5.4.0

Clusterのステータスを確認する

3台起動したのでクラスタのステータスを確認してみます。

$ curl $(docker-machine ip elasticsearch1):9200/_cat/health?v
epoch      timestamp cluster        status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1496326996 14:23:16  docker-cluster green           3         3      0   0    0    0        0             0                  -                100.0%
$ curl $(docker-machine ip elasticsearch1):9200/_cluster/health?pretty
{
  "cluster_name" : "docker-cluster",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 0,
  "active_shards" : 0,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}

以下の点が確認できればよいと思います。

  • statusがgreen
  • ノードの数が3
  • データノードの数が3

インデックスを作って確認してみる

クラスタが組めてそうなのでインデックスを作ってみます。

$ curl -XPUT $(docker-machine ip elasticsearch1):9200/test?pretty
{
  "acknowledged" : true,
  "shards_acknowledged" : true
}

クラスタなので、どのIPアドレスに問い合わせても上記で作成したインデックスができていれば問題ないでしょう。
確認してみます。

$ curl $(docker-machine ip elasticsearch1):9200/_cat/indices?v
health status index uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   test  0iOZud02QHqPMkcDemgdWg   5   1          0            0      1.2kb           650b

1台目はできてます。ここはインデックスを作ったときに指定したホストなので当然ですね。

$ curl $(docker-machine ip elasticsearch2):9200/_cat/indices?v
health status index uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   test  0iOZud02QHqPMkcDemgdWg   5   1          0            0      1.2kb           650b

2台目でもできてますね。順調。

$ curl $(docker-machine ip elasticsearch3):9200/_cat/indices?v
health status index uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   test  0iOZud02QHqPMkcDemgdWg   5   1          0            0      1.2kb           650b

3台目にもありました。バッチリ。

まとめ

以上で複数ホストにまたがった可用性のあるElasticsearchクラスタをコンテナで起動することができました。
このあとはcloud-awsプラグインを使用してEC2上にデプロイする方法などを検証してみようかなーと思っています。(コンテナでもできるのかな?)
Amazon Elasticsearch ServiceはVPCに対応してないのが残念ですよね。 サポートしましたね。

お気づきの点とかあれば優しくご指摘頂ければと思います。

コメント

タイトルとURLをコピーしました