RDBと同じようにデータのバックアップとリストアをやってみました。
次のdocker-compose.ymlを使って環境構築しています。
version: '3.9' services: es01: image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0 ports: - 9200:9200 - 9300:9300 environment: - discovery.type=single-node - action.destructive_requires_name=true - xpack.security.enabled=false - path.repo=/usr/share/elasticsearch/backup networks: - elastic volumes: - backup:/usr/share/elasticsearch/backup deploy: resources: limits: memory: 2G ki01: image: docker.elastic.co/kibana/kibana:8.0.0 environment: ELASTICSEARCH_HOSTS: "http://es01:9200" ports: - 5601:5601 networks: - elastic deploy: resources: limits: memory: 2G volumes: backup: driver: local networks: elastic: driver: bridge
elasticsearchが8.0.0になりましたが、デフォルトでセキュリティの機能が有効化されているので、OFFにしています。ONにしてあると色々と設定してあげないとkibanaが接続できませんでした。ローカルの開発以外では必ずONにするべきだとは思います。
バックアップ
バックアップ先に指定できるものはいくつか種類があるようです。ここでは共有ファイルシステムでやってみます。
https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshots-filesystem-repository.html
dockerで動かしているので、volumeを作成/アタッチしバックアップ先のディレクトリとして利用します。
elasticsearchのコンテナの環境変数 path.repo
に、バックアップ先のディレクトリとしてこのvolumeを指定します。この設定がないと、バックアップ先として設定できないので注意が必要です。
次のリクエストでリポジトリを作り、バックアップ先として登録します。
PUT _snapshot/repository_1 <-- ① { "type": "fs", "settings": { "location": "/usr/share/elasticsearch/backup", <-- ② "compress": true } }
① repository_1 はリポジトリの名前なので、自由に決められます。
② バックアップ先に利用するパスを指定します。path.repo に指定がないディレクトリは使えません。
バックアップする対象を作成したいので、一件ドキュメントを保存します。
PUT demo-index POST demo-index/_doc { "name": "bookstore" }
次のリクエストでスナップショットを作成できます。
PUT _snapshot/repository_1/snapshot_1?wait_for_completion=true { "indices": "demo-index" <-- ① }
① スナップショットに含めるインデックスを指定します。 *
にすると、全インデックスのスナップショットを作成できます。
レスポンスは次の通りです。
{ "snapshot" : { "snapshot" : "snapshot_1", "uuid" : "R-S8paawT0mUdt2f3UjvPg", "repository" : "repository_1", "version_id" : 8000099, "version" : "8.0.0", "indices" : [ <-- ① ".kibana_8.0.0_001", "demo-index", ".apm-custom-link", ".fleet-policies-7", ".kibana_task_manager_8.0.0_001", ".apm-agent-configuration", ".geoip_databases" ], "data_streams" : [ ], "include_global_state" : true, "state" : "SUCCESS", "start_time" : "2022-02-20T11:33:20.796Z", "start_time_in_millis" : 1645356800796, "end_time" : "2022-02-20T11:33:21.997Z", "end_time_in_millis" : 1645356801997, "duration_in_millis" : 1201, "failures" : [ ], "shards" : { "total" : 7, "failed" : 0, "successful" : 7 }, "feature_states" : [ { "feature_name" : "geoip", "indices" : [ ".geoip_databases" ] }, { "feature_name" : "fleet", "indices" : [ ".fleet-policies-7" ] }, { "feature_name" : "kibana", "indices" : [ ".kibana_8.0.0_001", ".apm-custom-link", ".apm-agent-configuration", ".kibana_task_manager_8.0.0_001" ] } ] } }
① スナップショットに含まれるインデックス。指定したもの以外も入ってますが、この辺りはまだよくわかってません。
リストア
バックアップができたところで、リストアを試してみたいと思います。
https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshots-restore-snapshot.html
リストアは、作成したスナップショットを元にインデックスを作成する操作になります。
なので、バックアップ時にやっていたように、リポジトリやスナップショットがelasticsearchに設定されていなければなりません。
今回のケースではそのまま同じDockerコンテナでリストアを試そうと思うので、リポジトリとスナップショットはバックアップ時に作成したものをそのまま使用できます。もし、別のコンテナやインスタンスにリストアをする場合には、バックアップデータを元にリポジトリを設定します。
リポジトリやスナップショットの確認は次のように行います。
// リポジトリの確認 GET _snapshot/repository_1 // スナップショットの確認 GET _snapshot/repository_1/snapshot_1
ワイルドカードを使って検索を行うこともできます。
GET _snapshot/*/*
リストアは、次のように行います。
POST _snapshot/repository_1/snapshot_1/_restore { "indices": "demo-index" }
URLは _snapshot/<リポジトリ名>/<スナップショット名>/_restore
になります。
ボディではリストアするインデックスを指定します。
ただ、この場合だと同じ名前でインデックスをリストアしようとするために、同名のインデックスが既に存在するとエラーとなります。
{ "error" : { "root_cause" : [ { "type" : "snapshot_restore_exception", "reason" : "[repository_1:snapshot_1/TUBO3UFDTwWbi199smmt6A] cannot restore index [demo-index] because an open index with same name already exists in the cluster. Either close or delete the existing index or restore the index under a different name by providing a rename pattern and replacement name" } ], "type" : "snapshot_restore_exception", "reason" : "[repository_1:snapshot_1/TUBO3UFDTwWbi199smmt6A] cannot restore index [demo-index] because an open index with same name already exists in the cluster. Either close or delete the existing index or restore the index under a different name by providing a rename pattern and replacement name" }, "status" : 500 }
リストアする時にインデックス名を変更するには、次のように、元のインデックス名から文字を一部分切り抜き、新しいインデックス名と連結させます。
POST _snapshot/repository_1/snapshot_1/_restore { "indices": "demo-index", "rename_pattern": "(.+)", "rename_replacement": "restored_index_$1" }
この場合、次のように、リストアが行われました。
GET restored_index_demo-index/_search { "query": { "match_all": {} } } // レスポンス { "took" : 2, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "restored_index_demo-index", "_id" : "ZdevNH8BGshAomOEMFkj", "_score" : 1.0, "_source" : { "name" : "bookstore" } } ] } }