Cuturnの適当日記

徒然なるままに適当に駄文を吐き出しております

Reindex Elasticsearch Index for Kibana Using Logstash

Fluentd+Elasticsearch+Kibanaの組み合わせで利用していて、後からどうしてもマッピングを変えないとグラフが作れない!というようなことがあるとき、インデクスを更新する方法を記載する。

まず、利用したのはLogstash。 Elasticsearch関連の処理ソフトでruby on railsで動くtireとか色々とあったのだがLogstashが最も楽だった。 バイナリ解凍して突っ込んで動かすだけなので、アレがないコレがないが無くてよい。

前提

KibanaではLogstash-*を収集するインデクスの対象としている。 したがって、Logstash-2015.08.29でも収集するし、Logstash-2015.08.29-2でも収集する。 Reindexとは書いたが同じインデクス名を使う必要は無い。 なお、本当に同じ名前にしたい場合はエイリアスを使ったりインデクスの名前を変更する必要があるが、 正直インデクスの名前を上手く不具合無く変更する方法がわからず…。

Logstashのインストール

適当にLogstash公式からtar.gzをダウンロードする。

Download Logstash Free • Get Started Now | Elastic

デーモンとして使う気は一切ないので、Linuxサーバ上の適当なディレクトリに解凍すればインストールOK。

$ tar zxvf logstash-1.5.4.tar.gz -C /usr/local/share/

Logstashコンフィグ作成

Logstashで使うコンフィグ logstash.cfgを作成する。ファイル名はなんでもいい。 input->elasticsearch->indexには作り直したいインデクス名を、 output->elasticsearch->indexには作り直し後のインデクス名を入れる。

input {
  elasticsearch {
    hosts => ["localhost"]
    index => "logstash-2015.08.16"
    docinfo => true
  }
}

output {
  elasticsearch {
    host => "localhost"
    protocol => "http"
    manage_template => false
    index => "logstash-2015.08.16-2"
    workers => 5
    document_type => "%{[\@metadata][_type]}"
  }
}

再作成(というかコピー)を実行する

以下のコマンドで実行できる。

$ /usr/local/share/logstash-1.5.4/bin/logstash -f logstash.cfg

これで新しいindexであるlogstash-2015.08.16-2が作成される。あとは元のインデクスを削除すればOK。

$ curl -XDELETE "http://localhost:9200/logstash-2015.08.16"

スクリプト

とりあえずいくつかたまってるインデクスを再作成したかったので、全くスマートじゃないスクリプトを作った。 基本全部日付のLogstashだったので全部配列にいれて、それ全部に対してぶん回す。 そんな感じでコンフィグを生成してはインデクスコピー、を繰り返す。

#!/bin/perl
my @date = ('2015.08.16','2015.08.17','2015.08.18','2015.08.19','2015.08.20','2015.08.21','2015.08.22','2015.08.23','2015.08.24','2015.08.25','2015.08.26','2015.08.27','2015.08.28','2015.08.29','2015.08.30','2015.08.31','2015.09.01','2015.09.02','2015.09.03','2015.09.04','2015.09.05','2015.09.06','2015.09.07','2015.09.08','2015.09.09','2015.09.10','2015.09.11','2015.09.12');

foreach $tmpdate (@date) {
      $confstr = <<"EOS";
input {
  elasticsearch {
    hosts => ["localhost"]
    index => "logstash-${tmpdate}"
    docinfo => true
  }
}

output {
  elasticsearch {
    host => "localhost"
    protocol => "http"
    manage_template => false
    index => "logstash-${tmpdate}-2"
    workers => 5
    document_type => "%{[\@metadata][_type]}"
  }
}
EOS

      print "Copying logstash-${tmpdate} to logstash-${tmpdate}  ...\n";
      open(CONFIG,"> /tmp/tmp.cfg");
      print CONFIG $confstr;
      close(CONFIG);
      system("/usr/local/share/logstash/bin/logstash -f /tmp/tmp.cfg");
      
      print "DELETE INDEX logstash-${tmpdate}"
      system("curl -XDELETE 'http://localhost:9200/logstash-${tmpdate}'");
}

なお、スクリプト化するときの設定ファイルの注意点としては、 document_typeのところで@マークをエスケープするのを忘れるとうまくいかないので注意。 なお、@metadataはElasticsearchに入れられるデータ1件1件の、index,type,_idを持つ。