LoginSignup
0
1

More than 3 years have passed since last update.

Amazon Elasticsearch serviceのsnapshot取得してリストア(復元)するまで

Last updated at Posted at 2020-11-19

Amazon Elasticsearch Service(以後esと記載)のsnapshotを取得する際、権限まわりで詰まったので、まとめてみる。
利用環境はMacです。

【背景】

  • esのsnapshotを手動で取得するのってどんな方法でできるんだろう。
  • なんかちょっと権限まわりややこしそうだから一回触ってみよう
  • 取得と復元でどれぐらい時間がかかるかもできたら測ってみよう

こんな課題感で手を動かし始めました。

【実際にやったこと】

このような手順で実現させて行きました!!!

手動で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という管理ポリシーを以下の内容で作成し、上で作成したサービスロールに対してアタッチする

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スクリプトを実行する(参考資料では認証をアクセスキーで行っていたが、現在公式からアクセスキーでの認証は、推奨されていない)

register-repositry.py
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を取得する

snapshot.py
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を取得したリポジトリを確認する

check_repository.py
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の取得状況を確認する

check_snapshot.py
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
    }
  } ]
}

スナップショットのリストア

リストアの際に同じ名前のインデックスがある場合、リストアできないので、リストアしたいインデックスを一度削除する必要があります。
指定のインデックスを一度削除して、リストアするまでの手順を示します。

一度インデックスを削除する

delete_index.py
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のコンソールで、ドメインを選択し、インデックスタブに行くと、インデックスが削除できていることを確認できます。
また、ダッシュボードで、検索可能なドキュメントが少なくなっていることも確認できます。

指定したインデックスをリストアする

restore_one.py
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のロールやポリシーの整理をするときに、結構苦労しました。。。
どのロールにどのポリシーをアタッチしたとかをしっかり整理できてないと厳しかったです。。

どなたかの参考になれば幸いです。。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1