あきろぐ

いろいろめもするよ

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

処理内容

実際に作成したスクリプトはこちら。

#!/bin/bash
#get ceph info
ceph_node_info=$(ceph node ls all -f json)
#timestamp for elasticsearch
date=`echo $(date "+%Y-%m-%dT%H:%M:%S.%3NZ")`
#date for index
date2=`echo $(date "+%Y-%m-%d-%H:%M")`

#setting of import data
index= '{"index":{"_index":"osd_'${date2}'","_type":"host_mapping"}}'
echo $index > result.json
echo '{"@timestamp":"'${date}'","ceph":['${ceph_node_info}']}' >> result.json

#send ceph info to elasticsearch
curl -s -H "Content_Type:application/json" -XPOST 'http://xxx.xx.xx.xx:9200/_bulk' --data-binary@result.json

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 .

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