Rso's Jotter

日々の開発の知見のメモやその他雑記

AWS ElasticSearch Service の手動スナップショットを取得する

掲題の対応を実施したので、内容をメモしておきます。

AWSはElastic Search Serivceを使えば、Elastic Searchを簡単に起動でき、Kibanaも入っている状態でスタートできるのですが、 データの手動バックアップアップ、リストアに関してはひと手間かかります。

手順

以下の公式の手順を実施するだけで終わりなのですが、やや行間を埋める必要があったので、そこを埋めつつ記載します。

docs.aws.amazon.com

上記を見ると、自動スナップショットはよろしく取ってくれるようですが、手動スナップショットはいくつかの手順を踏む必要があると書いています。 自分は、Elastic Searchドメインを削除する前に、事前にバックアップを取得しておく必要があり、手動バックアップを行いました。

前提条件

なにやら実施する前にいくつかの前提条件があるそうですが、まとめると..

  • Elastic Searchのスナップショット格納先のS3バケットを作成する必要がある。(Glacierはだめ)
  • ElasticSearch Service に S3にデータを保存できるロールを作成し、付与する必要がある。
    • (IAMに慣れていないと分かりづらいかもですが)、ElasticSearch Serviceがこのロールを扱える(引き受けられる)ように IAMロールに Principal を設定する必要がある。
    • ロールの付与はElasticSearch Serviceのアクセスポリシーの設定から行う。

Principal の設定は以下のIAMロール画面の 信頼関係 タブから設定できます。

f:id:rso:20200622181423p:plain
IAMロール画面

設定したprincipal は以下のとおりです。(公式のそのまま)

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

このロールに、ポリシーを追加してやります。今回は面倒なのでインラインポリシーで追加しました。 S3バケット名を、バックアップ用に作成したバケット名に変更してやります。

{
  "Version": "2012-10-17",
  "Statement": [{
      "Action": [
        "s3:ListBucket"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::s3-es-backup"
      ]
    },
    {
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::s3-es-backup/*"
      ]
    }
  ]
}

さらに、次にElastic Search Serviceのアクセスポリシーを修正して、先程作成したロールの付与と、スナップショット作成のために HttpsPut を許可してやります。こちらはElasticSearch Serviceの画面から 修正します。 こちらは公式のものをコピペすると何故かエラーになり、 "Principal" を追加してやると変更できました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::xxxxxxx:role/ESTheSnapshotRole"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "es:ESHttpPut"
      ],
      "Resource": "arn:aws:es:ap-northeast-1:xxxxx:domain/es-target-domain/*"
    }
  ]
}

スナップショットリポジトリの登録

通常であれば PUT elasticsearch-domain-endpoint/_snapshot/my-snapshot-repo-name でスナップショットリポジトリを登録できるのですが、AWSの ElasticSearch ServiceはCurlでは対応できず、Pythonなどのライブラリを使用する必要があるようです。これもサンプルを指示通りに修正し、実行します。

import boto3
import requests
from requests_aws4auth import AWS4Auth

host = 'https://xxxxxxxx.ap-northeast-1.es.amazonaws.com/' # include https:// and trailing /
region = 'ap-northeast-1' # 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)

# Register repository

path = '_snapshot/es-snapshot-repo-name' # the Elasticsearch API endpoint
url = host + path

payload = {
  "type": "s3",
  "settings": {
    "bucket": "s3-es-backup",
    "region": "ap-northeast-1", # for all other regions
    "role_arn": "arn:aws:iam::xxxxxxx:role/ESTheSnapshotRole"
  }
}

headers = {"Content-Type": "application/json"}

r = requests.put(url, auth=awsauth, json=payload, headers=headers)

print(r.status_code)
print(r.text)

上記を実行して {acknowledgement: true} が返ってきたので、作成できたようです。

スナップショット取得

スナップショット取得は上記に続き以下を実行します。

path = '_snapshot/es-snapshot-repo-name/last-snapshot'
url = host + path

r = requests.put(url, auth=awsauth)

これを実行した後、 GET /_snapshot/es-snapshot-repo-name/_all でスナップショット作成状態を確認し、 SUCCESS 担っていることを確認し、S3にも出力されていることを確認しました。

リストア

リストアに関しては、長くなってきたので、割愛します..

所感

いつも雰囲気でIAMを使用して理解していないせいもあり、少し予想より時間がかかってしまいました。 Elastic Search Serviceはとても簡単に利用開始できるのですが、こいう言った細かい運用は少し複雑な印象を受けます。このあたりももっとさくっとできればいいのですが...