はじめに

こんにちは、広島からリモートワークしている廣田(@hiropon1839)です。

みなさん、リストア訓練していますか?
バックアップを取得していても有事の際にそのバックアップから業務を継続できなくては意味がありません。
ということで、以前「個人データ保管のコスト削減策(S3 Glacier Deep Archive)とaws s3 syncコマンドの高速化」でS3 Glacier Deep Archiveに保管したデータをローカルPCへダウンロード(リストア)してみました。

※当ブログ記事での「個人データ」とは、仕事・業務に関連するデータではなく、完全にプライベートで利用する私的データ(写真等)を指します。

※S3への保管/S3からのダウンロードに際して、当ブログを参考にされたことによるデータ損失等には一切責任を負えません。利用者様の責任の範囲で実行してください。

S3 Glacier Deep Archiveへの保管に関しては、「個人データ保管のコスト削減策(S3 Glacier Deep Archive)とaws s3 syncコマンドの高速化をご参照ください。

目次

S3 Glacier Deep Archiveのファイルをローカルにダウンロードするまでの流れ
復元リクエスト(ファイル数が少ない場合)
復元リクエスト(ファイル数が多い場合)
S3バッチオペレーションとは
S3バッチオペレーション マニフェストファイルの作成
ジョブの作成
ジョブの実行
S3からのダウンロード
かかった料金
さいごに

S3 Glacier Deep Archiveのファイルをローカルにダウンロードするまでの流れ

復元リクエスト→復元完了→ダウンロードという流れとなり、ファイル数が多い場合はS3バッチオペレーションやAWS CLIの利用が必要となります。

1.復元リクエスト
ファイル数が少ない場合:AWSコンソールから手動で復元リクエスト
ファイル数が多い場合:S3バッチオペレーションを利用して復元リクエスト

2.復元完了

3.ダウンロード
ファイル数が少ない場合:AWSコンソールから手動でダウンロード
ファイル数が多い場合:AWS CLIを利用してコマンドでダウンロード

復元リクエスト(ファイル数が少ない場合)

2ファイルのみを復元してみます。
対象オブジェクトのディレクトリへ遷移し、対象オブジェクトを選択し、「復元を開始」をクリックします。

「復元されたコピーが利用可能な日数」を今回は「3」として設定してみます。
「取得階層」を「一括取得」とします。

今回の復元リクエストから48時間以内にファイルが復元され、復元されてから3日間、通常のS3スタンダードクラスに一時的にファイルが保存されます。
この3日間であれば、通常のS3のようにファイルダウンロードが可能となります。
「指定されたオブジェクト」が正しいことを確認し、「復元を開始」をクリックします。

復元が開始されます。

対象のオブジェクトへ遷移すると、「復元ステータス」が「進行中」となっています。

48時間以内に、「復元ステータス」が「完了済み」になります。
「完了済み」になったら「復元の有効期限」までの間、通常のS3オブジェクトと同様にダウンロードが可能です。

復元リクエスト(ファイル数が多い場合)

ローカルデータ完全消失を想定して、全ファイル(90,646個)を復元します。

「復元リクエスト(ファイル数が少ない場合)」のようにAWSコンソールから1ファイルずつ選択することは現実的ではないため、「バッチオペレーション」を利用します。

S3バッチオペレーションとは

S3 バッチオペレーションは Amazon S3 のデータ管理機能です。Amazon S3 マネジメントコンソールからの数回クリックにより、または単一の API リクエストによって、数十億個ものオブジェクトを大規模に管理できます。この機能を使用して、オブジェクトメタデータとプロパティの変更や、その他のストレージ管理タスク (オブジェクトのバケット間でのコピーまたはレプリケート、オブジェクトタグセットの置き換え、アクセスコントロールの変更、S3 Glacier からのアーカイブオブジェクトの復元など) を実行できます。
Amazon S3 バッチオペレーション(https://aws.amazon.com/jp/s3/features/batch-operations/)より引用し抜粋

S3バッチオペレーション マニフェストファイルの作成

S3バッチオペレーションを利用するためには、マニフェストファイルが必要です。
マニフェストファイルとは、処理対象のオブジェクトリストを指定するファイルのことです。
今回はcsvファイルを作成します。マニフェストファイルの形式は下記です。

バケット名,オブジェクト1フルパス
バケット名,オブジェクト2フルパス
バケット名,オブジェクト3フルパス
・
・

1オブジェクトずつ指定が必要なため、90,646-2=90,644行(2ファイルは手動で復元済のため)のcsvファイルを作成します。
csvファイル作成例は下記です。
例では対象S3バケット名を「test_bucket_name」としています。適宜ご自身のS3バケット名に読み替えてください。
aws s3 ls s3://test_bucket_name --recursive > object_list.txt
というような形でオブジェクトの一覧を取得します。
この時取得されるobject_list.txtファイルの形式は下記です。

2024-02-18 13:41:52 2807606 01.Hirota_All_Pictures/2010年/2010年12月/2010_001.jpg
2024-02-18 13:41:52 2114337 01.Hirota_All_Pictures/2010年/2010年12月/2010_002.jpg
2024-02-18 13:41:49 1512935 01.Hirota_All_Pictures/2010年/2010年12月/2010_003.jpg
2024-02-18 13:41:49 1909169 01.Hirota_All_Pictures/2010年/2010年12月/2010_004.jpg
2024-02-18 13:41:52 3121012 01.Hirota_All_Pictures/2010年/2010年12月/2010_005.jpg

下記のようなconvert.pyを作成し、マニフェストファイルの形式にします。

import csv

bucket_name = 'test_bucket_name'
input_file = 'object_list.txt'
output_file = 'manifest.csv'

with open(input_file, 'r', encoding='utf-8') as infile, open(output_file, 'w', newline='', encoding='utf-8') as outfile:
    writer = csv.writer(outfile)

    for line in infile:
        parts = line.split(maxsplit=3)
        key = parts[3].strip()
        if not key.endswith('/'):
            writer.writerow([bucket_name, key])

作成されたmanifest.csvの形式

test_bucket_name,01.Hirota_All_Pictures/2010年/2010年12月/2010_001.jpg
test_bucket_name,01.Hirota_All_Pictures/2010年/2010年12月/2010_002.jpg
test_bucket_name,01.Hirota_All_Pictures/2010年/2010年12月/2010_003.jpg
test_bucket_name,01.Hirota_All_Pictures/2010年/2010年12月/2010_004.jpg
test_bucket_name,01.Hirota_All_Pictures/2010年/2010年12月/2010_005.jpg

manifest.csvの行数と復元したいオブジェクト数が一致していることを確認します。
※「2010_001.jpg」「2010_002.jpg」は手動で復元済のため、この後2行を削除し、90,644行にします。

S3にマニフェストファイルをアップロードします。aws s3 cpコマンドでコピーします。

ジョブの作成

S3 -> バッチオペレーションに遷移し、「ジョブの作成」をクリックします。

AWSリージョンがS3バケットと同じリージョンであることを確認します。

マニフェスト形式は「CSV」を選択し、先程アップロードしたマニフェストオブジェクトを指定します。

オペレーションタイプは「復元」を選択します。

「ソースを復元」で「Glacier Flexible Retrieval または Glacier Deep Archive」を選択します。
「復元されたコピーが利用可能な日数」に指定した期間、通常のS3スタンダードクラスに一時的にファイルが保存され、期間中であれば通常のS3のようにファイルダウンロードが可能です。

ファイル数が多ければ多いほどダウンロードに時間がかかるため、日数は多めに設定したほうが良いです。
※指定した日数分S3スタンダードクラスのストレージ利用料金が発生します。
(今回は事情(AWSクレジットの有効期限の都合)により1日を指定しました。)
「取得階層」を「一括取得」とします。48時間以内に復元が完了します。

追加のオプションとして、「説明」と「優先順位」が指定できます。
「優先順位」は同一AWSアカウント内の他バッチオペレーションとの優先順位付けとなるため、他バッチオペレーションがなければ特に数値を変更する必要はありません。デフォルトの「10」を指定しました。

完了レポート生成の要否を指定できます。明示的に全ファイルに対して復元リクエストが実行されたこと、また失敗の場合は理由を確認したかったため、下記のように指定しました。

今回は信頼ポリシーに「batchoperations.s3.amazonaws.com」を設定し、ポリシー「AmazonS3FullAccess」を許可したIAMロール「s3role」を作成し、指定しました。
※個人利用環境のためポリシーを厳密に絞っていません。ご利用者様の環境に合わせてポリシーは変更してください。

設定内容を確認し、「ジョブの作成」をクリックします。

ステータスが「実行のための確認待ち」になります。

ジョブの実行

ジョブIDにチェックを入れ、「ジョブを実行」をクリックします。

再度内容を確認し、「ジョブを実行」をクリックします。 

ステータスが、「準備ができています」→「アクティブ」→「もうすぐ完了します」→「完了済み」に遷移しました。

「失敗した合計」が「30」ありました。
完了レポートを確認すると、「NoSuchKey」というエラーが出力していました。
失敗したファイルは、すべてファイル名に「+」記号と「 」(半角スペース)が混在していました。
「+」記号と「 」(半角スペース)の混在により、S3バッチオペレーションが正しくファイル名が取得できなかったと考えられます。
今回は深追いせず、成功した90,614ファイル+2ファイル(手動復元済)=90,616ファイルをダウンロード対象とします。

S3からのダウンロード

S3バッチオペレーションが完了してから約48時間後にダウンロードを開始します。
下記のように、各ファイルの「復元ステータス」が「完了済み」になります。

ファイル数が多いため、AWS CLIを利用してダウンロードします。
また、s3 syncコマンドを高速化するために、前回の記事個人データ保管のコスト削減策(S3 Glacier Deep Archive)とaws s3 syncコマンドの高速化」でチューニングした「max_concurrent_requests」の値(150)を今回もそのまま利用します。

当記事を参考に実際にS3からのダウンロードを実施される際は、前回記事をご参考に各自の環境に合わせた値にチューニングしてご利用ください。

下記コマンドで「max_concurrent_requests」を設定、設定値確認、S3からのダウンロードを実行します。
Windowsの場合、PowerShellで下記コマンドを実行します。

aws configure set default.s3.max_concurrent_requests 150
aws configure get default.s3.max_concurrent_requests
aws s3 sync s3://(バケット名)/(ダウンロード元ディレクトリ)/ (ダウンロード先ディレクトリ) --force-glacier-transfer




概ね13MiB/s~17MiB/sの範囲でダウンロードされており、15時間程度で総容量849GB、総ファイル数90,616個のダウンロードが完了しました。

ダウンロード完了後、S3バッチオペレーションでエラーとなっていた30ファイルを除いて「S3 Glacier Deep Archiveへの保管前のディレクトリ」と「今回ダウンロードしたディレクトリ」でファイル数が一致していることが確認できました。
無事にリストアできました!

S3 Glacier Deep Archiveへの保管前のディレクトリ:63,199ファイル+27,447ファイル=90,646ファイル
今回ダウンロードしたディレクトリ:63,199ファイル+27,417=90,616ファイル
失敗した30ファイルをプラスすると、90,616ファイル+30ファイル=90,646ファイルとなり、S3 Glacier Deep Archiveに保管しているファイル数と一致します。

かかった料金

今回はS3バッチオペレーションも利用したため、PCにデータをダウンロードするまでに発生する費用の項目は下記5項目です。
・データ取り出しリクエスト(大容量)料金:0.025USD/1,000リクエスト
・S3バッチオペレーション料金:0.25USD/1ジョブ + 1.00USD/1,000,000オブジェクト
・データ取り出し(大容量)料金:0.0025USD/GB
・S3スタンダードクラスでの一時保管料金:0.023USD/GB
・データ転送料金(S3からインターネットへのアウトバウンド通信):0.09USD/GB

請求書を確認してみましょう。
※ほとんどが今回のダウンロードに関する料金ですが、一部他料金も表示に含まれています。


「$0.025 per 1,000 Bulk requests to Glacier Deep Archive」
データ取り出しリクエスト(大容量)料金です。
S3バッチオペレーションを通して、90,616ファイルのデータ取り出しリクエストを実行しました。
90,616ファイル÷1000×0.025USD=約2.27USD


「$0.25 per job fee for Batch Operations」
S3バッチオペレーション1ジョブあたりの料金です。2 Jobsとなっていますが、1回はテストのため、今回のデータ取り出しリクエストで利用したジョブは1ジョブとなります。
1ジョブ×0.25USD=0.25USD

「$1.00 per 1 million object operations performed by Batch Operations」
処理された 100 万オブジェクトあたりの料金です。
90,644オブジェクト÷1,000,000×1.00USD=約0.09USD

S3バッチオペレーション全体としては、
0.25USD+約0.09USD=約0.34USD
となります。


「$0.0025 per GB Bulk retrieval fee from Glacier Deep Archive」
データ取り出し(大容量)料金です。
849.31GB×0.0025USD=約2.12USD


「Amazon Simple Storage Service TimedStorage-ByteHrs $0.023 per GB」
S3スタンダードへの保存に対するストレージ利用料金です。Glacier Deep Archiveクラスから一時的にスタンダードクラスへコピーしたファイルに対する課金です。約850GBを1日間保管したため、850GB÷30日間=約28GB-Moとなります。
28.093GB×0.023USD=約0.65USD


「$0.090 per GB data transfer out beyond the global free tier」
S3からインターネットに転送されたデータ転送料金です。
752.438GBとなっていますが、無料枠の100GBはS3以外のサービスと共通のため、無料枠から外して計算します。
$0.090USD×約850GB=約76.5USD

項目 料金
データ取り出しリクエスト(大容量)料金:0.025USD/1,000リクエスト 約2.27USD
S3バッチオペレーション料金:0.25USD/1ジョブ + 1.00USD/1,000,000オブジェクト 約0.34USD
データ取り出し(大容量)料金:0.0025USD/GB 約2.12USD
S3スタンダードクラスでの一時保管料金:0.023USD/GB 約0.65USD
データ転送料金(S3からインターネットへのアウトバウンド通信):0.09USD/GB 約76.5USD
合計 約82USD

今回のリストア全体で、約82USD約12,000円(@150円)となりました。

さいごに

実際にS3 Glacier Deep Archiveからデータをローカルにリストアすることができました。
1回のリストアに必要な料金について、試算だけでなく実際の請求書で裏付けが取れ、安心できました。
同じような状況でバックアップ・リストアを検討されている方はぜひお試しください。
関連:個人データ保管のコスト削減策(S3 Glacier Deep Archive)とaws s3 syncコマンドの高速化