Amazon Web Services ブログ
AWS Storage Gateway を介してアーカイブしたオブジェクトの復元を自動化する
オンプレミスファイルベースのアプリケーションをお持ちの AWS のお客様には、AWS Storage Gateway をファイルゲートウェイモードでデプロイし、実質的に無制限の Amazon Simple Storage Service (Amazon S3) のストレージにアクセスできる機能を気に入っていただいています。Amazon S3 バケットのコンテンツは、SMB や NFS などの一般的に使用されているストレージプロトコルを通して、ファイルゲートウェイによってファイルとして提示されます。ファイルベースのアクセスを必要とするお客様は、ヘルスケア (イメージングやゲノミクス)、メディアおよびエンターテイメント、金融サービスなどのさまざまな業界にわたります。
コンプライアンスと規制の要件を満たすため、長年にわたり可能な限り低いコストでファイルデータを保存およびアクセスしたいというお客様からのご意見をいただいています。なかでも、Amazon S3 ライフサイクルポリシーを使用して、 Amazon S3 Glacier (S3 Glacier) または Amazon S3 Glacier Deep Archive (S3 Glacier Deep Archive) などの低コストストレージクラスのオブジェクトを自動的に移動したいというご要望を頻繁にいただきます。図 1 をご参照ください 。
ライフサイクルポリシーを設定する前に、2 つのコールドストレージクラスの違いを十分に理解することをお勧めします。これは特に、ストレージコスト、取得時間、取得コストに関係するためです。
図 1: Amazon S3 ライフサイクルポリシーを使用して、Amazon S3 にアップロードされたオブジェクトを S3 Glacier に移動する
これまでは、データが低コストのストレージクラス (S3 Glacier) にアーカイブされると、オブジェクトを Amazon S3 標準 に手動で復元してからファイルゲートウェイを介してアクセスする必要がありました。この度、Amazon CloudWatch や AWS Lambda 関数を使用して復元リクエストをトリガーすることにより、アーカイブファイルを Amazon S3 に復元するこのワークフローを自動化できるようになりました。以下では、AWS Storage Gateway を介した Amazon S3 Glacier オブジェクトの復元の自動化について簡単に説明しているデモ動画をご覧いただけます。
前述のように、ファイルゲートウェイを使用してアーカイブファイルにアクセスするとどうなるか?
例を見てみましょう。Joe は、企業の財務部門に勤務する管理者で、それほどアクティブでないコンテンツを Amazon S3 に移行するプロジェクトを大きく進展させました。最近彼は、ファイルゲートウェイを起動して Amazon S3 バケットに添付すれば、1 つまたは複数のオンプレミスの場所にいるユーザーがクラウドの中央リポジトリにアクセスできることを知りました。ユーザーは最近作成または更新したファイルにアクセスする可能性が高いため、ファイルゲートウェイのローカルキャッシュ (ゲートウェイあたり最大 16 TB) を利用することでメリットを享受できます。同様に、アプリケーションがファイルゲートウェイのファイル共有にデータを書き込む場合、キャッシュのライトバック特性により、最大 500 MiB/s のスループットが得られます (詳細については、「AWS Storage Gateway のパフォーマンス」をご覧ください)。
Joe の財務部門には、データを 7 年間保持し、監査人のアドホックなリクエストを満たすためにアクセスできる必要があるという要件があります。こうした保持要件をコスト効率よく満たすために、Joe は Amazon S3 バケットにポリシーを設定し、30 日より古いオブジェクトを S3 Glacier Deep Archive に移動しました。ユーザーが 30 日より前のデータに定期的にアクセスする可能性は非常に低いことを知っているため、長い検索時間とそれに関連する検索コストのトレードオフは許容できます。
次に、Joe のユーザーがファイルゲートウェイのファイル共有を介してデータにアクセスするとどうなるかを見てみましょう。 3 つのシナリオがあります。
1.オブジェクトは既にファイルゲートウェイのディスクキャッシュにある
アクセスしたファイルがローカルのファイルゲートウェイディスクキャッシュで利用できる場合 (図 2 を参照)、ファイルゲートウェイはローカルディスクの速度でローカルキャッシュから直ちにデータを返します。これはユーザーにとって理想的です。
図 2: ローカルディスク速度でローカルキャッシュからファイルが返される
2.オブジェクトは Amazon S3 の「オンライン」ストレージクラスにあり、ファイルゲートウェイのキャッシュから削除されている
Joe のユーザーの 1 人が、ローカルのファイルゲートウェイのキャッシュにはないファイルにアクセスしようとしています。そのファイルは作成されて 30 日未満のものです (Joe には 30 日間のライフサイクルポリシーがあります)。彼のファイルはデフォルトの Amazon S3 ストレージクラス (この場合は Amazon S3 標準) から入手できます (図 3 をご参照ください)。
ファイルゲートウェイは、ファイルを表すオブジェクトを Amazon S3 から要求し、ファイルゲートウェイのローカルディスクキャッシュにダウンロードして、ユーザーに返します。ファイルは、新しいデータ用のスペースを作るために削除されるまで、ローカルキャッシュに残ります。キャッシングのしくみの詳細については、こちらの AWS re:Invent 2018 ディープダイブの動画をご覧ください。
図 3: ローカルのファイルゲートウェイキャッシュにないが 30日未満のファイルに Amazon S3 標準からアクセスする
3.オブジェクトが Amazon S3 コールドストレージクラスにある
Joe のユーザーの 1 人が、古いファイルにアクセスしようとしています。今回の場合、ファイルは S3 Glacier ストレージクラスにあるため、そのファイルを S3 ストレージクラスに復元せずに直接アクセスすることはできません (図 4 をご参照ください)。
最近まで、ファイルゲートウェイがファイルを表す S3 オブジェクトにアクセスしようとしてオブジェクトが直接利用できなかった場合、プロセスは失敗し、ユーザーは IO エラーを受け取っていました。Joe はこのエラーの原因を認識して、手動で取りかかることにし、ユーザーにオブジェクトを「復元」するよう要求していました。これでは、最適なユーザーエクスペリエンスとはいえません。
図 4: 初めに S3 ストレージクラスに復元せず、S3 Glacier ストレージクラスにある古いファイルにアクセスしようとしたときの IO エラー
CloudWatch Logs でこのエラーがどのように見えるかを、次に示します。
{
"severity": "ERROR",
"bucket": "mybucket",
"roleArn": "arn:aws:iam::123456789101:role/sts-test",
"source": "share-E1B9B18A",
"type": "InaccessibleStorageClass",
"operation": "S3UploadFailure",
"key": "myfile.txt",
"gateway": "sgw-B8D938D1",
"timestamp": "1565740862516"
}
では、手動でのワークフローへの介入を最小限にして、Joe と彼のユーザーがこのストレージクラスにあるファイルに簡単にアクセスできるようにするには、どうすればよいでしょうか? ファイルゲートウェイでは、Amazon CloudWatch Logs を使用して、エンドユーザーがコールドストレージクラスにアーカイブされたファイルにアクセスしたとき、Joe に通知できるようになりました。Joe は復元ワークフローに自動化を組み込むことができるようになり、喜んでいます。
エラーメッセージ「"type": "InaccessibleStorageClass"
」に基づいて、Joe がアクセスしようとしているオブジェクトを特定できます。"key":"myfile.txt"
("bucket":"mybucket"
内) が「オフライン」ストレージクラスに移動していることが分かります。このエラーは現在 CloudWatch Logs に書き込まれているため、Lambda 関数をログストリームに添付して、このエラーメッセージを処理し、アクションを実行できます。
- 注: このエラーは、オブジェクトがファイルゲートウェイの起動時 (またはキャッシュの更新後) に既にアクセスできないストレージクラスにあった場合、またはライフサイクルを使用してオブジェクトを移行した場合にのみ生成されます。コンソールからオブジェクトを手動で移行すると、別のエラーが生成されます。
ここでは、AWS Lambda 関数がオブジェクトのリコールリクエストを自動的に開始する方法を示します。リコールが完了すると、Joe と彼のユーザーに、Amazon Simple Notification Service (SNS) というサブスクライブが可能なトピックを介してメッセージを送信できます (図 5 をご参照ください)。オブジェクトを復元した後にユーザーがファイルに再度アクセスしようとすると、ファイルゲートウェイを介してアクセスできます。
AWS のお客様は、Amazon S3 Glacier のデータ取得料金を確認し、ファイルの自動取得がコストに与える影響を理解しておきましょう。Amazon S3 Glacier からファイルを頻繁に取得するとコストが増加しますので、自動化のメリットと比較し検討する必要があります。さらに、Amazon S3 Glacier と Amazon S3 Glacier Deep Archive の取得時間の違いを確認し、考慮する必要もあります。 |
図 5: Amazon CloudWatch がトリガーした AWS Lambda 関数
ステップ 1: ファイルゲートウェイの CloudWatch Logs グループをセットアップする
- ファイルゲートウェイをまだ実行していない場合は、こちらの手順に従って新しいゲートウェイを起動します。
- ロギングの設定ステップに来たら、[Create New Log Group] をクリックします。これで、CloudWatch Logs コンソールに移動する
- [Actions]、[Create New Log Group ] の順でクリックする
- ロググループに myFGWLogGroup などの名前を付ける
- ファイルゲートウェイコンソールに戻り、更新を [LogGroup] ドロップダウンで行う
- 新しいロググループを選択して、ファイルゲートウェイのセットアップの残りを完了する
ステップ 2: AWS Lambda の実行ロールを作成する
AWS Lambda 関数が実行時に適用する IAM ロールを作成する必要があります。Lambda 関数は S3 API を呼び出してオブジェクトのリコールを要求するため、通常の Lambda 基本実行ロール上にはこれらのアクセス許可が必要です。
- AWS Identity and Access Management (IAM) コンソールに移動し、[Roles] をクリックする
- [Create role] をクリックする
- [Lambda] を選択し、[Next: Permissions] をクリックする
- テストを行う AmazonS3FullAccess などの AWS 管理ポリシーのいずれかをこちらで選択するか、[Create Policy] オプションをクリックして、独自の最小権限ポリシーを作成する (推奨) こともできます。独自のポリシーを作成する場合、関連するリソースに対して「RestoreObject」アクションを許可する必要があります。
- 上記の Amazon S3 ポリシーに加えて、Lambda が通常どおり動作して CloudWatch Logs ストリームを生成できるように、 AWSLambdaBasicExecutionRole も添付する
- 自分で作成したポリシーを選択し、[Next: Tags] をクリックする
- オプションのタグをロールに追加する。ない場合は、[Next: Review] をクリックする
- ロール名を指定し、後で使用するためにメモして (myLambdaS3RestoreRole など)、[Create Role] をクリックする
ステップ 3: AWS Lambda 関数を作成する
次に、オブジェクトの復元を開始する Lambda 関数を作成する必要があります。
- AWS Lambda コンソールに移動する
- [Create function] をクリックする
- [Author from scratch] を選択する
- 名前を選択する (FGWGlacierRestore など)
- ランタイムに Python 2.7 を選択する
- [choose an execution role]、[Use an existing role] の順で展開する ステップ 2 で作成したロールを選択する
- [Create function] をクリックする
- [Function Code] ウィンドウペインまでスクロールし、エディタのコードを次のコードに置き換える
import os
import json
import boto3
import base64
import gzip
from botocore.exceptions import ClientError
from StringIO import StringIO
def lambda_handler(event, context):
cw_data = str(event['awslogs']['data'])
cw_logs = gzip.GzipFile(fileobj=StringIO(cw_data.decode('base64', 'strict'))).read()
log_events = json.loads(cw_logs)
for log_entry in log_events['logEvents']:
result = process_recall(log_entry)
print (result)
return {
'statusCode': 200,
'body': result
}
def process_recall(log_entry):
print ("message contents: " + log_entry['message'])
message_json = json.loads(log_entry['message'])
print (message_json)
if 'type' in message_json:
print ("Found ErrorType")
error_type = message_json['type']
print ("ErrorType = " + error_type)
if message_json['type'] != "InaccessibleStorageClass":
return "Unexpected error: not related to storage class"
else:
return_error = "error: no type entry"
return return_error
if 'bucket' in message_json:
print ("Found Bucket")
s3_bucket = message_json['bucket']
print ("Bucket = " + s3_bucket)
else:
return_error = "error: no bucket"
return return_error
if 'key' in message_json:
print ("Found Key")
s3_key = message_json['key']
print ("Key = " + s3_key)
else:
return_error = "error: no key"
return return_error
s3 = boto3.resource('s3')
s3_object = s3.Object(s3_bucket, s3_key)
try:
restore_days = int(os.environ['RestoreDays'])
result = s3_object.restore_object(RestoreRequest={'Days':restore_days,'GlacierJobParameters': {'Tier': os.environ['RecallTier']}})
except ClientError as e:
if e.response['Error']['Code'] == 'RestoreAlreadyInProgress':
return e.response['Error']['Code']
else:
return_error = "Unexpected Error whilst attempting to recall object"
return return_error
print (result)
return result
- 環境変数セクションまでスクロールして、以下のキーと値のペアに従い、2 つの環境変数を作成する
- Key = RecallTier | Value = “Expedited” or “Standard”
- この値は、S3 Glacier の復元レベルを指定するために使用
- Key = RestoreDays | Value = Integer
- この値は、復元されたオブジェクトが数日間一時的に利用可能にする期間を定義するために使用 (たとえば、1 など)
- Key = RecallTier | Value = “Expedited” or “Standard”
- 画面の上部で [Save] をクリックする
ステップ 4: CloudWatch Logs を Lambda 関数に接続する
最後に、CloudWatch Logs グループを Lambda 関数に接続して、ファイルゲートウェイログを処理できるようにする必要があります。
- コンソールでステップ 3 の Lambda 関数を開く
- [Designer] で [Add trigger] をクリックする
- トリガー設定で [CloudWatch Logs] を選択する
- [Log Group]フィールドで、ステップ 1 で作成したロググループを選択する (myFGWLogGroup など)
- [Filter name] (FGWLogsFilter など) を追加する
- [Filter pattern ] で、「InaccessibleStorageClass」を追加する
- [Enable Trigger] ボックスがオンとなっていることを確認する
- [Add] をクリックして続行する
ステップ 5: (オプション) Amazon Simple Notification Service (SNS) をセットアップして、復元完了通知を受け取る
Joe がオブジェクトの復元が完了したときに通知を受け取りたい場合、サブスクライブできる SNS トピックを設定できます。
パート A: SNS トピックを作成する
- Amazon Simple Notification Service コンソールを開く
- [Topics] に移動する
- [Create topic] をクリックする
- SNS トピックの名前 (FGWRestoreTopic など) を入力し、[Create topic] をクリックする
- 次に、SNS トピックの設定ウィンドウに移動し、作成した SNS トピックの ARN をコピーする
- 右上隅の [Edit] をクリックする
- Access policy セクションを展開する
次のコードスニペットを挿入し、最後の「]」の上に行を挿入する
注: <your-SNS-Topic-ARN>
および <your-s3-bucket-name>
の値を独自の値に変更します。
{
"Sid": "_s3_events_default_statement_ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "SNS:Publish",
"Resource": "<your-SNS-Topic-ARN>",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:s3::*:<your-s3-bucket-name>"
}
}
}
パート B: SNS トピックにサブスクライブする
- 次に、SNS トピック設定ウィンドウに移動します。[Create Subscription] をクリックする
- [Protocol ] フィールドで [Email] を選択する
- [Endpoint] フィールドに、SNS 通知を受信する有効なメールアドレスを入力する
- 入力したら、[Create Subscription] をクリックする
- E メールの受信トレイで通知を確認し、E メールの確認リンクを承認する
- Amazon S3 コンソールに戻る
- S3 バケットプロパティ (ファイルゲートウェイを介してマッピングされるバケット) を開く
- [Events]、[Add notification] の順でクリックする
- 名前 (FGWRestoreEvents など) を指定し、[Restore completed] をクリックする
- [Send to] フィールドから送信先として SNS トピックを選択し、[SNS] フィールドで先ほど作成したトピック、次に [ Save ] をクリックする
ステップ 6: テストする
- S3 Glacier ストレージクラスにあることが分かっているファイルに (ファイルゲートウェイ共有を介して) アクセスを試みます。
注: ファイルが既にローカルのファイルゲートウェイキャッシュにある場合、ファイルはキャッシュから返され、この新しいワークフローは実行されません。 - 最初の IO エラーが表示される
- CloudWatch コンソールに移動し、左側の列から [Logs] をクリックする
- 以前に作成したファイルゲートウェイロググループを選択する
- [Log Streams] 列の下に、share-xyz123 のようなエントリが表示されます。これはファイルゲートウェイのファイル共有 ID です。そのエントリが表示されない場合がありますが、ロググループがファイルゲートウェイからデータを受信するのに最大 5 分かかることがあることに留意してください。
- ファイルゲートウェイ共有からのログストリームが表示されたら、それをクリックする
- エラーメッセージをクリックして、type:InaccessibleStorageClass を探す。ここでは、アクセスしようとしたファイル (キー) と S3 バケットの詳細も表示できます。
- Lambda コンソールの別のウィンドウを開き、Lambda ロググループで関数を確認し、正常な復元要求 (http 202 応答) を確認する
- SNS 通知を有効にしている場合、S3 Glacier の復元が完了すると、本文に「eventName”:”ObjectRestore:Completed」を含む E メールが送信されます。この時点で、ファイルゲートウェイを介してファイルに再度アクセスできます。
まとめ
Lambda 関数を活用することで、S3 Glacier からファイルの復元を自動化したり、復元処理中に S3 Glacier Deep Archive が手動介入の必要を抑えたりすることが可能となります。この機能は、Joe のような管理者の負担の一部を取り除きますが、すべてのユースケースの復元の問題を解決するものではありません。ユーザーは、このプロセスがニーズに適しているかどうかを判断できるように、ワークフローを理解する必要があります。復元プロセスに時間がかかりすぎると、ファイル共有の書き込みと読み込みを行うアプリケーションでタイムアウトが発生するユースケースがいくつかあります。Lambda 関数が設定されている場合、復元は最終的に行われますが、アプリケーションはタイムアウトするまで十分な時間を待機できない場合があります。一部のアプリケーションではタイムアウトを調整できますが、調整できないアプリケーションもあります。アプリケーションがゲートウェイにデータを出し入れする状況では、ユーザーは機能をテストし、適切に機能するかどうかを確認する必要があります。
ユーザーは S3 Glacier または S3 Glacier Deep Archive から復元されたデータの取得および取得要求コストを考慮してください。これらのストレージクラスはデータの長期アーカイブ用に設計されており、頻繁にアクセスされるデータには推奨しません。ユーザーは、データを Amazon S3 Glacier と Amazon S3 Glacier Deep Archive のどちらに保存するかを慎重に検討する必要があります。また、これらのストレージクラスからデータを復元するために頻繁にリクエストする際のコストの影響も考慮する必要があります。
ファイルゲートウェイモードの Amazon Storage Gateway、Amazon Tape Gateway、Lambda functions、Simple Notification Services、Amazon S3 Glacier の料金、および AWS Billing and Cost Management についての詳細は、こちらでご覧いただけます。