Thanks to visit codestin.com
Credit goes to www.sambaiz.net

AWS Backup で各種リソースのバックアップをまとめて取る

aws

AWS Backup はリソースIDやタグで指定した S3 や RDS、DynamoDB などのバックアップをまとめて取ることができるマネージドサービス。Organization 配下のアカウントにポリシーを適用してガバナンスを強化したり、他のリージョンやアカウントの Vault にコピーすることで DR に備えることができる。

AWS Organizaionsで複数のアカウントを一元管理する - sambaiz-net

料金 はバックアップとリストアそれぞれで容量に対してかかる。 ただ、S3 については東京リージョンの保存料金が $0.025/GB なのに対してバックアップは $0.06/GB とかなり割高なので、ある程度の規模の場合 AWS Backup を使わず自前でバックアップを取った方がよさそうだ。 データのリカバリーという観点でいえば Bucket 自体の削除さえケアできればバージョニングもその手段になり得る。そもそもバージョニングを有効にしないと AWS Backup の対象にできない。

S3のバージョニングを有効にして誤って上書きや削除してしまったオブジェクトを復旧できるようにする - sambaiz-net

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as backup from 'aws-cdk-lib/aws-backup';
import * as iam from 'aws-cdk-lib/aws-iam';

export class AwsBackupTestStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // VPC for RDS
    const vpc = new ec2.Vpc(this, 'BackupTestVpc', {
      maxAzs: 2,
      natGateways: 0,
      subnetConfiguration: [
        {
          name: 'Public',
          subnetType: ec2.SubnetType.PUBLIC,
          cidrMask: 24,
        },
      ],
    });

    // RDS Instance (PostgreSQL)
    const dbInstance = new rds.DatabaseInstance(this, 'BackupTestDatabase', {
      engine: rds.DatabaseInstanceEngine.postgres({
        version: rds.PostgresEngineVersion.VER_16_6,
      }),
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO),
      vpc,
      vpcSubnets: {
        subnetType: ec2.SubnetType.PUBLIC,
      },
      publiclyAccessible: true,
      multiAz: false,
      allocatedStorage: 20,
      maxAllocatedStorage: 100,
      databaseName: 'testdb',
      credentials: rds.Credentials.fromGeneratedSecret('dbadmin'),
      backupRetention: cdk.Duration.days(7), // Enable RDS automatic backups for PITR (AWS Backup handles long-term retention)
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      deletionProtection: false,
    });

    // Allow PostgreSQL access from anywhere (test environment only)
    dbInstance.connections.allowFromAnyIpv4(ec2.Port.tcp(5432));

    // S3 Bucket
    const bucket = new s3.Bucket(this, 'BackupTestBucket', {
      versioned: true, // Required for AWS Backup
      encryption: s3.BucketEncryption.S3_MANAGED,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });

    // Tag resources for AWS Backup selection
    cdk.Tags.of(dbInstance).add('Backup', 'daily');
    cdk.Tags.of(bucket).add('Backup', 'daily');

    // Backup Vault
    const backupVault = new backup.BackupVault(this, 'BackupVault', {
      backupVaultName: 'AwsBackupTestVault',
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    // Backup Plan
    const backupPlan = new backup.BackupPlan(this, 'BackupPlan', {
      backupPlanName: 'DailyBackupPlan',
      backupVault,
      backupPlanRules: [
        new backup.BackupPlanRule({
          ruleName: 'HourlyBackup',
          scheduleExpression: cdk.aws_events.Schedule.cron({
            minute: '0',  // Every hour
          }),
          deleteAfter: cdk.Duration.days(7),
          startWindow: cdk.Duration.hours(1),
          completionWindow: cdk.Duration.hours(2),
        }),
      ],
    });

    // Backup Selection (tag-based)
    const backupRole = new iam.Role(this, 'BackupRole', {
      assumedBy: new iam.ServicePrincipal('backup.amazonaws.com'),
      managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSBackupServiceRolePolicyForBackup'),
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSBackupServiceRolePolicyForRestores'),
        iam.ManagedPolicy.fromAwsManagedPolicyName('AWSBackupServiceRolePolicyForS3Backup'),
        iam.ManagedPolicy.fromAwsManagedPolicyName('AWSBackupServiceRolePolicyForS3Restore'),
      ],
    });

    backupPlan.addSelection('DailyBackupSelection', {
      resources: [
        backup.BackupResource.fromTag('Backup', 'daily'),
      ],
      role: backupRole,
      allowRestores: true,
    });
  }
}

最短 60 分の指定した間隔で Recovery points が作られるので選んで新しいインスタンスにリストアできる。