OpenSearch Service で手動スナップショットを作成してスケジュールする方法を教えてください。
Amazon OpenSearch Service ドメインの手動スナップショットを作成する必要があります。また、定期的にスナップショットを自動的に実行したいと考えています。
簡単な説明
OpenSearch Service ドメインの手動スナップショットを作成するには、スナップショットデータを保存する Amazon Simple Storage Service (Amazon S3) バケットを設定します。S3 バケットをスナップショットのリポジトリとして登録します。最後に、登録されたリポジトリを使用して手動スナップショットを作成します。OpenSearch Dashboards を使用して、登録されたリポジトリのスナップショットを撮ることもできます。
OpenSearch 2.1+ の手動スナップショットを自動的にスケジュールするには、スナップショットポリシーを使用します。以前のバージョンの OpenSearch では、Amazon EventBridge スケジューラで AWS Lambda 関数を使用してください。
解決策
注: AWS コマンドラインインターフェイス (AWS CLI) コマンドの実行中にエラーが発生した場合は、「AWS CLI で発生したエラーのトラブルシューティング」を参照してください。また、AWS CLI の最新バージョンを使用していることを確認してください。
前提条件:
- ご使用のドメインが OpenSearch 1.0+ を実行している。
- ユーザーまたはロールの AWS Identity and Access Management (IAM) ポリシーには、バケットを管理するために必要な CreateBucket 権限と PutBucketPolicy 権限がある。
- ユーザーまたはロールの IAM ポリシーには、IAM ポリシーとロールを作成するために必要な IAMFullAccess 権限がある。
- ユーザーまたはロールの IAM ポリシーには、リポジトリの登録に必要な ESHttpPut 権限があります。
S3 バケットを作成する
次の手順を実行します。
-
OpenSearch サービスドメインと同じ AWS リージョンに新しいバケットを作成します。
-
IAM コンソールまたは AWS CLI を使用して、S3 バケットへのアクセスに必要なアクセス権限を付与する IAM ポリシーを作成します。
ポリシーの例:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetBucketLocation" ], "Resource": [ "arn:aws:s3:::your-bucket-name" ] }, { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject", "iam:PassRole" ], "Resource": [ "arn:aws:s3:::your-bucket-name/*" ] } ] }注: your-bucket-name を実際のバケット名に置き換えます。
-
IAM コンソールまたは AWS CLI を使用して、OpenSearch サービスの IAM ロールを作成します。
次の create-role コマンドの例では、TheSnapshotRole という名前のロールを作成し、そのロールに信頼ポリシーをアタッチします。aws iam create-role --role-name TheSnapshotRole --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "opensearchservice.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }' -
IAM コンソールまたは AWS CLI を使用して、Amazon S3 アクセスポリシーをロールにアタッチします。
-
IAM コンソールまたは AWS CLI を使用して、iam:PassRole アクセス許可を持つポリシーを作成します。
ポリシーの例:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::account-id:role/TheSnapshotRole" }, { "Effect": "Allow", "Action": "es:ESHttpPut", "Resource": "arn:aws:es:region:account-id:domain/domain-name/*" } ] }注: account-id をご自分の AWS アカウント ID に、region をご使用のリージョンに、domain-name を OpenSearch Service のドメイン名に置き換えてください。
-
次の attach-user-policy コマンドを実行して、AWS CLI を使用するように設定した IAM ユーザーに iam:PassRole policy をアタッチします。
aws iam attach-user-policy --user-name YOUR_IAMUSERNAME --policy-arn arn:aws:iam::account-id:policy/PassRolePolicy注: YOUR_IAMUSERNAME をユーザー名に、account-id をご自分のアカウント ID に置き換えてください。
スナップショットリポジトリを登録する
スナップショットリポジトリを登録するには、AWS Signature Version 4 でリクエストに署名する必要があります。リポジトリ名を CS で始めることはできません。また、複数のドメインから同じリポジトリに書き込むことはベストプラクティスではありません。リポジトリへの書き込み権限を持つドメインを 1 つだけ設定します。
Python を使用して Lambda にスナップショットリポジトリを登録します。または、awscurl と AWS CLI を使用してスナップショットリポジトリを登録するには、ご使用のインスタンスで次のコマンドを実行します。
read -r ACCESS_KEY SECRET_KEY SESSION_TOKEN <<< $(aws sts get-session-token --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text) awscurl \ --access_key $ACCESS_KEY \ --secret_key $SECRET_KEY \ --session_token $SESSION_TOKEN \ --region us-west-2 \ --service es \ -X PUT \ -H "Content-Type: application/json" \ 'domain-endpoint/_snapshot/my-snapshot-repo' \ -d '{ "type": "s3", "settings": { "bucket": "bucketname", "region": "us-west-2", "role_arn": "arn:aws:iam::account-id:role/TheSnapshotRole" } }'
注: my-snapshot-repo を実際のリポジトリ名に、bucketname を実際のバケット名に、us-west-2 をご使用のリージョンに置き換えてください。また、domain-endpoint を OpenSearch Service のドメインエンドポイントに、account-id をご自分のアカウント ID に、TheSnapshotRole をご自分のロール名に置き換えてください。
awscurl をインストールするには、次のコマンドを実行します。
pip install awscurl
詳細については、GitHub のウェブサイトで「awscurl」を参照してください。
手動スナップショットを作成する
curl コマンドを使用して、OpenSearch Service ドメインのスナップショットを手動で取得してください。OpenSearch 2.5 以降では、OpenSearch Dashboards を使用できます。手順については、OpenSearch ウェブサイトの「Take a snapshot (スナップショットを撮る)」を参照してください。
スナップショットを作成したら、S3 バケットまたは OpenSearch Dashboards で表示できます。
自動化された手動スナップショットをスケジュールする
OpenSearch 2.1 以降では、API または OpenSearch Dashboards を使用して、登録されたリポジトリでスナップショットポリシーを作成できます。詳細については、OpenSearch ウェブサイトの「Snapshot management API (スナップショット管理 API)」と「Creating an SM policy (SM ポリシーの作成)」を参照してください。
2.1 より前の OpenSearch バージョンでは、以下の手順を実行して手動スナップショットをスケジュールしてください。
- OpenSearch Service ドメインが仮想プライベートクラウド (VPC) にある場合は、同じ VPC で Python 3.13 ランタイムを使用して新しい Lambda 関数を作成します。
- requests-aws4auth を含む AWSSDKPandas-Python313 レイヤーを関数に追加します。詳細については、AWS SDK for pandas ウェブサイトの「AWS Lambda managed layers (AWS Lambda マネージドレイヤー)」と Python ウェブサイトの「requests-aws4auth」を参照してください。
- Lambda 関数に次のコードを入力します。
注: domain-endpoint は実際のドメインエンドポイントに置き換えてください。ただし、https:// は含めないでください。また、my-snapshot-repo をご使用のスナップショットリポジトリに、us-west-2 をご使用のリージョンに置き換えてください。import json import boto3 import requests from requests_aws4auth import AWS4Auth from datetime import datetime def lambda_handler(event, context): # OpenSearch endpoint and repository details host = 'domain-endpoint' repository = 'my-snapshot-repo' snapshot = f"snapshot-{datetime.now().strftime('%Y%m%d%H%m%S')}" region = 'us-west-2' service = 'es' # Get AWS credentials credentials = boto3.Session().get_credentials() awsauth = AWS4Auth( credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token ) # API endpoint for creating snapshot url = f'https://{host}/_snapshot/{repository}/{snapshot}' # Snapshot creation parameters payload = { "indices": "*", "ignore_unavailable": True, "include_global_state": False } try: # Make the request response = requests.put( url, auth=awsauth, json=payload, headers={"Content-nt-Type": "application/json"} ) # Check if request was successful if response.status_code == 200: return { 'statusCode': 200, 'body': json.dumps({ 'message': 'Snapshot creation initiated successfully', 'snapshot_name': snapshot, 'response': response.json() }) } else: return { 'statusCode': response.status_code, 'body': json.dumps({ 'message': 'Failed to create snapshot', 'error': response.text }) } except Exception as e: return { 'statusCode': 500, 'body': json.dumps({ 'message': 'Error creating snapshot', 'error': str(e) }) } - Lambda 関数にアタッチされているロールに次の権限をアタッチします。
注: region ご使用のリージョンに、account-id をご自分のアカウント ID に、my-snapshot-repo を実際のリポジトリ名に、domain-name を実際のドメイン名に置き換えてください。{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "es:ESHttpPut", "es:DescribeElasticsearchDomain" ], "Resource": "arn:aws:es:region:account-id:domain/domain-name/*" } ] } - EventBridge スケジューラを使用して、スケジュールに従って Lambda 関数を呼び出します。
(オプション) 不要なスナップショットを削除する
スナップショットポリシーで作成される手動スナップショットの場合は、max_age パラメータまたは Retention period を使用して有効期限を設定します。詳細と手順については、OpenSearch ウェブサイトの「Parameters (パラメータ)」と「Creating an SM policy (SM ポリシーの作成)」を参照してください。
Lambda 関数が手動スナップショットを作成した場合、有効期限オプションを設定することはできません。代わりに、別の Lambda 関数を使用して OpenSearch スナップショットを削除してください。
次の Lambda 関数は、30 日以上経過した OpenSearch スナップショットを削除します。
import json import boto3 import requests from requests_aws4auth import AWS4Auth from datetime import datetime, timedelta import re def parse_date_from_snapshot_name(snapshot_name): # Pattern for format: snapshot-YYYY-MM-DDtHH-MM-SS try: # Skip "snapshot-" prefix and parse the date part date_str = snapshot_name[9:] # Remove "snapshot-" return datetime.strptime(date_str, '%Y-%m-%dt%H-%M-%S') except (ValueError, IndexError): return None def lambda_handler(event, context): # OpenSearch endpoint and repository details host = 'domain-endpoint' repository = 'my-snapshot-repo' region = 'us-west-2' service = 'es' # Get AWS credentials credentials = boto3.Session().get_credentials() awsauth = AWS4Auth( credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token ) try: # First, get all snapshots list_url = f'https://{host}/_snapshot/{repository}/_all' list_response = requests.get( list_url, auth=awsauth, headers={"Content-Type": "application/json"} ) if list_response.status_code != 200: raise Exception(f"Failed to list snapshots: {list_response.text}") response_data = list_response.json() snapshots = response_data.get('snapshots', []) current_time = datetime.now() deletion_results = [] # Process each snapshot for snapshot in snapshots: snapshot_name = snapshot.get('snapshot') try: snapshot_date = parse_date_from_snapshot_name(snapshot_name) if snapshot_date and (current_time - snapshot_date).days > 30: # Delete snapshot delete_url = f'https://{host}/_snapshot/{repository}/{snapshot_name}' delete_response = requests.delete( delete_url, auth=awsauth, headers={"Content-Type": "application/json"} ) deletion_results.append({ 'snapshot': snapshot_name, 'status': 'deleted' if delete_response.status_code == 200 else 'failed', 'response': delete_response.text }) else: deletion_results.append({ 'snapshot': snapshot_name, 'status': 'skipped', 'reason': 'Not older than 30 days or date not found in name' }) except Exception as e: deletion_results.append({ 'snapshot': snapshot_name, 'status': 'error', 'error': str(e) }) return { 'statusCode': 200, 'body': json.dumps({ 'message': 'Snapshot deletion process completed', 'results': deletion_results }) } except Exception as e: return { 'statusCode': 500, 'body': json.dumps({ 'message': 'Error in snapshot deletion process', 'error': str(e) }) }
注: domain-endpoint を実際のドメインエンドポイント (https:// は付けない) に、region をご使用のリージョンに、my-snapshot-repo を実際のリポジトリ名に置き換えます。Lambda 関数のタイムアウトを 60 秒に設定することをお勧めします。
問題のトラブルシューティング
発生したエラーに基づいて、次のアクションを実行します。
"No permissions for [cluster:admin/snapshot/create]" エラー
OpenSearch Service ドメインに対してきめ細かなアクセス制御を有効にした場合は、OpenSearch Service に Lambda 関数ロールへのアクセス権を付与する必要があります。アクセスを許可しない場合、次の権限エラーが発生します。
""statusCode": 403, "body": "{"message": "Failed to create snapshot", "error": "{\"error\":{\"root_cause\":[{\"type\":\"security_exception\",\"reason\":\"no permissions for [cluster:admin/snapshot/create] and User [name=arn:aws:iam::123456789012:role/service-role/Lambda_ES_Snapshot-role"
この問題を解決するには、以下のコマンドを実行して OpenSearch Service に Lambda 関数ロールへのアクセス権を付与します。
awscurl \ --access_key ABCDE \ --secret_key EXAMPLESECRET\ --region us-west-2 \ --service es \ -X PUT \ -H "Content-Type: application/json" \ 'https://domain-endpoint/_plugins/_security/api/rolesmapping/all_access' \ -d '{"backend_roles": ["arn:aws:iam::account-id:role/service-role/Lambda_AOS_Snapshot-role"], "hosts": [], "users": ["master-user", "arn:aws:iam::account-id:user/second-primary-user" ]}'
注: ABCDE を実際のアクセスキーに、EXAMPLESECRET を実際のシークレットに、us-west-2 をご使用のリージョンに置き換えてください。また、domain-endpoint を OpenSearch Service のドメインエンドポイントに、account-id をご自分のアカウント ID に、Lambda_AOS_Snapshot-role を実際の Lambda 関数ロール名に置き換えてください。
"AccessDeniedException" エラー
"AccessDeniedException" エラーメッセージが表示された場合は、S3 バケットにアクセスする IAM ロールの信頼関係を設定する必要があります。この問題をトラブルシューティングするには、IAM ポリシーシミュレーターを使用して、IAM ポリシーのどの部分を更新する必要があるかを特定します。
"S3Exception" エラー
"S3Exception: The bucket is in region 'us-west-1'" というエラーメッセージが表示されたら、バケットを OpenSearch Service ドメインと同じリージョンに移動する必要があります。
"SignatureDoesNotMatch" エラー
"SignatureDoesNotMatch" というエラーメッセージが表示される場合は、AWS 認証情報の有効期限が切れているか、署名に誤った情報が使用されています。AWS 認証情報を最新の状態に保ち、署名のリージョンが正しいことを確認してください。
"not authorized to perform: iam:PassRole" エラー
AWS Signature Version 4 を使用しない場合、次のエラーメッセージが発生します。
"Message":"User: anonymous is not authorized to perform: iam:PassRole on resource: arn:aws:iam::account-id:role/TheSnapshotRole because no resource-based policy allows the iam:PassRole action"
このエラーのトラブルシューティングについては、「OpenSearch Service クラスターにアクセスしようとすると、"User: anonymous is not authorized" というエラーが発生する原因を教えてください」を参照してください。
トラブルシューティングの詳細については、「OpenSearch Service クラスターの手動スナップショットエラーを解決するにはどうすればいいですか?」を参照してください。
関連情報
別の AWS アカウントにある OpenSearch Service ドメインからデータを復元する方法を教えてください。
