closeされたインデックスのスナップショットを作成する

# はじめに

細かい機能ですが、いつの間にやらcloseされたインデックスのスナップショットが作れるようになっています。
今回は、これをちょっと試してみたいと思います。
といっても、7.1以降の機能ではありますが・・・

（2019.03.20[追記](#20190320追記)）

# 準備

## ドキュメントの確認

[公式ドキュメント](https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html)を開いておきます。
というか、私はすぐコマンド忘れちゃうもんで・・・

## インスタンスの起動

自分でコンパイルするもよし、本家のDocker Image(`docker.elastic.co/elasticsearch/elasticsearch:8.0.0-SNAPSHOT`とか）をもってきて起動するもよし。
スナップショットを作るので、以下の設定もしておきます。

```yaml:elasticsearch.yml
path.repo: /var/lib/elasticsearch/snapshots
```

## リポジトリ作成

リポジトリを作成します。

```json
PUT /_snapshot/my_backup
{
   "type": "fs",
   "settings": {
     "location": "/usr/share/elasticsearch/snapshots"
   }
}

{
   "acknowledged" : true
}
```

## インデックスの用意

スナップショット取得対象のインデックスを用意します。
何でも良いですが、KibanaのSampleがあるので、それをReindexして使ってみます。

```json
POST _reindex
{
   "source": {
     "index": "kibana_sample_data_logs"
   },
   "dest": {
     "index": "snapshot_test"
   }
}

{
   "took" : 2653,
   "timed_out" : false,
   "total" : 14005,
   "updated" : 14005,
   "created" : 0,
   "deleted" : 0,
   "batches" : 15,
   "version_conflicts" : 0,
   "noops" : 0,
   "retries" : {
     "bulk" : 0,
     "search" : 0
   },
   "throttled_millis" : 0,
   "requests_per_second" : -1.0,
   "throttled_until_millis" : 0,
   "failures" : [ ]
}
```

で、作成出来たら即クローズ。

```json
POST snapshot_test/_close

{
   "acknowledged" : true,
   "shards_acknowledged" : true
}
```

## スナップショットの作成

さて、スナップショットを作成してみます。

```json
PUT /_snapshot/my_backup/snapshot_2?wait_for_completion=true
{
   "indices": "snapshot_test",
   "ignore_unavailable": true
}

{
   "snapshot" : {
     "snapshot" : "snapshot_2",
     "uuid" : "09_ykunaRdqrv9v4j1DCXw",
     "version_id" : 8000099,
     "version" : "8.0.0",
     "indices" : [
       "snapshot_test"
     ],
     "include_global_state" : true,
     "state" : "SUCCESS",
       "start_time" : "xxxx-xx-xxTxx:xx:xx.xxxZ",
       "start_time_in_millis" : xxxxxxxxxxxxx,
       "end_time" : "yyyy-yy-yyTyy:yy:yyyZ",
       "end_time_in_millis" : yyyyyyyyyyyyy,
     "duration_in_millis" : 637,
     "failures" : [ ],
     "shards" : {
       "total" : 1,
       "failed" : 0,
       "successful" : 1
     }
   }
}
```

できたようです。
確認してみると・・・

```json
GET _snapshot/my_backup/snapshot_2

{
   "snapshots" : [
     {
       "snapshot" : "snapshot_2",
       "uuid" : "09_ykunaRdqrv9v4j1DCXw",
       "version_id" : 8000099,
       "version" : "8.0.0",
       "indices" : [
         "snapshot_test"
       ],
       "include_global_state" : true,
       "state" : "SUCCESS",
       "start_time" : "xxxx-xx-xxTxx:xx:xx.xxxZ",
       "start_time_in_millis" : xxxxxxxxxxxxx,
       "end_time" : "yyyy-yy-yyTyy:yy:yyyZ",
       "end_time_in_millis" : yyyyyyyyyyyyy,
       "duration_in_millis" : 637,
       "failures" : [ ],
       "shards" : {
         "total" : 1,
         "failed" : 0,
         "successful" : 1
       }
     }
   ]
}
```

ちゃんとできているようです。

6系とかでcloseされたインデックスのスナップショットを作成しようとすると、

```json
{
   "error": {
     "root_cause": [
       {
         "type": "cluster_block_exception",
         "reason": "blocked by: [FORBIDDEN/4/index closed];"
       }
     ],
     "type": "cluster_block_exception",
     "reason": "blocked by: [FORBIDDEN/4/index closed];"
   },
   "status": 403
}
```

と言われてしまいます。

## レストア

さて、スナップショットをレストアしてみます。
まずは、元のインデックスを削除します。

```json
DELETE snapshot_test

{
   "acknowledged" : true
}
```

続いてレストア。

```json
POST /_snapshot/my_backup/snapshot_2/_restore

{
   "accepted" : true
}
```

できたみたいなので、確認してみます。

```json
GET _cat/indices/snapshot_test

yellow open snapshot_test wILZAszyQ3CSD2t97kMf8g 1 1 14005 0 10.9mb 10.9mb
```

ちゃんと元に戻ってますね。
openしているのはご愛敬。

# 最後に

今まではメモリから追い出したいけど、スナップショット作るまではcloseできないなーと思ってたのですが、これえができるようになると、メモリが圧迫されなくてよくなるのはありがたいですね。
＃フリーズでも良いけど。

CCRでもcloseされたインデックスが扱えるようになっているようなので、そのうち（気が向いたら。か、ネタが無かったら）試してみましょう。
⇒やってみたけどレプリケーションされていないような気がする・・・なんか条件あんのかな・・・

# 追記

## 2019.03.20追記

クローズがらみで、CCRのお話。

### CCRのleader側をcloseした場合

CCRの場合、leader側のIndexをcloseすると、follower側では、以下の例外を検知するらしい。

```json
   "readExceptions": [
     {
       "from_seq_no": 3,
       "retries": 5,
       "exception": {
         "type": "cluster_block_exception",
         "reason": "blocked by: [FORBIDDEN/4/index closed];"
       }
     }
   ]
```

でも、follower側は特に何も起きない。
leader側Indexを再度openした後は、followのpause->resumeすると普通にfollowが再開されます。

### CCRのleader側をfreezeした場合

これに対して、leader側をfreezeすると、まず以下の状態になるらしい。

```json
   "readExceptions": [
     {
       "from_seq_no": 1,
       "retries": 6,
       "exception": {
         "type": "no_shard_available_action_exception",
         "reason": "No shard available for [Request{fromSeqNo=1, maxOperationCount=5120, shardId=[ccr_test-1][0], expectedHistoryUUID=_kL7U9HMRgy7cAISsXpT-A, pollTimeout=1m, maxBatchSize=32mb}]"
       }
     }
   ]
```

しばらくすると、follower側のIndexはcloseされます。
leader側をunfreezeしてから、follower側Indexをfollowのpause->resumeすると、以下のエラーがでやがります。

```
[illegal_argument_exception] the leader index setting[{"index.frozen":"false","index.number_of_shards":"1"}] and follower index settings [{"index.number_of_shards":"1"}] must be identical
```

freezeするとElasticsearchが`index.frozen: false`という値を設定しちゃうんですね。でも、その値はfollower側にはないので、整合性が取れてないよ、と。
なので、follower側Indexをfreeze->unfreezeしてから、followのpause->resumeをすると、ちゃんとfollowが再開されます。

てか、これそのうち動きが変わるかな。