はじめに

先日こちらの記事で、自動スナップショットと手動スナップショットについて記載しました。
特に手動スナップショットとリストアについて、記事内での紹介のみではイメージ湧きづらかったので、今回はその手順について記載します。

手動スナップショットの取得の流れ

大きな流れとしては以下のような形です。

  • 取得先 S3 バケット作成
  • スナップショット取得時に設定する Role 作成
  • 取得先 S3 をリポジトリ登録
  • 既存クラスターのスナップショット取得

イメージ図

前提

  • VPC に OpenSearch を構築したパターンを想定しており、EC2 に接続してから行うイメージで記載しています。
  • きめ細かいアクセスポリシーを設定していない前提の内容となります。
  • 基本的には OpenSearch に関わる手順内容を記載し、Role や S3 の記載手順の詳細なものは記載しません。

必要な Role やポリシー(画像内の黄色の吹き出しの設定)

EC2 のインスタンス Role に次のポリシーをアタッチしておく:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/ スナップショットリポジトリ登録 Role"
    },
    {
      "Effect": "Allow",
      "Action": "es:ESHttpPut",
      "Resource": "arn:aws:es:region:123456789012:domain/OpenSearchのドメイン名/*"
    }
  ]
}

この Role が無いと、対象ドメインの OpenSearch のスナップショットの取得先としてリポジトリ登録処理ができないため、バックアップの処理を指示できません(AWSアカウントやドメイン名は書き換えてください)。

スナップショット取得先の S3 をリポジトリとして登録(画像内の青色吹き出しの設定)

スナップショットリポジトリ登録 Role 作成し、以下のポリシーと信頼関係を作成した Role に設定する:

{
  "Version": "2012-10-17",
  "Statement": [{
      "Action": [
        "s3:ListBucket"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::s3-bucket-name"
      ]
    },
    {
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::s3-bucket-name/*"
      ]
    }
  ]
}
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "",
    "Effect": "Allow",
    "Principal": {
      "Service": "es.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
  }]
}

スナップショット取得先の S3 をリポジトリとして登録

トークン取得:

TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`

role 取得:

ROLE_NAME=`curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/iam/security-credentials/

クレデンシャル取得:

CRED=`curl -H "X-aws-ec2-metadata-token: $TOKEN" -s "http://169.254.169.254/latest/meta-data/iam/security-credentials/${ROLE_NAME}"`

クレデンシャル整形(リージョンは適切なものを指定します):

AWS_ACCESS_KEY_ID=`echo $CRED | jq -r ".AccessKeyId"`
AWS_SECRET_ACCESS_KEY=`echo $CRED | jq -r ".SecretAccessKey"`
AWS_SESSION_TOKEN=`echo $CRED | jq -r ".Token"`
REGION="ap-northeast-1"
SERVICE="es"

スナップショット取得に利用するリポジトリ登録コマンド実行:

curl -XPUT "https://VPCドメイン/_snapshot/リポジトリ名定義" \
-H 'Content-Type: application/json' \
-H  "X-Amz-Security-Token: ${AWS_SESSION_TOKEN}" \
--aws-sigv4 "aws:amz:${REGION}:${SERVICE}" \
--user "${AWS_ACCESS_KEY_ID}:${AWS_SECRET_ACCESS_KEY}" \
-d'
{
  "type": "s3",
  "settings": {
    "bucket": "S3登録用バケット",
    "region": "ap-northeast-1",
    "role_arn": "arn:aws:iam::AWSアカウントID:スナップショットリポジトリ登録 Role 作成で作った Role/"
  }
}'

OpenSearch のダッシュボードへアクセスし、 Dev Tools から以下を実行しリポジトリが登録されていることを確認する:

GET /_cat/repositories?v

スナップショット取得

スナップショットを取得するには、次のコマンドを実行します:

PUT /_snapshot/リポジトリ名/任意のスナップショット名

取得したスナップショットを確認するためには、以下のコマンドを使用します:

GET /_snapshot/リポジトリ名/_all

以上でスナップショットの取得が完了です。

では続いてリストア手順について記載します。

取得した手動スナップショットからのリストア

手動スナップショットの取得の流れ

大きな流れとしては以下のような形です。

  • リストアを実行する
  • 想定されるエラーの対処
  • リストアされたインデックス確認

リストア

リストアする:

POST /_snapshot/リポジトリ名/スナップショット名/_restore

同じインデックスがある場合、以下のようなエラーがでる:

{
  "error": {
    "root_cause": [
      {
        "type": "snapshot_restore_exception",
        "reason": "[リポジトリ名:スナップショット名/スナップショットID?] cannot restore index [.[重複するインデックス名] because an open index with same name already exists in the cluster. Either close or delete the existing index or restore the index under a different name by providing a rename pattern and replacement name"
      }
    ],
<略>
  },
  "status": 500
}

このような事象が出る場合、インデックスを削除したりリネームする:

全インデックス削除:

DELETE /_all

個別にインデックス削除:

<br />DELETE /インデックス名:

特定のインデックスをリネームしてリストア:

POST /_snapshot/リポジトリ名/スナップショット名/_restore
{
    "indices": "*",
    "ignore_unavailable": true,
    "include_global_state": false,
    "rename_pattern": "リネーム対象インデックス",
    "rename_replacement": "リネーム後インデックス"
}

再実行しうまくいくと以下のような出力がある:

{
  "accepted" : true
}

リストア状況の確認

リストア状況は以下で確認できる (s列に出てくる内容が status) :

GET _cat/recovery?v=true&h=i,s,t,ty,st,shost,thost,f,fp,b,bp

index 状況を確認する:

GET /_cat/indices?v

以上でリストアが完了です。

別クラスターで復元する場合の補足について、以下記載します。

別クラスター復元に関する補足

  • 別クラスターへの復元をする際には、別クラスターの構築は行っておき、起動までは行う必要がある
    • EC2 や RDS の復元をイメージしているとリストアメニューから行うイメージになるため補足
  • 別クラスター構築後、そのクラスターからもリポジトリが参照できるよう、別クラスターでもリポジトリ登録する必要がある
    • スナップショットを取得した既存クラスターと同じリポジトリを登録することで、リポジトリ内のスナップショットが参照可能になる
  • リポジトリ登録時には作成したスナップショット用の Role のポリシーに別クラスターの記載も必要になる

所感

思ったより調べる中で記事が見つからなかったので纏めてみました。
手動スナップショットは別クラスターへの復元という点や任意のタイミングで取得できることから、行う機会は多いかと思います。
EC2 や RDS のように容易にスナップショットやそれのリストアをコンソールから行えるわけではないので、ちょっとハードルが高いように見えていましたが整理できたかと思います。
別クラスターへ復元する際の内容は細かく記載していませんが、補足部分に記載した内容を加味することで、別クラスターへの復元も複雑ではなく可能と思います。
手動スナップショットの定期実行も含めてバックアップ運用をされる場合は、Lambda で定期実行するなどで可能かと思います。
※その場合、復元手順を準備しておき、別クラスターでのリストアを想定してリポジトリ登録を忘れないようにしましょう

参照にした URL

手動スナップショット作成
https://docs.aws.amazon.com/ja_jp/opensearch-service/latest/developerguide/managedomains-snapshots.html
復元のコマンドを確認した参考ドキュメント
https://opensearch.org/docs/latest/api-reference/snapshots/restore-snapshot/