AmazonESに別クラスタで取得したElasticsearchのスナップショットをリストアする方法


AmazonESを検証するにあたり、既存のオンプレのインデックスをリストアして試験したいかったので、運用中のESスナップショットからAmazonESへのリストアをやってみた。
Elasticsearchでは、snpshot&restoreはAPI介して簡単に行えるが、AmazonESはAWS独自設定(権限)が結構難しかったのでその内容をシェア。

※Amazon ES Amazon Elasticsearch Serviceの略(長いので以下はESSに略す)
公式の略に準拠
![Amazon_Web_Services_ブログ__【AWS発表】Amazon_Elasticsearch_Service.jpg](https://qiita-image-store.s3.amazonaws.com/0/40850/437cd926-ac78-6334-cb03-0410afb9b434.jpeg "Amazon_Web_Services_ブログ__【AWS発表】Amazon_Elasticsearch_Service.jpg")

#内容

Elasticsearchで取得したスナップショットを、AmazonES上にリストアしてインデックスが出来るまで。

要約すると、Amazon ESのスナップショットリポジトリとしてs3バケットを指定し、別のESで取得したスナップショットを対象にrestoreすることでデータの復元をするという仕組み

※個人的には、IAMをうまく理解出来てなかったのでつまずきポイントが多く、やったことを手順にまとめた。


![よくある質問_-_Amazon_Elasticsearch_Service___AWS.jpg](https://qiita-image-store.s3.amazonaws.com/0/40850/5a46d944-58d7-1e03-20e2-27a1a480e2c4.jpeg "よくある質問_-_Amazon_Elasticsearch_Service___AWS.jpg")

#タスクリスト

- [x] ~~s3をスナップショット置き場として設定し取得~~ 手元で取ってs3にアップロードすれば良い
- [x] オンプレ(バックアップ元)でのsnapshot取得(ローカルに取得するケース)
- [x] AmazonESでスナップショットのリポジトリを作る(ここ大変、、)
- [x] AmazonESにスナップショットからリストア

#手順

例)
web_aplog-2016.09.0という名前のインデックスを、オンプレのElasticsearchからAmazon ESにリストアする

##1.オンプレ(バックアップ元)でのsnapshot取得

###1.ローカルのファイルシステムにスナップショットリポジトリを登録

```
$ curl -XPUT 'http://localhost:9200/_snapshot/snapshot1' -d '{
      "type": "fs",
      "settings": {
          "location": "/opt/work/es_backup/snapshot1",
          "compress": true
      }
  }'
```

###2.web_aplog-2016.09.05というインデックスのスナップショット取得

```
$ curl -XPUT http://localhost:9200/_snapshot/snapshot1/snapshot_1 - d '{
  "indices": "web_aplog-2016.09.05",
  "ignore_unavailable": true,
  "include_global_state": false
}'
```

###スナップショットのステータス確認

![1__nagais_logsrv1__opt_work_es_backup_snapshot1__ssh_.jpg](https://qiita-image-store.s3.amazonaws.com/0/40850/8cc9fdb6-c60a-1a49-9229-ad37bd47af77.jpeg "1__nagais_logsrv1__opt_work_es_backup_snapshot1__ssh_.jpg")

###スナップショットディレクトリのファイル郡

![Banners_and_Alerts_と_1__nagais_logsrv1__opt_work_es_backup_snapshot1__ssh_.jpg](https://qiita-image-store.s3.amazonaws.com/0/40850/5381e4a6-a608-285b-6eb6-426d456e0c54.jpeg "Banners_and_Alerts_と_1__nagais_logsrv1__opt_work_es_backup_snapshot1__ssh_.jpg")


###3.取得したスナップショットをs3バケット(後の手順でAmazon ESのスナップショットリポジトリに指定する)にアップロードする

#####※バケット直下にこの4ファイルを置くこと(下手な階層作ると後々ハマる原因になるので注意)

##2.AmazonESでスナップショットのリポジトリを作る(ここ大変、、)

###1.AmazonES用のIAMRoleを作成する

仮で、AmazonESRelationという名前のロールを作るとする。

1-1.適当な名前でロールを作る
1-2.TypeをAmazon EC2で作らねばならない
1-3.ロールが出来たら信頼関係ポリシに下記を追加する


```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "es.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

###2.スナップショット置き場となるS3バケットに対して、1で作ったロールの権限を付けてあげる

IAM力が低すぎて、個人的には理解して動かすのに一番時間かかったところ。

【ここでやること】
ElasticsearchのAPIでスナップショットリポジトリとする、s3に対して、IAMロールのアクセス権限を与える。

2-1.s3のアクセスポリシに下記設定を入れる

Principalに1で作ったロールをマッピングすることで、該当s3バケットに対してAmazonESからのアクセスが可能となる。

```
{
	"Version": "2012-10-17",
	"Id": "xxx",
	"Statement": [
		{
			"Effect": "Allow",
			"Principal": {
				"AWS": "arn:aws:iam::[ID]:role/AmazonESRelation"
			},
			"Action": "s3:ListBucket",
			"Resource": "arn:aws:s3:::[バケット名]"
		},
		{
			"Effect": "Allow",
			"Principal": {
				"AWS": "arn:aws:iam::[ID]:role/AmazonESRelation"
			},
			"Action": "s3:*",
			"Resource": "arn:aws:s3:::[バケット名]/*"
		}
	]
}
```

##3.AmazonESに対して、ElasticsearchのREST APIを介したスナップショットリポジトリの登録

3-1.python実行環境で、botoライブラリをインストール

```
pip install python
```

3-2.AWSがサンプルのpythonコードを用意してくれているので、各値を自分の環境のものに書き換える。

※下記サンプルは、AWSのサポートページのままなので適宜読み替える。

```
from boto.connection import AWSAuthConnection

class ESConnection(AWSAuthConnection):

    def __init__(self, region, **kwargs):
        super(ESConnection, self).__init__(**kwargs)
        self._set_auth_region_name(region)
        self._set_auth_service_name("es")

    def _required_auth_capability(self):
        return ['hmac-v4']

if __name__ == "__main__":

    client = ESConnection(
            region='us-east-1',
            host='search-weblogs-etrt4mbbu254nsfupy6oiytuz4.us-east-1.es.a9.com',
            aws_access_key_id='my-access-key-id',
            aws_secret_access_key='my-access-key', is_secure=False)

    print 'Registering Snapshot Repository'
    resp = client.make_request(method='POST',
            path='/_snapshot/weblogs-index-backups',
            data='{"type": "s3","settings": { "bucket": "es-index-backups","region": "us-east-1","role_arn": "arn:aws:iam::123456789012:role/MyElasticsearchRole"}}')
    body = resp.read()
    print body
```

3-3.実行

成功すると下記のように出力される。

#####※	1,2の設定が出来てないと、尽く403エラーで弾かれるのでその場合は都度追ってい原因を確認。。

```
$ python snapshot_setting.py
Registering Snapshot Repository
{"acknowledged":true}


```

##4.AmazonESにスナップショットからリストア

4-1.AmazonES上から、s3にオンプレからコピーしたスナップショットの存在が見れることを確認

※ここで最初に取ってs3バケットにアップロードしたスナップショットが見れるようになっているはず。

```
$ curl -XGET [AmazonESエンドポイント]/_snapshot/es-snapshot/_all?pretty
{
  "snapshots" : [ {
    "snapshot" : "snapshot_1",
    "version_id" : 1050299,
    "version" : "1.5.2",
    "indices" : [ "web_aplog-2016.09.05" ],
    "state" : "SUCCESS",
    "start_time" : "2016-09-30T10:22:30.491Z",
    "start_time_in_millis" : 1475230950491,
    "end_time" : "2016-09-30T10:25:02.025Z",
    "end_time_in_millis" : 1475231102025,
    "duration_in_millis" : 151534,
    "failures" : [ ],
    "shards" : {
      "total" : 2,
      "failed" : 0,
      "successful" : 2
    }
  } ]
}


```

4-2.リストア

ここまで来ればリストア出来たも同然なのでリストアのAPIを叩く

- リストア中は、AmazonESのクラスタ状態がRedになる
- 1250万docs,2.2Gのリストあで2分30秒くらい

```
$ curl -XPOST https://[AmazonESエンドポイント]/_snapshot/es-snapshot/snapshot_1/_restore
{"accepted":true}
```

4-3.リストアのステータス確認

```
[AmazonESエンドポイント]/_snapshot/es-snapshot/snapshot_1/_status?pretty
{
  "snapshots" : [ {
    "snapshot" : "snapshot_1",
    "repository" : "es-snapshot",
    "state" : "SUCCESS",
    "shards_stats" : {
      "initializing" : 0,
      "started" : 0,
      "finalizing" : 0,
      "done" : 2,
      "failed" : 0,
      "total" : 2
    },
    "stats" : {
      "number_of_files" : 212,
      "processed_files" : 212,
      "total_size_in_bytes" : 2425102339,
      "processed_size_in_bytes" : 2425102339,
      "start_time_in_millis" : 1475230950905,
      "time_in_millis" : 151028
    },

    "stats" : {
      "number_of_files" : 212,
      "processed_files" : 212,
      "total_size_in_bytes" : 2425102339,
      "processed_size_in_bytes" : 2425102339,
      "start_time_in_millis" : 1475230950905,
      "time_in_millis" : 151028
    },
    "indices" : {
      "web_aplog-2016.09.05" : {
        "shards_stats" : {
          "initializing" : 0,
          "started" : 0,
          "finalizing" : 0,
          "done" : 2,
          "failed" : 0,
          "total" : 2
        },
        "stats" : {
          "number_of_files" : 212,
          "processed_files" : 212,
          "total_size_in_bytes" : 2425102339,
          "processed_size_in_bytes" : 2425102339,
          "start_time_in_millis" : 1475230950905,
          "time_in_millis" : 151028
        },
        "shards" : {
          "0" : {
            "stage" : "DONE",
            "stats" : {
              "number_of_files" : 106,
              "processed_files" : 106,
              "total_size_in_bytes" : 1212374605,
              "processed_size_in_bytes" : 1212374605,
              "start_time_in_millis" : 1475230950905,
              "time_in_millis" : 151028
            }
          },
          "1" : {
            "stage" : "DONE",
            "stats" : {
              "number_of_files" : 106,
              "processed_files" : 106,
              "total_size_in_bytes" : 1212727734,
              "processed_size_in_bytes" : 1212727734,
              "start_time_in_millis" : 1475230950906,
              "time_in_millis" : 147145
            }
          }
        }
      }
    }
  } ]
}

```

4-4.GUIからも一応確認。

ここまで来ればKibanaから見るもよし、API突くもよしというレディ状態になる。

[AmazonES WebUI]
![Amazon_Elasticsearch_Service_Management_Console.jpg](https://qiita-image-store.s3.amazonaws.com/0/40850/45e906ba-a5b2-287f-3611-c8ccdd8fdc57.jpeg "Amazon_Elasticsearch_Service_Management_Console.jpg")

[kibana]

![Discover_-_Kibana_4.jpg](https://qiita-image-store.s3.amazonaws.com/0/40850/91a4bf89-7380-5530-d13a-7e544a248820.jpeg "Discover_-_Kibana_4.jpg")

※timestamp型のフォーマットが少し気になるな(後で、共通なのかリストアにもテンプレート効くのか確かめてみる)

##所感

振り返ってみると、IAMをしっかり理解していればそんなに難しいポイントはなかったのかもしれない。
只、これで既存のインデックス復元して、Amazon ESでのパフォーマンス試験が出来る！！

##参照

http://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/es-managedomains.html#es-managedomains-snapshot-registerdirectory

https://www.elastic.co/guide/en/elasticsearch/reference/2.3/modules-snapshots.html#_snapshot_status