いんふら女子めも

YEEE~('ω')ノ★ 現役インフラエンジニア!

Elasticsearchが立ち上がらないときの対処法

どんなエラーが発生したのか?

Elasticsearchを起動させようとすると失敗する。

$ sudo systemctl start elasticsearch
● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Sun 2019-06-09 06:41:29 UTC; 6min ago
     Docs: http://www.elastic.co
  Process: 5538 ExecStart=/usr/share/elasticsearch/bin/elasticsearch -p ${PID_DIR}/elasticsearch.pid --quiet -Edefault.path.logs=${LOG_DIR} -Edefault.path.data=${DATA_DIR} -Edefault.path.conf=${CONF_DIR} (code=exited, status=1/FAILURE)
  Process: 5537 ExecStartPre=/usr/share/elasticsearch/bin/elasticsearch-systemd-pre-exec (code=exited, status=0/SUCCESS)
 Main PID: 5538 (code=exited, status=1/FAILURE)

環境

  • Elasticsearch5.6
  • vagrant2.2.3
  • CentOS7.6

対処法

Elasticsearchのステータスの詳細を表示

上記の情報だけではよく分からないので、どこで失敗しているか詳細を見てみます。

$sudo systemctl status elasticsearch -l
[中略] 
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000000085330000, 2060255232, 0) failed; error='Cannot allocate memory' (errno=12)
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: #
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # There is insufficient memory for the Java Runtime Environment to continue.
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # Native memory allocation (mmap) failed to map 2060255232 bytes for committing reserved memory.
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # An error report file with more information is saved as:
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # /tmp/hs_err_pid5538.log
Jun 09 06:41:29 localhost.localdomain systemd[1]: elasticsearch.service: main process exited, code=exited, status=1/FAILURE
Jun 09 06:41:29 localhost.localdomain systemd[1]: Unit elasticsearch.service entered failed state.
Jun 09 06:41:29 localhost.localdomain systemd[1]: elasticsearch.service failed.

Javaを起動するために必要なメモリが不十分であることが判明。

Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000000085330000, 2060255232, 0) failed; error='Cannot allocate memory' (errno=12)
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: #
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # There is insufficient memory for the Java Runtime Environment to continue.

今回使用しているVMの搭載メモリは4GBでElasticsearchには2GB割り当てるように設定していたのですが、そんなに空きがなかったことが起動に失敗する原因でした。

設定ファイルの修正

Elasticsearchの割り当てメモリの変更(ヒープサイズ)は、"/etc/elasticesearch/jvm.options"で行います。
XmsとXmxの値を2GBから1GBに書き換えました。

$sudo vi /etc/elasticesearch/jvm.options
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space

-Xms1g
-Xmx1g

公式ドキュメントにも記載がありますが、Xms(最小ヒープサイズ)とXmx(最大ヒープサイズ)は等しい値にする必要があります。詳しくは以下を参照してください。
www.elastic.co

Elasticsearchを再起動させる

設定ができたら、Elasticsearchを再起動させてステータスを確認します。ステータスがactiveになっていたらOKです。

$sudo systemctl restart elasticsearch
$systemctl status elasticsearch
● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2019-06-09 06:53:47 UTC; 13s ago
     Docs: http://www.elastic.co
  Process: 6279 ExecStartPre=/usr/share/elasticsearch/bin/elasticsearch-systemd-pre-exec (code=exited, status=0/SUCCESS)
 Main PID: 6280 (java)
   CGroup: /system.slice/elasticsearch.service
           mq6280 /bin/java -Xms1g -Xmx1g -XX:+UseConcMarkSweepGC -XX:CMSInit...

Jun 09 06:53:47 localhost.localdomain systemd[1]: Starting Elasticsearch...
Jun 09 06:53:47 localhost.localdomain systemd[1]: Started Elasticsearch.
Jun 09 06:53:47 localhost.localdomain elasticsearch[6280]: OpenJDK 64-Bit Ser...
Hint: Some lines were ellipsized, use -l to show in full. 

動作確認

これでElasticsearchは正常に使えるはずなので、curlコマンドを使ってElasticsearchからレスポンス返ってくるか確認します。

$ curl http://0.0.0.0:9200
{
  "name" : "WTDjnDZ",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "f_ZGcQzRQGyhlqOA8XLVOA",
  "version" : {
    "number" : "5.6.16",
    "build_hash" : "3a740d1",
    "build_date" : "2019-03-13T15:33:36.565Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.1"
  },
  "tagline" : "You Know, for Search"

今回は、elasticsearchのymlファイルにて"network.host"を"0.0.0.0"に設定しているので、curl先は0.0.0.0にしています。ローカルホストを指定している場合は、"curl localhost:9200"でレスポンス返ってくるはずです。

curlを実行して以下のようなコネクションエラーが発生した場合は、"/etc/elasticsearch/elasticsearch.yml"ファイルのnetwork.hostを確認してください。

curl: (7) Failed connect to localhost:9200; Connection refused

以上です。

Zabbixエージェントによる監視が有効にならないときの対処法

エラー内容

ZabbixのWebインターフェース画面を確認すると、登録したホストに以下のエラーが表示。

Get value from agent failed: cannot connect to [[IP_address]:10050]: [4] Interrupted system call

環境

  • Zabbix server3.0.3
  • Zabbix agent3.0.3
  • CentOS7

対処法

1. SELinuxの確認

Zabbixエージェントの入ったホスト上でSELinuxが有効か無効か確認する

#現在の状態確認
getenforce
#有効だったら無効にする
sudo setenforce 0

2. ファイヤーウォールの確認

現在のファイヤーウォールの状態を確認し、Zabbixが登録されていない場合は追加する。

#ファイヤーウォールの状態確認
systemctl status firewalld
#ファイヤーウォール設定確認
firewall-cmd --list-all 
#Zabbixを追加する(サービスかポートか片方で大丈夫なはず)
#サービス追加
firewall-cmd --add-service=zabbix --zone=public --permanent
#ポート追加
firewall-cmd --add-port=10050/tcp --zone=public --permanent
#設定をリロードする
firewall-cmd --reload

リロードして"success"と表示されればOK!
"--permanent"を付けないとリロードしたら設定が無効になるので注意。

3. ZabbixのWebインターフェース画面を確認する

画面を更新すれば、赤くなっていたエラーメッセージが消えていると思います。

ElasticsearchにjsonをインポートしてGrafanaで可視化したい

何をやったのか

今回は、コマンドを打って取得した情報をjson形式に変換してElasticsearchにデータを流し込みます。Elasticsearchにデータを格納するときは、Metricbeatを通常使っているのですが、Metricbeatでは取得できない情報もElasticsearchに投入しGrafanaで可視化したかったので、そのためのシェルスクリプトを作りました。

コマンドで取得するデータはCephノードの情報です。
処理の流れとしては、以下の通りです。

  1. コマンドでCeph情報を取る
  2. タイムスタンプをデータに付ける
  3. データにインデックス情報を付与してElasticsearchに送る
  4. Elasticsearchにデータ登録されているか確認する
  5. Grafana上に登録する

Cephのコマンドは-fオプションで出力内容をjson等に変換できるので便利。-fの出力形式はjson, json-pretty, xml, xml-pretty, planeから選択することが出来ます。(※'pretty'がついてるのは見やすいように出力してくれる形式のこと。)
例えばこんな感じで。

ceph osd tree -f json

Cephのコマンドはどんなものがあるかは下記のサイトを参照すると良いです。どんなオプションがあるかは、ceph --helpでチェック。
www.lisa.jp

環境

  • Ceph12.2.5
  • Elasticsearch6.6.1
  • Grafana5.4

処理内容

githubスクリプト挙げてます('ω')ノ
定期的にデータ取得する場合はcronに登録しとけばOK.
github.com

Elasticsearchに送るjsonデータは、IndexとTypeを最初に指定する必要があります。Type_IDは省略可能です。
形式は以下の通りです。

#頭にインデックスを指定する
{ "index" : { "_index" : "[index_name], "_type" : "[type_name], "_id" : "[id]" } }
#続けてインポートするデータを書く
{"field_1":"value_1","field_2":"value_2"}

注意したいのは、1つのjsonデータにつきインデックス、タイプを指定する必要があるので下記のようなデータをインポートすることはできません。

#NG例
{ "index" : { "_index" : "[index_name], "_type" : "[type_name], "_id" : "[id]" } }
{"field_1":"value_1","field_2":"value_2"}
{"field_3":"value_3","field_4":"value_4"}

連続してデータをインポートするならば、下記のようにします。

#Ok例
{ "index" : { "_index" : "[index_name], "_type" : "[type_name], "_id" : "[id]" } }
{"field_1":"value_1","field_2":"value_2"}

{ "index" : { "_index" : "[index_name], "_type" : "[type_name], "_id" : "[id]" } }
{"field_3":"value_3","field_4":"value_4"}

つまづいたところ

タイムスタンプの位置

タイムスタンプの位置が悪くてGrafanaのデータソース登録の時にうまくいきませんでした。Grafanaのデータソース登録しようとすると、「No date field named @timestamp」というメッセージが。。。

何が悪かったかと言うと、cephフィールドの中にタイムスタンプを入れていたため認識されませんでした。なのでタイムスタンプをcephフィールドの外に出してデータソースの登録をすると成功!

#修正前
{"ceph":["@timestamp":"'${date}'",'${ceph_node_info}']}
#修正後
{"@timestamp":"'${date}'","ceph":['${ceph_node_info}']}

Grafanaのデータソースの登録方法は下記を見ると良いです。
私の大体下記の記事と同じように設定しています。
designetwork.daichi703n.com
注意点は、URLの後ろにポート指定すること(http://[elasticsearch_ip_address]:9200)、インデックス名やタイムフィールド名を間違えないことですかね?インデックス名は、私の場合YYYY.MM.DDの形式だと認識されなかったので、[index_name]-*に変えて登録すればデータソースが正常に追加されました。

括弧の位置とか数とか

jsonのフォーマットがよくわかってなくて[]で括るのか{}で括るのか悩みました。jsonのデータ構造が分かりにくかったら、jqコマンド等使うと見やすくなるので、間違いに気が付くと思います。
こんな感じで。

ceph osd tree -f json | jq .

大体エラーメッセージに何が悪いかかかれているので何回かトライ&エラーしてみるとよいです。

GrafanaのVariable機能を使ってみよう【Zabbix編】

以前の記事では、Zabbixの監視画面をGrafanaで作成する方法についてを書きました。
akng-engineer.hatenablog.com

今回は、監視するサーバーや監視アイテムが増えたときに有用な機能であるVariablesについて紹介します。Variables機能を使うことでGrafanaでの監視画面の作成がかなり楽になるので、知らない方は是非使ってみてほしいです!

Variables(変数)とは

公式ドキュメントには下記のような説明がされています。

変数は値のプレースホルダである。メトリッククエリやパネルタイトルに変数を使うことができる。ダッシュボートの上部にあるドロップダウンで値を変更するとパネルのメトリッククエリに新しい値が反映される。

つまり、変数を使うことで同じような画面やパネルを手動で作る必要がなくなる便利な機能です。

GrafanaのVariables機能について詳しく知りたい方は、公式ドキュメントを参照してください。
grafana.com

環境

今回使っているバージョンは以下の通りです。

  • Zabbix4.0
  • Grafana6.16

変数を登録するよ

Grafanaにログインし対象のダッシュボードを開いたら、画面右上の「Dashboard Settings」をクリック
f:id:akngo22:20190512155620j:plain
続いてVariables⇒Add Variableをクリック
f:id:akngo22:20190512160759j:plain
変数登録に必要な事項を入力し、Addをクリック
f:id:akngo22:20190512160856j:plain
Name:変数名
Data sourse:変数に登録するデータソース(ここではZabbixの情報を使うのでZabbix)
Refresh:変数を更新した場合の反映方法(今回はダッシュボードをリロードしたときを選択)
Query:変数を登録するためのクエリはここに書く
Sort:変数のソート方法(アルファベット順とか若番か老番順かなど)
Preview of Values:変数に格納された値のプレビューが見れる

クエリはどう書くの

クエリの書き方ですが、今回は「Virtual Machines」というホストグループに属している全ホストを変数扱いにしたいので、クエリは「Virtual Machines.*」と入力しました。
Zabbixのデータは、ホストグループ⇒ホスト⇒アプリケーション⇒アイテムというデータ構成になっているので、「⇒」の部分は「.(ドット)」でつないでください。
例を挙げると、

  • 全ホストグループを指定⇒クエリ:「*」
  • あるホストグループの全ホストを指定⇒クエリ:「hostgroup_name.*」
  • あるホストグループのあるホストの全アプリケーションを指定⇒クエリ:「hostgroup_name.host_name.*」

こんな感じで変数登録することができます。

Regrex(正規表現)を使えば、ある条件にマッチするホストグループ名やホスト名を指定することもできます。
Preview of Valuesを見れば、きちんと変数に値が格納されているか登録前にわかりますよ!

パネルに変数設定をするよ

変数を登録し、ダッシュボードに戻ると画面上部にドロップダウンリストが表示されていることを確認します。
パネルに変数設定するには、パネルの編集画面を開きます。
f:id:akngo22:20190512161902j:plain
今回メトリッククエリ、タイトル名に変数を使うので、変数設定したい部分に変数名を入力しましょう。
変数名を使うときには"$変数名"と入力します。

設定が完了したら、ドロップダウンリストでサーバー名を選択します。
f:id:akngo22:20190512163720j:plain
f:id:akngo22:20190513215621j:plain
リストで選択したホストの情報がきちんと反映されているのが確認できればOKです。

まとめ

変数を使うと同じような画面を大量に作る必要もなくなるので、かなり作業が楽になると思います。
また、Zabbixのホストグループに新しくホストが追加されたとしても、自動的にGrafana側へ反映されるのでGrafanaの設定は何もしなくていいので便利ですね。さらに、変数は同じような画面を複数作らなくても良いだけではなく、同じようなパネルが必要な場合に一括で作成することもできます。それはまた別に書こうかな。

以上です。