NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

注目のタグ

    AWS Backup for Amazon S3によるバケットのバックアップ&リストア

    こんにちは、上野です。 2021年のre:Inventで発表されたAWS Backupの新機能紹介です。

    AWS Backupとは

    Amazon EC2、Amazon EBS、Amazon RDSなどの複数のAWSサービスのバックアップを、AWS Backupという1つのサービスで一元管理できるサービスです。バックアップの定期実行やリージョン間コピーなどの処理が、AWSマネージドで実行できます。

    今回検証する新機能

    AWS BackupにAmazon S3がサポート対象として追加されたので、それを試してみます。

    2021年11月にオレゴンリージョン限定でプレビューとして公開され、

    aws.amazon.com

    2022年2月に東京リージョンを含む複数のリージョンで一般公開されました。

    aws.amazon.com

    そもそもS3のバックアップは必要なのか?

    最初にこれが疑問に出てくるかもしれません。S3では、オブジェクトは3個以上のAZに自動コピーされます。

    つまり、AZ障害やデータセンター障害を考慮したバックアップは不要となります。

    保存したリージョンの外(他のリージョン)には保存されないため、リージョン全体の障害を考慮する場合は、別リージョンへのコピー保存も検討が必要です。

    また、利用者の誤操作による削除、更新については別途検討する必要があります。 S3にはバージョニング機能があるので、誤操作をした場合も、この機能を有効にすれば、過去のバージョンから復旧できます。

    バージョニング方式

    バージョニングを有効にした場合の履歴管理方法を見ていきます。

    次のように、バージョニングがON、テキストファイルが10個格納されたバケットを用意します。

    各テキストファイルには以下のように数字が書かれています。
    test0.txt⇒「0」
    test1.txt⇒「1」
    ・・・
    test9.txt⇒「9」

    これらすべてのファイルを、誤操作で更新してしまった場合を想定します。 実際に以下のように書き換えます。
    test0.txt⇒「10」
    test1.txt⇒「11」
    ・・・
    test9.txt⇒「19」

    バージョニングが有効になっているので、以下のように2つのバージョンが生成されるのがわかります。

    さて、これらすべてのファイルを元の状態に戻すにはどうしたら良いでしょうか。 復元方法は公式ドキュメントに記載があります。2種類です。

    • 以前のバージョンを同じバケットにコピー(任意のバージョンを指定)
    • 最新バージョンを完全に削除(1つ前に戻す)

    この操作を、オブジェクト1個ずつ実施する必要があります。

    10個であれば手動でも行けるかもしれませんが、数百数千となった場合は手動復旧は難しいです。 そのため復旧処理をスクリプト化しても良いのですが、開発やテストにも時間がかかりますし、そこまで備えておくべきなのか?という疑問も残ります。

    このように大量のオブジェクトに誤操作で更新してしまい、「あの頃のバケットに戻して!」となった場合に実現できるのが今回のアップデートになります。

    AWS Backup for Amazon S3を使ってみる

    AWS BackupでS3を利用する場合、リソース設定を有効にする必要があります。
    リソース設定にS3が追加されているので、これを有効にします。

    実際にバケットを作成して試していきます。

    まずは同じようにテキストファイルが10個あるバケットを用意しておきます。バケットのバージョニングはONにする必要があります。各オブジェクトのサイズは2.0Bです。(後ほど更新するので覚えておいてください)

    また、バケット設定でACLも有効にしておく必要があります。

    ※有効にしていないと以下のように復旧時にエラーとなります。

    この状態で、AWS Backupを設定していきます。

    なお、AWSデフォルトのサービスロールでは、S3関連の権限がないため、以下ドキュメントのとおり、ポリシーを2種類足してあげる必要があります。

    Amazon S3 backups - AWS Backup

    付与対象ロール:AWSBackupDefaultServiceRole
    ※ロールが無い場合はAWS Backupのバックアップ実行時に初回作成

    付与ポリシー①:

    {
      "Version":"2012-10-17",
      "Statement":[
        {
          "Sid":"S3BucketBackupPermissions",
          "Action":[
            "s3:GetInventoryConfiguration",
            "s3:PutInventoryConfiguration",
            "s3:ListBucketVersions",
            "s3:ListBucket",
            "s3:GetBucketVersioning",
            "s3:GetBucketNotification",
            "s3:PutBucketNotification",
            "s3:GetBucketLocation",
            "s3:GetBucketTagging"
          ],
          "Effect":"Allow",
          "Resource":[
            "arn:aws:s3:::*"
          ]
        },
        {
          "Sid":"S3ObjectBackupPermissions",
          "Action":[
            "s3:GetObjectAcl",
            "s3:GetObject",
            "s3:GetObjectVersionTagging",
            "s3:GetObjectVersionAcl",
            "s3:GetObjectTagging",
            "s3:GetObjectVersion"
          ],
          "Effect":"Allow",
          "Resource":[
            "arn:aws:s3:::*/*"
          ]
        },
        {
          "Sid":"S3GlobalPermissions",
          "Action":[
            "s3:ListAllMyBuckets"
          ],
          "Effect":"Allow",
          "Resource":[
            "*"
          ]
        },
        {
          "Sid":"KMSBackupPermissions",
          "Action":[
            "kms:Decrypt",
            "kms:DescribeKey"
          ],
          "Effect":"Allow",
          "Resource":"*",
          "Condition":{
            "StringLike":{
              "kms:ViaService":"s3.*.amazonaws.com"
            }
          }
        },
        {
          "Sid":"EventsPermissions",
          "Action":[
            "events:DescribeRule",
            "events:EnableRule",
            "events:PutRule",
            "events:DeleteRule",
            "events:PutTargets",
            "events:RemoveTargets",
            "events:ListTargetsByRule",
            "events:DisableRule"
          ],
          "Effect":"Allow",
          "Resource":"arn:aws:events:*:*:rule/AwsBackupManagedRule*"
        },
        {
          "Sid":"EventsMetricsGlobalPermissions",
          "Action":[
            "cloudwatch:GetMetricData",
            "events:ListRules"
          ],
          "Effect":"Allow",
          "Resource":"*"
        }
      ]
    }
    

    付与ポリシー②:

    {
      "Version":"2012-10-17",
      "Statement":[
        {
          "Sid":"S3BucketRestorePermissions",
          "Action":[
            "s3:CreateBucket",
            "s3:ListBucketVersions",
            "s3:ListBucket",
            "s3:GetBucketVersioning",
            "s3:GetBucketLocation",
            "s3:PutBucketVersioning"
          ],
          "Effect":"Allow",
          "Resource":[
            "arn:aws:s3:::*"
          ]
        },
        {
          "Sid":"S3ObjectRestorePermissions",
          "Action":[
            "s3:GetObject",
            "s3:GetObjectVersion",
            "s3:DeleteObject",
            "s3:PutObjectVersionAcl",
            "s3:GetObjectVersionAcl",
            "s3:GetObjectTagging",
            "s3:PutObjectTagging",
            "s3:GetObjectAcl",
            "s3:PutObjectAcl",
            "s3:PutObject",
            "s3:ListMultipartUploadParts"
          ],
          "Effect":"Allow",
          "Resource":[
            "arn:aws:s3:::*/*"
          ]
        },
        {
          "Sid":"S3KMSPermissions",
          "Action":[
            "kms:Decrypt",
            "kms:DescribeKey",
            "kms:GenerateDataKey"
          ],
          "Effect":"Allow",
          "Resource":"*",
          "Condition":{
            "StringLike":{
              "kms:ViaService":"s3.*.amazonaws.com"
            }
          }
        }
      ]
    }
    

    IAMロールの準備ができたら、AWS Backupの画面に移動して、オンデマンドバックアップを取得してみます。

    リソースタイプにS3、バケット名にバックアップ対象のバケットを指定します。その他の保持期間などの設定はデフォルトで行きます。

    ステータスが実行中となり・・

    2分ほどで完了となりました。

    では、ここでS3バケットの中身を書き変えてみます。 5つのファイルを更新し、5つのファイルを削除しました。 更新はわかりにくいですが、サイズが2.0Bから3.0Bに変わっています。

    これが誤操作だったとして、最初のオブジェクトが10個だった状態に戻してみます。

    AWS Backupの画面から、バックアップボールドに残っている復旧ポイントから、復元ボタンを押下します。

    復元先に別のバケットを指定し、そのバケット上に復旧させます。

    ※「ソースバケットに復元する」(同じバケットに復旧する)というメニューもあるのですが、同じ名前の(新しいバージョンの)オブジェクトがあった場合、オブジェクトは復旧(更新)されません。つまりバックアップ取得後の更新についても更新前に戻したい場合は、別途空のバケットを復旧先に指定する必要があります。

    Restore S3 data using AWS Backup - AWS Backup

    Restores of objects are skipped if the source bucket has an object with the same name or version ID.
    (上野訳)ソースバケットに同じ名前もしくは同じversion IDのオブジェクトがあったらリストアをスキップする

    英語文と上野訳が少し怪しいですが、ソースバケットをターゲットとして同じ名前のオブジェクトがあったらスキップするという意図かと思います。実際にソースバケットを指定した場合は、同じ名前で更新されたオブジェクトは元に戻りませんでした。

    脱線が長くなりましたが、改めて、復元先に空の別バケットを指定して復旧させます。

    復元ジョブが実行中となり・・

    10分ほどで完了しました。

    リストア先のバケットを見てみると、最初に格納されていた2.0Bのオブジェクト10個が格納されていることがわかります。最終更新日時は、リストアされた日時になるようです。(バックアップ時のオブジェクト更新日時は残らない)

    検証は以上です。

    まとめ

    S3のバックアップ、特に操作ミスや処理失敗時にどう復旧させるか設計時に悩むこともありましたが、このAWS Backupがひとつの解決策として使用できそうです。

    今回はオンデマンドバックアップで手動実行しましたが、バックアッププランを使用して日次定期バックアップもできるので、「S3バケット全体の状態を定期保存」するということが実現できるようになりました。

    AWS Backupの使用ではACLの有効が必須ですが、S3側のドキュメントではACL無効かおススメとなっており、ここは中々悩ましいポイントです。ACLが無効状態でもAWS Backupが利用可能になるアップデートを期待しましょう。

    すべての新しいバケットの ACL を無効にし、オブジェクト所有権を執行します。 - Amazon Simple Storage Service

    それではまた!

    執筆者上野史瑛

    Japan APN Ambassador 2020
    AWSを中心としたクラウドの導入、最適化を専門に行っています。