知識の引き出し

獲得した知識は、使えるように引き出しに整理してしまっておこう。

VagrantでElasticsearchクラスタを作ってみる

まえがき

FEK(fluentd + Elasticsearch + Kibana)によるログ可視化環境を試しに組んでみたところ、ログ検索を担当するElasticsearchが一番のボトルネックだった。

Kibanaのダッシュボードにいくつも定義されたグラフから来る複雑なクエリのお陰でCPU、メモリはカツカツだし、1日1GB以上生成されるログでDISKもパンパン、全てのリソースが一番最初に音を上げてしまう明らかなボトルネックになることがわかった。

そこで、Elasticsearchをクラスタ構成にして負荷分散を図り、さらにDISK容量もスケールアウトできないか。

Elasticsearchはスケールアウト可能だとは聞いていたので、手元のPC上でVMを立て冗長構成を試してみた。 その時の構築メモを残しておく。

※かなり時間が経ってしまって、バージョンなどは古くなってしまったがあしからず。

環境

HW

 MacBook Air (OSX Yosemite 10.10.5)

VM

 CentOS 6.5 ( on Vagrant 1.6.3 )

SW

  • OpenJDK (64bit) 1.8.0_51
  • Elasticsearch 1.7.1

Elasticsearchは実施時点で最新のものを利用。

Vagrantインスタンスを立てる

以下の様なVagrantfileを用意して、vagrant up

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "centos65_x86_64"

  config.vm.define :web1 do |web|
    web.vm.network :private_network, ip: "192.168.33.10"
    web.vm.provider "virtualbox" do |vb|
      vb.memory = "1048"
    end
  end

  config.vm.define :web2 do |web|
    web.vm.network :private_network, ip: "192.168.33.11"
    web.vm.provider "virtualbox" do |vb|
      vb.memory = "1048"
    end
  end

  config.vm.define :web3 do |web|
    web.vm.network :private_network, ip: "192.168.33.12"
    web.vm.provider "virtualbox" do |vb|
      vb.memory = "1048"
    end
  end

end

Elasticsearchのインストール

Elasticsearchを動かすにはJavaが必要。 なのでインストールの順番はJava→Elasticsearchとする。

Javaのインストール

yumでインストールするが、バージョンを選ぶためにyum searchしてからインストールするバージョンを指定。

$ sudo yum search openjdk
                   ・
                   ・
                 (略)
java-1.8.0-openjdk.x86_64 : OpenJDK Runtime Environment
java-1.8.0-openjdk-debug.x86_64 : OpenJDK Runtime Environment with full debug on
java-1.8.0-openjdk-demo.x86_64 : OpenJDK Demos
                   ・
                   ・
                 (略)

# 1.8をインストール
$ sudo yum install java-1.8.0-openjdk.x86_64

Elasticsearch本体のインストール

Elasticsearchの公式サイトからダウンロードするのか一覧が確実。

$ sudo wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.1.zip

設定

elasticsearch.yml で以下の設定を3台とも同じにする。

cluster.name: mycluster

host名が名前解決出来ないと起動時にエラーになるため、/etc/hostsに設定追加。

192.168.33.10 web1
192.168.33.11 web2
192.168.33.12 web3

起動

以上ができたら起動。

# ./elasticsearch-1.7.1/bin/elasticsearch

(以下、web2のstdout。 ※web2 → web1 → web3 の順に起動されている)

[2015-09-01 05:27:23,269][INFO ][node                     ] [William Stryker] version[1.7.1], pid[2409], build[b88f43f/2015-07-29T09:54:16Z]
[2015-09-01 05:27:23,271][INFO ][node                     ] [William Stryker] initializing ...
[2015-09-01 05:27:23,536][INFO ][plugins                  ] [William Stryker] loaded [], sites []
[2015-09-01 05:27:23,667][INFO ][env                      ] [William Stryker] using [1] data paths, mounts [[/ (/dev/sda1)]], net usable_space [6.3gb], net total_space [7.8gb], types [ext4]
[2015-09-01 05:27:30,824][INFO ][node                     ] [William Stryker] initialized
[2015-09-01 05:27:30,830][INFO ][node                     ] [William Stryker] starting ...
[2015-09-01 05:27:31,134][INFO ][transport                ] [William Stryker] bound_address {inet[/192.168.33.11:9300]}, publish_address {inet[/192.168.33.11:9300]}
[2015-09-01 05:27:31,241][INFO ][discovery                ] [William Stryker] mycluster/m-MMbTLfQaK0lrPUbs-iGw
[2015-09-01 05:27:35,078][INFO ][cluster.service          ] [William Stryker] new_master [William Stryker][m-MMbTLfQaK0lrPUbs-iGw][web2][inet[/192.168.33.11:9300]], reason: zen-disco-join (elected_as_master)
[2015-09-01 05:27:35,125][INFO ][http                     ] [William Stryker] bound_address {inet[/192.168.33.11:9200]}, publish_address {inet[/192.168.33.11:9200]}
[2015-09-01 05:27:35,126][INFO ][node                     ] [William Stryker] started
[2015-09-01 05:27:35,299][INFO ][gateway                  ] [William Stryker] recovered [2] indices into cluster_state
[2015-09-01 05:28:01,266][INFO ][cluster.service          ] [William Stryker] added {[Styx and Stone][NC8yxTlOSfyiJ5vcEtKttA][web1][inet[/192.168.33.10:9300]],}, reason: zen-disco-receive(join from node[[Styx and Stone][NC8yxTlOSfyiJ5vcEtKttA][web1][inet[/192.168.33.10:9300]]])
[2015-09-01 05:28:27,478][INFO ][cluster.service          ] [William Stryker] added {[Tex Dawson][KpOh0tfRRfSItoKUw0XImQ][vagrant-centos65.vagrantup.com][inet[/192.168.33.12:9300]],}, reason: zen-disco-receive(join from node[[Tex Dawson][KpOh0tfRRfSItoKUw0XImQ][vagrant-centos65.vagrantup.com][inet[/192.168.33.12:9300]]])

動作確認

3台それぞれで、以下を確認。

$ curl http://192.168.33.10:9200    #web1〜web3それぞれ
{
  "status" : 200,
  "name" : "William Stryker",
  "cluster_name" : "mycluster",
  "version" : {
    "number" : "1.7.1",
    "build_hash" : "b88f43fc40b0bcd7f173a1f9ee2e97816de80b19",
    "build_timestamp" : "2015-07-29T09:54:16Z",
    "build_snapshot" : false,
    "lucene_version" : "4.10.4"
  },
  "tagline" : "You Know, for Search"
}

headプラグインを追加するとビジュアルで確認しやすい(インストールは1台でも良い)。

$ ./elasticsearch-1.7.1/bin/plugin -install mobz/elasticsearch-head

以下のURLで各ノードを確認できる。

http://192.168.33.11:9200/_plugin/head/

f:id:catnapper_mar:20160321232954p:plain

3台の場合は、同じデータが2箇所に配置されていることが分かる。

ノード障害時の挙動確認

障害で1ノードがダウンしてしまった場合のクラスタの挙動を確認する。

web1をシャットダウンすると、web2のstdoutに以下のように表示される。

[2015-09-01 06:21:09,425][INFO ][cluster.service          ] [William Stryker] removed {[Styx and Stone][NC8yxTlOSfyiJ5vcEtKttA][web1][inet[/192.168.33.10:9300]],}, reason: zen-disco-node_left([Styx and Stone][NC8yxTlOSfyiJ5vcEtKttA][web1][inet[/192.168.33.10:9300]])
[2015-09-01 06:21:09,541][INFO ][cluster.routing          ] [William Stryker] delaying allocation for [7] unassigned shards, next check in [59.8s]
[2015-09-01 06:22:09,678][INFO ][cluster.routing          ] [William Stryker] delaying allocation for [0] unassigned shards, next check in [0s]
[2015-09-01 06:22:10,101][INFO ][cluster.routing          ] [William Stryker] delaying allocation for [0] unassigned shards, next check in [0s]

どうなったか、再度ブラウザから確認。 f:id:catnapper_mar:20160321233401p:plain

2台に寄せられ、データが均等配分されることが確認出来る。

以上から、(4台以上の場合の検証も必要だが)使えるDISK容量はN-1台分と理解して良さそう。 DISK容量もスケールアウト可能と思われる。

参考

Elasticsearch のクラスタを構築する - Carpe Diem

Cluster機能を使う – AWSで始めるElasticSearch(2) | Developers.IO