[Elasticsearch] BackupとRestore

Elasticsearchノードのお引越し

先日、KubernetesなインフラにSNS機能を移転したこともあり、残すはElasticsearchサーバだけになりました。分散SNSソフトで使用するElasticsearchはこれまでに取り込んだメッセージなどが蓄積されており、データベースサイズとしてさほど大きくはないのですが、SNS上で使用する検索機能で必要となります。

今までElasticsearchとしての論理バックアップ・論理リストアはやったことがないので試しました。

コマンドライン等書かれている内容は、当方の環境に特化した形のままで記載しています。実際の環境でお試しの際は、ぜひ変動個所については読み替えてくださいますようお願いいたします。

全体的な流れ

リポジトリの作成(旧サーバ・新サーバ共に)
バックアップリポジトリを作成します。リポジトリ作成に当たり、elasticsearch.yml上で「path.repo」というパラメータでリポジトリ領域のディレクトリを指定する必要があるようです。
リポジトリを設定ファイルで指定したのち、一旦Elasticsearchを再起動します。
バックアップの取得(旧サーバ上)
curlコマンドを使用して、バックアップを取得します。リポジトリで指定した領域に対してバックアップデータが出力されます。
ファイルの転送(旧サーバ→新サーバ)
新しいサーバにリポジトリのディレクトリごとデータを転送します。今回はrsyncを使って転送しています。scpとかFTPでもよいのではないかなと思います。
データリストアの実行(新サーバ上)
curlコマンドを使用して、データリストアを行います。バックアップしたインデックスがリストアされ、読み出せるようになります。

リポジトリの作成

リポジトリの作成は以下のようなことを実行します。

curl -H "Content-Type: application/json" -XPUT 'http://localhost:9200/_snapshot/backup1' -d '{
  "type": "fs",
  "settings": {
    "location" : "/var/lib/elasticsearch/backups/backup1",
    "compress": true
  }
}'

うまくいけば以下のような結果になります。

{"acknowledged":true}

失敗した場合、こんな風になります。
以下の場合だと、ちゃんとpath.repoを定義してないことに起因するエラーが出力されてます。

{
  "error":{
    "root_cause":[
      {
        "type":"repository_exception",
        "reason":"[backup1] location [/usr/share/elasticsearch/data/backups/backup1] doesn't match any of the locations specified by path.repo"
      }
    ],
    "type":"repository_exception",
    "reason":"[backup1] failed to create repository",
    "caused_by":{
      "type":"repository_exception",
      "reason":"[backup1] location [/usr/share/elasticsearch/data/backups/backup1] doesn't match any of the locations specified by path.repo"
    }
  }
}

k3sなど、Kubernetes環境を使用する場合は、Elasticsearchを動かすYAML上で「env」配下に以下のように記述をするとよいと思います。

          env:
            - name: cluster.name
              value: misskey-cluster
            - name: bootstrap.memory_lock
              value: "false"
            - name: bootstrap.system_call_filter
              value: "false"
                 :
                中略
                 :
            - name: path.repo
              value: "/usr/share/elasticsearch/data/backups/backup1"

バックアップ処理

バックアップ処理を以下のようにcurlコマンドを実行して出力させます。どんな処理もそうなのですが、ES6.x以降は明示的にコンテントヘッダの入力が必要ですので注意しませう。

curl -H "Content-Type: application/json" -XPUT 'http://localhost:9200/_snapshot/backup1/backup-2019.11.04?wait_for_completion=true' -d '{
"indices": "*",
"ignore_unavailable": true,
"include_global_state": false
}'

応答として、整形されてないJSONが返ってきますが、以下のコマンド実行で結果をもう少し見やすくできたりします。

curl -H "Content-Type: application/json" -XGET 'http://localhost:9200/_snapshot/backup1/backup-2019.11.04?pretty'

{
  "snapshots" : [
    {
      "snapshot" : "backup-2019.11.04",
      "uuid" : "THnyIfBZTc60HxdUvahyDg",
      "version_id" : 6080199,
      "version" : "6.8.1",
      "indices" : [
        "misskey_note"
      ],
      "include_global_state" : false,
      "state" : "SUCCESS",
      "start_time" : "2019-11-04T04:37:07.880Z",
      "start_time_in_millis" : 1572842227880,
      "end_time" : "2019-11-04T04:37:16.840Z",
      "end_time_in_millis" : 1572842236840,
      "duration_in_millis" : 8960,
      "failures" : [ ],
      "shards" : {
        "total" : 5,
        "failed" : 0,
        "successful" : 5
      }
    }
  ]
}

ちなみにバックアップデータはこんな感じでした。

30M     ./backups/backup1/indices/kdCdZAVQT5uI2bq6pHz5rA/1
30M     ./backups/backup1/indices/kdCdZAVQT5uI2bq6pHz5rA/3
30M     ./backups/backup1/indices/kdCdZAVQT5uI2bq6pHz5rA/4
30M     ./backups/backup1/indices/kdCdZAVQT5uI2bq6pHz5rA/2
30M     ./backups/backup1/indices/kdCdZAVQT5uI2bq6pHz5rA/0
149M    ./backups/backup1/indices/kdCdZAVQT5uI2bq6pHz5rA
149M    ./backups/backup1/indices
149M    ./backups/backup1
149M    ./backups
300M    .

リストア処理

リストア処理は以下の通りとなります。URLにおいて_snapshot以降はリポジトリ名/保存バックアップセット名の順で打ち込んでいく感じになります。

curl -H "Content-Type: application/json" -XPOST 'http://msk-elsearch.default.svc.cluster.local:9200/_snapshot/backup1/backup-2019.11.04/_restore' -d '{
"indices": "*",
"ignore_unavailable": true,
"include_global_state": false
}'

どーしても覚えられないREST API

私自身Elasticsearchは面白そうだと思って使ってるんですが、なかなかRESTful APIというのがわからないですね。それなりに努力してはいるんですが・・・・いやはやむずかしいっす。

何度も何度も打ち込んで覚えてこうして整理していくしかないなーとは感じています。