背景
S3にbucket/log/20201101
のようにdailyでログデータを保存しており、一定期間がたったログについてはS3からGlacierに移していましたが、Glacierのログデータが数ヶ月分必要になり、それを復元する必要がありました。
検討したこと
-
S3 Glacierアーカイブをフォルダごと復元 - Qiita
- インストールが割と大変で今回はこのツールは使いませんでした。
-
まとめてGlacierからS3に戻すためのワンライナー - Qiita
- データ量が少なければワンライナーでも良いと思うのですが、今回の数ヶ月分のデータの場合1日復元するのに1時間かかっていました。(非同期のオプション等があれば違うかもしれないです。)
対応
S3の大量のオブジェクトに対して復元という一つの操作をするということで、S3 batch operationsを使うことにしました。
S3 batch operationsは大きく以下のようなステップで実行さます。
- manifestファイルの作成
- manifestファイルのアップロード
- ジョブの作成
- ジョブの実行
manifest ファイルの作成
- manifestファイルは
bucket, object_key
の形式で記載します。ここではバケットと復元したいログデータオブジェクトのkeyを記載したCSVを作成します。 - 作成したファイルをS3にアップロードしてください。
target_date_range = Date.parse(config['START_DATE'])..Date.parse(config['END_DATE'])
target_date_range.each do |date|
# 復元対象のログデータが保存されているディレクトリのオブジェクト一覧を取得します
s3_objects = s3_list_object_content(config['BUCKET'], "#{config['S3_KEY']}/#{date.strftime('%Y%m%d')}")
# 取得したオブジェクト一覧をCSV形式でmanifestファイルにします
s3_objects.each do |object|
CSV.open(file_name, 'a') { |f| f << [config['BUCKET'], object.key] }
end
end
ジョブの作成
-
confirmation_required: false
を指定することでジョブの作成と同時に実行を行います。true
にするとジョブが作成され、実行は別途行う必要があります。 - reportに指定bucketにジョブの結果が出力されます。復元に失敗したものなどがあればここに表示されます。
job_id = Aws::S3Control::Client.new.create_job(
account_id: config['AWS_ACCOUNT_ID'],
confirmation_required: false,
operation: {
s3_initiate_restore_object: {
expiration_in_days: 10,
glacier_job_tier: config['GLACIER_JOB_TIER'],
},
},
report: {
bucket: "arn:aws:s3:::#{config['MANIFEST_BUCKET']}",
format: 'Report_CSV_20180820',
enabled: true,
prefix: 'report',
report_scope: 'AllTasks',
},
client_request_token: SecureRandom.uuid,
manifest: {
spec: {
format: 'S3BatchOperations_CSV_20180820',
fields: ['Bucket', 'Key'],
},
location: {
object_arn: "#{manifest_bucket_arn}/#{manifes_file_name}",
etag: etag,
},
},
description: 'restore',
priority: 10,
role_arn: config['ROLE_ARN'],
tags: config['TAGS'],
)
puts job_id
その他
- S3 batch operationsはジョブ単位で課金されるので、ジョブの分割には注意しましょう。
- 最終的に作成したスクリプトは https://github.com/akiraisomura/s3_utils に置いてあります。