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/
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]
どうなったか、再度ブラウザから確認。
2台に寄せられ、データが均等配分されることが確認出来る。
以上から、(4台以上の場合の検証も必要だが)使えるDISK容量はN-1台分と理解して良さそう。 DISK容量もスケールアウト可能と思われる。
参考
crontab内のコマンドラインでの%(パーセント)の扱い
crontabそのものをcronで毎日日付つきでバックアップしようと思って仕込んだら全然うまく行かなかった時に調べて見つけた、神の啓示。
dateコマンド と crontab の コマンドライン中の %(パーセント)記号 - keigoiの日記
すっごくスッキリしたことは覚えてる。
ソースコンパイルしたPHPに後からpdo_pgsqlをインストールする
PHPからPostgresqlに繋ぎたいので、ソースコンパイルしたPHP環境(今回の例では5.4.7)に、pdo_pgsqlをインストールして下さいと頼まれた。 PHP環境の構築や拡張モジュールなどには正直なところ全く詳しくなかったので、 どうやるのか、あまりに見当つかないものの、調べてやってみることに。
と思ってしばらく探したら、以下の記事がほとんどドンピシャ大当たり。ありがとうございます。
PHPをコンパイルした環境に、後からpgsql.soなどのモジュールを追加する方法 - Web系エンジニアbcoのメモ帳
以下、自分の環境でやった手順をメモる。
前提となるphp環境について
- php 5.4.7
- phpのインストール先:/opt/php
- /usr/local/bin/php は、/opt/php/bin/php へのSymlinkとしている
- コンパイルしたソースの置き場所:/usr/local/src/php-5.4.7
作業手順
現環境のPHPをコンパイルしたソースの置き場所にある、extentionディレクトリへ行く
# cd /usr/local/src/php-5.4.7/ext/pdo_pgsql
phpのパス確認
拡張モジュールは今使っているphpのパス上にあるツールを使って生成するため、phpのパス(インストールパス)を確認する。
# ls -l /usr/local/bin/php lrwxrwxrwx 1 root root 16 5月 13 16:21 2014 /usr/local/bin/php -> /opt/php/bin/php
phpizeでconfigureファイルを作成
phpizeとは?
拡張モジュールをビルドする低レベルなビルドツール。autoconfやautomake m4等のビルドツールが別途必要になる。これを使用することにより、PHPをソースから再コンパイルすることなく拡張モジュールをビルドすることができる。
引用:phpizeとは - PHP用語 Weblio辞書
インストールパス上のphpizeを実行すると、configure実行ファイルが出来る。
# /opt/php/bin/phpize
configureを実行
ここでは、--with-pdo-pgsql を入れることと、--with-php-config で、現在のphpパス上にあるphp-config実行ファイルを指定する必要がある
# ./configure --with-pdo-pgsql --with-php-config=/opt/php/bin/php-config
make実行
# make # make test # make install Installing shared extensions: /opt/php/lib/php/extensions/no-debug-non-zts-20100525/
インストール完了。これで、拡張ディレクトリにpdo_pgsql.soファイルが出来る。
php.iniファイルを編集
/etc/php.ini に、; extensionsのディレクトリと対象のモジュールの名前を記述する。
; 拡張モジュールの置き場 extension_dir = /opt/php/lib/php/extensions/no-debug-non-zts-20100525/ ; 利用するextension extension = pdo_pgsql.so
apacheを再起動
# /etc/init.d/httpd restart
1時間ごとにlogrotateする方法
ログファイル管理はlogrotateを使って週1回または1日1回ローテートするように仕掛けたらひとまずOK。だいたいのケースでは。
が、普通に設定したら最短で1日1回しかローテートできないので、ログファイルが数百MB、数GBと大きくなる場合にはOKとは言えない。 できれば1時間に1回ローテートできないものか。
単純な発想だが、1時間に1回、cronで強制的にローテート実行させることで可能である。 以下、logrotateの基本的な設定方法の確認の意味も込めて、手順をメモっておく。
1.アーカイブ先(olddir)作成
アーカイブ先を分けるのは必須ではないが、分けておくとログディレクトリ直下には常に最新のログのみが書き出されているのですっきりする。
# mkdir -p /var/log/nginx/archives
2.logrotate設定
毎時ローテートさせたいログファイル専用の設定ファイルを用意する。
# mkdir -p /etc/logrotate.hourly # vi /etc/logrotate.hourly/nginx
気をつけるのはローテートさせる回数とファイル名(日付・タイムスタンプ付にする)。 あとは好みに応じて設定。
/var/log/nginx/huge_access.log { create 0644 nginx nginx daily # cronで実行するため、実質的に意味なし rotate 720 # 1ヶ月保持出来るローテート回数(24回/日 × 30日) missingok notifempty compress dateext # ファイル名に日付を付ける dateformat -%Y%m%d-%s # 毎時生成されるためタイムスタンプを付ける olddir /var/log/nginx/archives sharedscripts postrotate [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid` endscript }
※dateext, dateformatの "%s" は、logrotateのバージョンによって使えない場合もある。
3. 設定テスト
-d デバッグモード(dry-runされて、ローテートされない)で実行し、設定エラーが出ないか確認
# logrotate -dv /etc/logrotate.hourly/nginx
4. 初回実行
新規にローテート対象となったファイルは、初回実行時に /var/lib/logrotate.status にエントリ追加されるだけでローテートされないので、cronでスケジュール実行される前に1回手動で実行する
# logrotate -v /etc/logrotate.d/logrotate.hourly/nginx
※1回目は、いずれのログも /var/lib/logrotate.status にエントリがない、または既に毎時ローテートされているファイル のどちらかのため、 dailyローテートのテストとしては、ローテート対象外(log does not need rotating)という結果になる。
5.ローテート履歴(logrotate.status) 確認
対象のログが、logrotate.status エントリに本日日付で入っていることを確認。
# cat /var/lib/logrotate.status logrotate state -- version 2 ・ ・ (略) "/var/log/nginx/huge_access.log" 2015-8-29 #←これ
6. cron設定
5までで、毎日3:00以降の任意のタイミング(cron.dailyの実行タイミング)でローテートが実施されるようにはなった。 ただ、これだけでは日次ローテートしかされないため、cronで毎時実行させる。
# logrotate -f で強制ローテート実行 0 * * * * /usr/sbin/logrotate -f -s /var/lib/logrotate.status /etc/logrotate.hourly/nginx
これで設定完了。
・・・と、これを書いている最中、既に3.8.5からhourly設定可能になっているという情報を見かけ。今度使ってみよ。
https://fedorahosted.org/logrotate/browser/tags/r3-8-8/CHANGES
参考
タイトルとか決めてないけどこのままでもいいかもしんない: logrotateでnginxのログを1時間ごとにローテートをする
Gitでリモートブランチをローカルにチェックアウトする
今のところ頻繁にやる作業ではないため、忘れがち。 なんだっけ・・・とググってたらドンピシャだったので備忘録代わりに貼らせて頂きます。