Amazon Elasticsearch Service(以後esと記載)のsnapshotを取得する際、権限まわりで詰まったので、まとめてみる。
利用環境はMacです。
【背景】
- esのsnapshotを手動で取得するのってどんな方法でできるんだろう。
- なんかちょっと権限まわりややこしそうだから一回触ってみよう
- 取得と復元でどれぐらい時間がかかるかもできたら測ってみよう
こんな課題感で手を動かし始めました。
【実際にやったこと】
- 公式ドキュメントを参考にする
- 【Amazon Elasticsearch Service】 手動スナップショットからリストアする方法を参考にする(この記事を本当に参考にさせていただきました)
- Kibanaでアクセス許可を与える
このような手順で実現させて行きました!!!
手動でS3にsnapshotを取得していく
手動でsnapshotを作成するためには、前提として、以下の対応が必要になります。
- s3のバケットの作成
- IAMロール、ポリシーを整理する(←ここで苦労しました)
- Kibanaでの認証
- 手動snapshotのリポジトリを登録する
- 手動snapshotを取得する
- snapshotを取得したリポジトリを確認する
- snapshotの取得状況を確認する
- スナップショットのリストア
- 一度インデックスを削除する
- 指定したインデックスをリストアする
今回記述しているscriptはpythonで書いていますが、他にもJava, Ruby, Node, Goでも記述できます。こちらの公式ドキュメントを参考にしてください
それでは順番に説明していきたいと思います。
S3バケットの作成
手動でsnapshotを保存するためのバケットを作成する。
今回はS3コンソールでarn:aws:s3:::test-es-snapshot
を作成した。これは以下の二つの箇所で必要になる
- IAMロールにアタッチされたIAMポリシーのResource Statement内
- snapshotリポジトリ登録に使用するpythonのpayload内
IAMロール、ポリシーを整理する
今回確認すべき箇所は三箇所
1.ESのサービスロール(arn:aws:iam::ユーザ名:role/es_s3_role)を作成する。
信頼関係を以下のように編集する
principalで指定するのは"誰がこのロールを引き受けるか”ということ
以下のServiceはesを示しており、「作成したサービスロールはesを引き受ける」という意味(だと思う。)
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "es.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
}
2.S3に対してアクセスし、データを取得するためのポリシーをサービスロールに対してアタッチする
create-es-backup-policyという管理ポリシーを以下の内容で作成し、上で作成したサービスロールに対してアタッチする
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::test-es-snapshot"
]
},
{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::test-es-snapshot/*"
]
}
]
}
3.Kibana側でIAMロールのアクセスを許可する
Kibana で、[Security (セキュリティ)]、[Role Mappings (ロールのマッピング)]、[Add (追加)] の順に選択します。[Role (ロール)]で、[manage_snapshots] を選択します。次に、IAM ユーザーまたは IAM ロールの ARN を該当するフィールドに指定します。ユーザーの ARN は、[Users (ユーザー)]セクションに入力します。ロールの ARN は、[Backend roles (バックエンドロール)] セクションに入力します。(※これで、スナップショットを使用するためのロール情報のアクセス許可を付与する)
今回はKibanaのRole MappingsというページのBackend Rolesというところに、作成したサービスロールのARN情報を入力した。
(IAMのポリシーの操作でも認証情報は設定できるはずだが、エラーで詰まったのでこの手法で回避した)
以上で、IAMロール周りの整理は終わりです。
手動snapshotのリポジトリを登録する
以下のpythonスクリプトを実行する(参考資料では認証をアクセスキーで行っていたが、現在公式からアクセスキーでの認証は、推奨されていない)
import boto3
import requests
from requests_aws4auth import AWS4Auth
region = 'リージョン名' # e.g. us-west-1
service = 'es'
credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)
host = 'esドメインのエンドポイント /' # /を忘れないように
# Register repository
path = '_snapshot/test-es-snapshot' # the Elasticsearch API endpoint
url = host + path
payload = {
"type": "s3",
"settings": {
"bucket": "バケット名",
"region": "リージョン名",
"role_arn": "作成したサービスロール名"
}
}
headers = {"Content-Type": "application/json"}
r = requests.put(url, auth=awsauth, json=payload, headers=headers)
print(r.status_code)
print(r.text)
responseが以下のようになっていることを確認する
200
{"acknowledged":true}
手動snapshotを取得する
import boto3
import requests
from requests_aws4auth import AWS4Auth
region = 'リージョン名' # e.g. us-west-1
service = 'es'
credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)
host = 'esドメインのエンドポイント /' # /を忘れないように
path = '_snapshot/test-es-snapshot/my-snapshot-1' # the Elasticsearch API endpoint
url = host + path
r = requests.put(url, auth=awsauth)
print(r.text)
-> % python snapshot.py
Enter MFA code for :
{"accepted":true}
snapshotを取得したリポジトリを確認する
import boto3
import requests
from requests_aws4auth import AWS4Auth
region = 'リージョン名' # e.g. us-west-1
service = 'es'
credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)
host = 'esドメインのエンドポイント /' # /を忘れないように
path = '_snapshot/?pretty'
url = host + path
r = requests.get(url, auth=awsauth)
print(r.text)
-> % python check_repository.py
Enter MFA code for :
{
"cs-automated-enc" : {
"type" : "s3"
},
"test-es-snapshot" : {
"type" : "s3",
"settings" : {
"bucket" : "test-es-snapshot",
"region" : "リージョン名",
"role_arn" : "作成したサービスロール名"
}
}
}
snapshotの取得状況を確認する
import boto3
import requests
from requests_aws4auth import AWS4Auth
region = 'リージョン名' # e.g. us-west-1
service = 'es'
credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)
host = 'esドメインのエンドポイント /' # /を忘れないように
path = '_snapshot/test-es-snapshot/_all?pretty'
url = host + path
r = requests.get(url, auth=awsauth)
print(r.text)
-> % python check_snapshot.py
Enter MFA code for :
{
"snapshots" : [ {
"snapshot" : "my-snapshot-1",
"uuid" : "*************",
"version_id" : ******,
"version" : "7.8.0",
"indices" : [ "index名①", "index名②", ・・・・・・ ],
"include_global_state" : true,
"state" : "SUCCESS",
"start_time" : "2020-11-17T07:20:17.265Z",
"start_time_in_millis" : 1605597617265,
"end_time" : "2020-11-17T07:21:21.901Z",
"end_time_in_millis" : 1605597681901,
"duration_in_millis" : 64636,
"failures" : [ ],
"shards" : {
"total" : 38,
"failed" : 0,
"successful" : 38
}
} ]
}
スナップショットのリストア
リストアの際に同じ名前のインデックスがある場合、リストアできないので、リストアしたいインデックスを一度削除する必要があります。
指定のインデックスを一度削除して、リストアするまでの手順を示します。
一度インデックスを削除する
import boto3
import requests
from requests_aws4auth import AWS4Auth
region = 'リージョン名' # e.g. us-west-1
service = 'es'
credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)
host = 'esドメインのエンドポイント /' # /を忘れないように
# DELETE INDEX
path = 'インデックス名'
url = host + path
r = requests.delete(url, auth=awsauth)
print(r.text)
-> % python delete_index.py
Enter MFA code for :
{"acknowledged":true}
esのコンソールで、ドメインを選択し、インデックスタブに行くと、インデックスが削除できていることを確認できます。
また、ダッシュボードで、検索可能なドキュメントが少なくなっていることも確認できます。
指定したインデックスをリストアする
import boto3
import requests
from requests_aws4auth import AWS4Auth
region = 'リージョン名' # e.g. us-west-1
service = 'es'
credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)
host = 'esドメインのエンドポイント /' # /を忘れないように
path = '_snapshot/test-es-snapshot/my-snapshot-1/_restore'
url = host + path
payload = {"indices": "インデックス名"}
headers = {"Content-Type": "application/json"}
r = requests.post(url, auth=awsauth, json=payload, headers=headers)
print(r.text)
-> % python restore_one.py
Enter MFA code for :
{"accepted":true}
まとめ
snapshotの取得やリストアは参考資料がとても役に立ちました。(ほとんど同じです。)
IAMのロールやポリシーの整理をするときに、結構苦労しました。。。
どのロールにどのポリシーをアタッチしたとかをしっかり整理できてないと厳しかったです。。
どなたかの参考になれば幸いです。。