Amazon Elasticsearch ServiceのISMによるインデックス自動削除方法

## はじめに
2020年5月3日にAmazon Elasticsearch Serviceにおいて
Open Distro for ElasticsearchのIndex State Management(以降、ISM)が実装されました。

Open Distro for ElasticsearchでISMが実装されたタイミングで予想していましたが
これにより今まで個別にCuratorを動かすEC2やLambdaを用意してましたが、不要になりました。

**【参考】**
・ [Amazon Elasticsearch Serviceでインデックス管理を自動化する][00]
・ [Amazon Elasticsearch ServiceのIndex State Management][01]
・ [Open Distro for ElasticsearchのIndex State Management][02]
・ [Curatorを使用したAmazon Elasticsearch Serviceでのデータの更新][03]

## 本投稿の内容
この機会にCuratorを卒業し、ISMで古くなったインデックスを自動削除しようと思います。

世には、UltraWarmを使うための設定例やrollover indexを利用する方法ばかりで
単に古いインデックスを自動的に削除する方法がなかったので、まとめてみました。

インデックスの**経過日数(min_index_age)**で試すと結果が出るまでに時間がかかります。
検証する場合、**最小ドキュメント数(min_doc_count)**を「1」とすることをお勧めします。

本検証も最小ドキュメント数を「1」としています。
また、インデックス削除時にSlackに通知するように設定しています。

**【参考】**
・ [Automating Index State Management for Amazon ES][04]

## 利用環境
| 項目 | 内容 |
|---------|---------|
| Elasticsearch | 7.9 (latest) |
| Region | us-west-2 |
※投稿時点における最新版を採用しています。

**【補足】**
・ ISMは、バージョン6.8以降が必要になります。

## 実施手順
1. Webhook URLの取得
2. Index policyの作成
3. 手動でのpolicy適用
4. Index Templateを利用したpolicy適用

### 1. Webhook URLの取得
- 下記のURLを参考にSlackのWebhook URLを取得します。

**【参考】**
・ [SlackのWebhook URL取得手順][05]

### 2. Index policyの作成
- Kibanaにログインします。
- [Index Management] > [Index policies]で**Create policy**をクリックします。
- [Policy ID]を**delete_index_less_than_1_doccuments** (好きな名前とします)とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211371/8ab905ce-b776-c6e8-ee5f-b4d3fa059e9e.png)

- [Define policy]のデフォルト設定を削除し、以下を貼り付け、[Create]をクリックします。

```json:DefinePolicy
{
    "policy": {
        "description": "Changes less than 1 doccuments index deletes.",
        "schema_version": 1,
        "error_notification": {
            "destination": {
                "slack": {
                    "url": "https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxx/xxxxxxxxxxxxx"
                }
            },
            "message_template": {
                "source": "The index {{ctx.index}} failed during policy execution."
            }
        },
        "default_state": "current",
        "states": [
            {
                "name": "current",
                "actions": [],
                "transitions": [
                    {
                        "state_name": "delete",
                        "conditions": {
                            "min_doc_count": 1
                        }
                    }
                ]
            },
            {
                "name": "delete",
                "actions": [
                    {
                        "notification": {
                            "destination": {
                                "slack": {
                                    "url": "https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxx/xxxxxxxxxxxxx"
                                }
                            },
                            "message_template": {
                                "source": "The index {{ctx.index}} is being deleted",
                                "lang": "mustache"
                            }
                        }
                    },
                    {
                        "delete": {}
                    }
                ],
                "transitions": []
            }
        ]
    }
}
```

**【補足】**
・ SlackのURLには、手順1で取得したWebhook URLを使用します。

### 3. 手動でのpolicy適用
- [Index Management] > [Indices]で作成したpolicyを適用するインデックスを選択します。
- **Apply policy**をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211371/fed73468-d60e-e483-d353-40e0322132c2.png)

- 作成したpolicyを選択し、**Apply**をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211371/e9571ac5-7ab0-ba88-e9eb-4b930e47f61a.png)

- **Managed by Policy**がYesになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211371/d31a90b8-a428-e88f-2c93-bfd9a84be99f.png)

- [Managed Indcies]にIndexが表示され、[Job Status]が**Initalizing**となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211371/9e6cc8be-caa0-d680-eb30-4ad4b753316e.png)

- 30〜48分経つと[Job Status]が**Running**となり、policyが適用されました。
- [Info]には、**Successfully initialized policy:<ポリシー名>**が表示されます。
- [Status]には、policyで指定したdefault_stateの値 (current) が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211371/9b7093e9-6af4-9ae0-48c8-0facf96e7dc4.png)

> ポリシーをインデックスにアタッチすると、ISM は 30～48 分ごとに実行されるジョブを作成し、ポリシーアクションを実行して条件を確認してから、インデックスを別の状態に移行します。このジョブを実行する基本時間は 30 分ごとです。さらに、0～60% のランダムなジッターが追加され、すべてのインデックスから同時にアクティビティが急増しないようにします。

- 30分ごとにジョブが実行され、削除条件である最小ドキュメント数1に該当すると、[Info]には**Transitioning to delete [index=<対象のインデックス名>]**が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211371/cefe217e-b8f1-9e41-ae7b-6fa6fe306323.png)

- [Info]に**Successfully sent notification [index=<対象のインデックス名]**と表示されると、Slackに以下のようなメッセージが届きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211371/448c06e2-35f8-16f8-fb5c-8fc582b11c60.png)

- さらに数十分経過するとインデックスは削除されます。

これでインデックスを削除できましたが、これでは都度手動でpolicy適用することになります。
次は、Index Templateを利用し、インデックス作成時にpolicyを適用する方法を紹介します。

### 4. Index Templateを利用したpolicy適用
- 以下、Logstash経由でCloudTrailを取り込む場合のIndex Templateです。
- **opendistro.index_state_management.policy_id**にPolicyIDを指定します。

```json:cloudtrail_index_template
PUT _template/cloudtrail
{
"index_patterns": ["log-aws-cloudtrail-*"],
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas" : 1,
    "opendistro.index_state_management.policy_id": "delete_index_less_than_1_doccuments",
    "index.mapping.total_fields.limit": 2000
  },
  "mappings" : {
    "dynamic_templates" : [
      {
        "message_field" : {
          "path_match" : "message",
          "match_mapping_type" : "string",
          "mapping" : {
            "type" : "text",
            "norms" : false
          }
        }
      },
      {
        "string_fields" : {
          "match" : "*",
          "match_mapping_type" : "string",
          "mapping" : {
            "type" : "text",
            "norms" : false,
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    ],
    "properties" : {
      "@timestamp" : {
        "type" : "date"
      },
      "@version" : {
        "type" : "keyword"
      },
      "geoip" : {
        "dynamic" : true,
        "properties" : {
          "ip" : {
            "type" : "ip"
          },
          "location" : {
            "type" : "geo_point"
          },
          "latitude" : {
            "type" : "half_float"
          },
          "longitude" : {
            "type" : "half_float"
          }
        }
      }
    }
  },
  "aliases" : { }
}
```

- これで手動でpolicy適用した場合と同様に**Managed Indices**に表示されます。
- [Info]が**Evaluating transition conditions [index=<対象のインデックス>]**の場合は、policy評価中でまだ条件に合致していない状態です。

## まとめ
さて、いかがでしたでしょうか？

今回は、最小ドキュメント数で試しましたが、以下のように
インデックスの経過日数を31日にすれば、1ヶ月以上前のインデックスは自動的に削除してくれます。

```
"conditions": {
    "min_index_age": 31
}
```

UltraWarmは、そこそこな規模が無いと費用対効果が合いません。
インデックスの自動削除としても便利な機能だと思います！

皆様もぜひ活用してみてはいかがでしょうか ^^

[00]:https://aws.amazon.com/jp/about-aws/whats-new/2020/03/automate-index-management-with-amazon-elasticsearch-service/ "Amazon Elasticsearch Serviceでインデックス管理を自動化する"
[01]:https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/ism.html "Amazon Elasticsearch ServiceのIndex State Management"
[02]:https://opendistro.github.io/for-elasticsearch-docs/docs/ism/ "Open Distro for ElasticsearchのIndex State Management"
[03]:https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/curator.html "Curatorを使用したAmazon Elasticsearch Serviceでのデータの更新"
[04]:https://aws.amazon.com/jp/blogs/big-data/automating-index-state-management-for-amazon-es/ "Automating Index State Management for Amazon ES"
[05]:https://qiita.com/vmmhypervisor/items/18c99624a84df8b31008 "SlackのWebhook URL取得手順"