S3で削除したファイルを復元する方法 — バージョニングが有効な場合の完全ガイド

S3バケットのファイルを誤って削除してしまった — 本番環境でこれが起きると、まず確認するのは「バージョニングを有効にしていたか」という一点だ。バージョニングが有効であれば、S3上の削除は実際にはデータを消去しておらず、削除マーカーと呼ばれるオブジェクトを追加する操作に過ぎない。この仕組みを理解していれば、復元は数分で完了する。

TL;DR — S3削除ファイルの復元手順

ステップ操作目的
1バージョニング有効化を確認復元可能かを判断する
2削除マーカーを特定どのバージョンIDが削除操作かを確認
3削除マーカーを削除直前バージョンを最新として復元
4特定バージョンを直接コピー任意の過去バージョンに戻す場合

S3バージョニングの仕組み — 削除とは何か

バージョニングが有効なバケットでは、オブジェクトに対するすべての書き込みと削除が履歴として保持される。通常のDELETEリクエスト(バージョンIDを指定しない削除)は、オブジェクト本体を消去するのではなく、削除マーカー(Delete Marker)という特殊なバージョンを最新として追加する。GETリクエストはこの削除マーカーを参照して404を返すが、以前のバージョンはストレージ上にそのまま残っている。

一方、バージョンIDを明示したDELETEリクエストは、そのバージョンを完全に消去する。この2つを混同すると復元操作を誤る。削除マーカー自体もバージョンIDを持つオブジェクトであり、これを削除することで直前バージョンが最新に昇格する、というのが復元の基本原理だ。

sequenceDiagram participant Client as クライアント participant S3 as S3 バケット Note over S3: v1 (古いバージョン) Note over S3: v2 (削除前の最新) Client->>S3: DELETE key.txt (バージョンID指定なし) S3-->>S3: 削除マーカー追加 (IsLatest=true) Client->>S3: GET key.txt S3-->>Client: 404 Not Found (削除マーカーが最新) Note over Client: 復元操作 Client->>S3: DELETE key.txt --version-id [削除マーカーID] S3-->>S3: 削除マーカーを除去 Note over S3: v2 が IsLatest=true に復帰 Client->>S3: GET key.txt S3-->>Client: 200 OK (v2 を返す)
  1. バージョニング有効時の通常DELETE: 削除マーカーが最新バージョンとして追加される。過去のバージョンv1、v2はストレージに残存する。
  2. GETリクエスト: 削除マーカーが最新のため、S3は404を返す。
  3. 削除マーカーをDELETE: マーカーが除去され、v2が最新バージョンとして復活する。
  4. バージョンID指定のDELETE: 対象バージョンを完全消去する。この操作は取り消せない。

前提確認 — バージョニングが有効かどうかをチェックする

復元を試みる前に、対象バケットのバージョニング状態を確認する。バージョニングが無効だった場合、削除されたオブジェクトは復元できない。

aws s3api get-bucket-versioning \
  --bucket your-bucket-name

レスポンスに"Status": "Enabled"が含まれていれば復元可能だ。MFADeleteEnabledになっている場合は、削除マーカーの削除にMFAデバイスが必要になる点に注意する。

S3削除ファイルの復元 — ステップバイステップ

ステップ1: 削除マーカーのバージョンIDを特定する

復元対象のオブジェクトキーに対して、すべてのバージョンと削除マーカーを一覧表示する。削除マーカーはIsDeleteMarker: trueとして返される。

aws s3api list-object-versions \
  --bucket your-bucket-name \
  --prefix your/object/key.txt

出力例(抜粋):

{
  "DeleteMarkers": [
    {
      "Key": "your/object/key.txt",
      "VersionId": "abc123XYZ",
      "IsLatest": true,
      "LastModified": "2024-05-10T08:30:00.000Z"
    }
  ],
  "Versions": [
    {
      "Key": "your/object/key.txt",
      "VersionId": "def456ABC",
      "IsLatest": false,
      "LastModified": "2024-05-09T14:00:00.000Z"
    }
  ]
}

IsLatest: trueかつDeleteMarkers配列に含まれているバージョンIDが、削除操作によって追加されたマーカーだ。このIDをメモしておく。

ステップ2: 削除マーカーを削除して直前バージョンを復元する

削除マーカーのバージョンIDを明示してDELETEすることで、マーカーが除去され、直前のバージョンが最新として復活する。これが最も一般的な復元パターンだ。

aws s3api delete-object \
  --bucket your-bucket-name \
  --key your/object/key.txt \
  --version-id abc123XYZ

成功すると、レスポンスにDeleteMarker: trueと削除されたバージョンIDが返される。その後、通常のGETリクエストでオブジェクトにアクセスできることを確認する。

aws s3api head-object \
  --bucket your-bucket-name \
  --key your/object/key.txt

404が返らなければ復元成功だ。

ステップ3(任意): 特定の過去バージョンを復元する

削除マーカーを除去するだけでは不十分な場合、つまり「削除前のバージョンではなく、さらに古いバージョンに戻したい」ときは、対象バージョンを現在のキーにコピーする。これにより、そのバージョンの内容が新しい最新バージョンとして書き込まれる。

aws s3api copy-object \
  --bucket your-bucket-name \
  --copy-source your-bucket-name/your/object/key.txt?versionId=def456ABC \
  --key your/object/key.txt

このコピー操作は新しいバージョンIDを生成する。元のバージョンdef456ABCはそのまま履歴に残る。

複数ファイルを一括復元する場合

特定のプレフィックス配下のすべての削除マーカーを除去したい場合、AWS CLIのみでは一括操作のネイティブサポートがないため、スクリプトで対応する必要がある。以下はBashでの実装例だ。

🔽 一括削除マーカー除去スクリプト(クリックして展開)
#!/bin/bash
BUCKET="your-bucket-name"
PREFIX="your/prefix/"

# 削除マーカーのバージョンIDをすべて取得して削除する
aws s3api list-object-versions \
  --bucket "$BUCKET" \
  --prefix "$PREFIX" \
  --query 'DeleteMarkers[?IsLatest==`true`].[Key, VersionId]' \
  --output text | while read KEY VERSION_ID; do
    echo "削除マーカーを除去: $KEY ($VERSION_ID)"
    aws s3api delete-object \
      --bucket "$BUCKET" \
      --key "$KEY" \
      --version-id "$VERSION_ID"
done

このスクリプトはIsLatesttrueの削除マーカーのみを対象にする。削除マーカーが最新でない(その後に別バージョンが書き込まれた)オブジェクトは対象外になるため、意図しない上書きを防げる。

実際の障害パターン — 誤診断から正しい原因特定へ

あるケースで、バージョニング有効なバケットからファイルが消えたと報告を受けた。list-object-versionsを実行すると削除マーカーが存在し、復元手順を試みた。しかし削除マーカーを除去しても、アプリケーションは依然として404を返し続けた。

最初の誤診断は「削除マーカーの除去が失敗している」というものだった。head-objectでオブジェクト自体は確認できるのに、アプリケーション側だけ404が続く。

実際の原因はCloudFrontのキャッシュだった。CloudFrontが404レスポンスをキャッシュしており、オリジンのS3が復元済みであってもエッジキャッシュが古い404を返し続けていた。aws cloudfront create-invalidationでキャッシュを無効化して初めて正常に解決した。S3側の復元操作は最初から正しく機能していた。

S3の復元確認は必ずS3 APIに直接アクセスして行う。CDNやアプリケーションレイヤーを経由した確認は、キャッシュの影響を受ける。

IAM権限 — 復元操作に必要な最小権限

削除マーカーの除去とバージョン一覧取得には、以下の権限が必要だ。

🔽 最小権限IAMポリシー(クリックして展開)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucketVersions",
        "s3:GetBucketVersioning"
      ],
      "Resource": "arn:aws:s3:::your-bucket-name"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:DeleteObjectVersion",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::your-bucket-name/*"
    }
  ]
}

s3:DeleteObjectVersionは削除マーカーの除去に必要な権限だ。通常のs3:DeleteObjectとは別アクションである点に注意する。バケットポリシーでExplicit Denyが設定されている場合、IAMポリシーでAllowを付与してもアクセスは拒否される。

S3削除ファイルの復元 — 注意すべき動作の詳細

バージョニングを有効にしたタイミングより前にアップロードされたオブジェクトには、バージョンIDとしてnullが割り当てられる。このnullバージョンを誤って削除すると、そのバージョンは完全に消去される。list-object-versionsの出力でVersionIdが"null"と表示されているオブジェクトは、この状態にある。

また、S3 Intelligent-TieringやS3 Glacierなどのストレージクラスに移行されたバージョンを復元する場合、Glacier/Glacier Deep Archiveからの取り出しには別途復元リクエストが必要で、即時アクセスはできない。バージョン一覧のStorageClassフィールドで事前に確認しておくこと。

graph TD A["バージョニング確認
get-bucket-versioning"] --> B{"Status: Enabled?"}; B -- "No" --> C["復元不可
バックアップを確認"]; B -- "Yes" --> D["削除マーカー特定
list-object-versions"]; D --> E{"直前バージョンに
戻せばよい?"}; E -- "Yes" --> F["削除マーカーを削除
delete-object --version-id"]; E -- "No" --> G["特定バージョンをコピー
copy-object --copy-source ...?versionId="]; F --> H["復元確認
head-object"]; G --> H; H --> I{"200 OK?"}; I -- "No" --> J["CDN/アプリキャッシュを確認"]; I -- "Yes" --> K["復元完了"];
  1. バージョニング確認: まずget-bucket-versioningでEnabled状態を確認する。
  2. 削除マーカー特定: list-object-versionsでIsLatestな削除マーカーのVersionIdを取得する。
  3. 直前バージョン復元: 削除マーカーのVersionIdを指定してdelete-objectを実行する。
  4. 任意バージョン復元: 特定の過去バージョンに戻す場合はcopy-objectでVersionIdを指定してコピーする。
  5. 復元確認: head-objectでS3 APIに直接アクセスして確認する。

まとめと次のステップ — S3削除ファイルの復元を確実にするために

バージョニングが有効であれば、通常の削除操作からの復元は削除マーカーの除去という単純な操作で完結する。重要なのは、削除マーカーの除去とバージョンの完全削除を混同しないことだ。前者はデータを保持したまま最新バージョンを変更するが、後者は取り消せない。

今後の対策として検討すべき設定:

  • MFA Delete: バージョンの完全削除と、バージョニングの無効化にMFAを要求する。誤操作や不正アクセスによる完全削除を防ぐ最も強力な保護だ。
  • S3 Object Lock: コンプライアンス要件がある場合、WORM(Write Once Read Many)モデルでオブジェクトを保護できる。
  • S3バケットのレプリケーション: 別リージョンへのクロスリージョンレプリケーション(CRR)を設定することで、リージョン障害や誤削除に対する追加の保護層になる。

公式ドキュメント: Amazon S3 — 以前のバージョンの復元

用語集

用語説明
削除マーカー(Delete Marker)バージョニング有効バケットで通常のDELETE操作を行った際に追加される特殊なバージョン。オブジェクト本体は削除されない。
バージョンID(Version ID)バージョニング有効バケットの各オブジェクトバージョンに割り当てられる一意の識別子。
MFA Deleteバージョンの完全削除やバージョニング設定変更にMFA認証を要求するS3の機能。
nullバージョンバージョニング有効化前にアップロードされたオブジェクトに割り当てられるバージョンID。
S3 Object Lock指定期間中のオブジェクト削除・上書きを防止するWORMモデルの保護機能。

コメント

このブログの人気の投稿

SQS Visibility Timeoutの完全解説:メッセージ二重処理の原因と対策

EC2 SSH接続タイムアウトの原因と修正方法 — セキュリティグループのインバウンドルール完全ガイド

S3パブリックアクセス拒否の原因と解決策:バケットレベルの「Block Public Access」が優先される仕組み