AWS CDK で AWS Backup を実装してみた

今回は、AWS Backup サービスによる EC2、EBS、RDSなどの自動バックアップと通知をAWS CDKで実装する方法をまとめました。

はじめに

今回は、AWS Backupサービスを使用して、EC2インスタンスやEBS、RDSなどのリソースの自動バックアップとバックアップ結果通知の仕組みをAWS CDKでコード化していきます。タグベースでバックアップ対象を柔軟に制御し、日次・週次・月次の異なるスケジュールでバックアップを実行します。

 今回作成するリソース

– SNSトピック: バックアップ実行結果の通知
– IAMロール: AWS Backup実行専用ロール
– Backup Vault: バックアップデータの安全な保存場所
– Backup Plan: 日次の自動バックアップスケジュール
– Backup Selection: タグベースでのバックアップ対象リソース選択

アーキテクチャ概要

 

AWS CDK ソースコード

 

SNS設定

    const emailAddresses = [                                                                            // SNS通知先メーリングリスト
      'xxxxxx@example.com',
      'xxxxxxx@example.com'
    ];

    const backupNotificationTopic = new sns.Topic(this, 'BackupNotificationTopic', {                    // バックアップ監視用のトピック
      topicName: 'backup-notification-topic',                                                           // トピック名
      displayName: 'AWS Backup Notification Topic'                                                      // 表示名
    });

    emailAddresses.forEach(email => {                                                                   // バックアップ監視用のサブスクリプション
        backupNotificationTopic.addSubscription(
        new subscriptions.EmailSubscription(email)
      );
    });

ポイント:

  • 複数の管理者アドレスに通知可能
  • バックアップジョブの完了・失敗を即座に通知するためのSNS

IAMロール設定

    const backupRole = new iam.Role(this, 'BackupRole', {
      roleName: 'backup-role',                                                                                  // バックアップロール名
      assumedBy: new iam.ServicePrincipal('backup.amazonaws.com'),                                              // AWS Backupサービスが引き受け
      managedPolicies: [                                                                                        // マネージドポリシー
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSBackupServiceRolePolicyForBackup'),         // バックアップ用マネージドポリシー
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSBackupServiceRolePolicyForRestores'),       // リストア用マネージドポリシー
      ]
    });    

ポイント:

  • AWS Backupサービス専用のロール
  • バックアップとリストア両方の権限を付与

Backup Vault設定

    const backupVault = new backup.BackupVault(this, 'BackupVault', {                              // バックアップボールトの作成
      backupVaultName: 'backup-vault',                                                             // バックアップボールト名
      notificationTopic: backupNotificationTopic,                                                  // バックアップ監視用SNSトピック
      notificationEvents: [                                                                        // 通知イベント
        backup.BackupVaultEvents.BACKUP_JOB_COMPLETED,                                             // バックアップジョブ完了
      ],
      removalPolicy: cdk.RemovalPolicy.DESTROY                                                     // スタック削除時にボールトを削除
    });

ポイント:

  • バックアップデータの暗号化保存
  • SNS通知と連携
  • バックアップジョブ完了時の自動通知
  • リリース完了後RemovalPolicy.RETAINに変更推奨

Backup Plan設定(日次)

    const dailyBackupPlan = new backup.BackupPlan(this, 'DailyBackupPlan', {
      backupPlanName: 'daily-backup-plan',                                                       // バックアッププラン名
      backupPlanRules: [                                                                         // バックアップルール作成
        new backup.BackupPlanRule({
          ruleName: 'daily-backup-rule',                                                         // バックアップルール名
          backupVault: backupVault,                                                              // バックアップボールトを指定
          scheduleExpressionTimezone: TimeZone.ASIA_TOKYO,                                       // 実行スケジュールのタイムゾーンを指定:JST
          scheduleExpression: events.Schedule.cron({                                             // 実行スケジュール(毎日2:00 JST)
            hour: '2',
            minute: '00',
            day: '*',
            month: '*',
            year: '*'
          }),
          startWindow: cdk.Duration.hours(1),                                                    // 次の時間以内に開始:1時間
          completionWindow: cdk.Duration.hours(2),                                               // 次の時間以内に完了:2時間
          deleteAfter: cdk.Duration.days(1)                                                      // 保持期間:1日
        })
      ]
    });

ポイント:

  • タイムゾーン: すべてAsia/Tokyo(JST)で統一
  • スケジュール:
    • 日次: 毎日 2:00 JST
  • 実行時間: 1時間以内開始、2時間以内完了
  • 保持期間: 要件に応じて調整可能(コードは1日設定)

Backup Selection設定(日次)

    const dailyBackupResource = new backup.CfnBackupSelection(this, 'DailyBackupResource', {                      
      backupPlanId: dailyBackupPlan.backupPlanId,                                                 // バックアッププランを指定
      backupSelection: {
        iamRoleArn: backupRole.roleArn,                                                           // IAMロールを指定
        selectionName: 'daily-backup-resource',                                                   // リソース割り当て名
        resources: ['arn:aws:ec2:*:*:instance/*'],                                                // 特定のリソースタイプを含める:EC2のすべてのインスタンス
        conditions: {                                                                             // タグを使用して選択を絞り込む
          StringEquals: [{                                                                        // 次と等しい
            ConditionKey: 'aws:ResourceTag/BackupScheduleDaily',                                  // キー
            ConditionValue: 'True'                                                                // 値
          }]
        }
      }
    });

ポイント:

  • タグベース選択: 柔軟なリソース管理
  • 必要なタグ:
    • 日次: BackupScheduleDaily: True
  • 対象リソース: EC2インスタンス

動作フロー

  1. スケジュール開始: 設定されたCronスケジュールに従ってバックアップ開始
  2. タグチェック: 対象リソースのタグを確認し、バックアップ対象を特定
  3. バックアップ実行: AWS Backupサービスがバックアップを自動実行
  4. 結果通知: SNSトピック経由でメール通知
  5. ライフサイクル管理: 保持期間満了後の自動削除

今回実装したコンストラクトファイルまとめ

 

import * as cdk from 'aws-cdk-lib';
import { TimeZone } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as backup from 'aws-cdk-lib/aws-backup';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as events from 'aws-cdk-lib/aws-events';
import * as sns from 'aws-cdk-lib/aws-sns';
import * as subscriptions from 'aws-cdk-lib/aws-sns-subscriptions';

export interface BackupConstructProps {
  // 必要に応じて追加のプロパティを定義
}

export class BackupConstruct extends Construct {
  constructor(scope: Construct, id: string, props?: BackupConstructProps) {
    super(scope, id);


    //===========================================
    // バックアップ監視用SNSトピック作成
    //===========================================
    const emailAddresses = [                                                                                      // SNS通知先メーリングリスト
      'xxxxxx@example.com',
      'xxxxxxx@example.com'
    ];

    const backupNotificationTopic = new sns.Topic(this, 'BackupNotificationTopic', {                              // バックアップ監視用のトピック
      topicName: 'backup-notification-topic',                                                                     // トピック名
      displayName: 'AWS Backup Notification Topic'                                                                // 表示名
    });

    emailAddresses.forEach(email => {                                                                             // バックアップ監視用のサブスクリプション
        backupNotificationTopic.addSubscription(
        new subscriptions.EmailSubscription(email)
      );
    });

    //===========================================
    // バックアップ用IAMロール作成
    //===========================================
    const backupRole = new iam.Role(this, 'BackupRole', {
      roleName: 'backup-role',                                                                                    // バックアップロール名
      assumedBy: new iam.ServicePrincipal('backup.amazonaws.com'),                                                // AWS Backupサービスが引き受け
      managedPolicies: [                                                                                          // マネージドポリシー
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSBackupServiceRolePolicyForBackup'),           // バックアップ用マネージドポリシー
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSBackupServiceRolePolicyForRestores'),         // リストア用マネージドポリシー
      ]
    });    

    //===========================================
    // AWS Backup作成
    //===========================================
    // バックアップボールトの作成
    const backupVault = new backup.BackupVault(this, 'BackupVault', {                                             // バックアップボールトの作成
      backupVaultName: 'backup-vault',                                                                            // バックアップボールト名
      notificationTopic: backupNotificationTopic,                                                                 // バックアップ監視用SNSトピック
      notificationEvents: [                                                                                       // 通知イベント
        backup.BackupVaultEvents.BACKUP_JOB_COMPLETED,                                                            // バックアップジョブ完了
      ],
      removalPolicy: cdk.RemovalPolicy.DESTROY                                                                    // スタック削除時にボールトを削除
    });

    // 要件に合わせてバックアッププランを選択する
    // 日次バックアッププランの作成
    const dailyBackupPlan = new backup.BackupPlan(this, 'DailyBackupPlan', {
      backupPlanName: 'daily-backup-plan',                                                                        // バックアッププラン名
      backupPlanRules: [                                                                                          // バックアップルール作成
        new backup.BackupPlanRule({
          ruleName: 'daily-backup-rule',                                                                          // バックアップルール名
          backupVault: backupVault,                                                                               // バックアップボールトを指定
          scheduleExpressionTimezone: TimeZone.ASIA_TOKYO,                                                        // 実行スケジュールのタイムゾーンを指定:JST
          scheduleExpression: events.Schedule.cron({                                                              // 実行スケジュール(毎日2:00 JST)
            hour: '2',
            minute: '00',
            day: '*',
            month: '*',
            year: '*'
          }),
          startWindow: cdk.Duration.hours(1),                                                                     // 次の時間以内に開始:1時間
          completionWindow: cdk.Duration.hours(2),                                                                // 次の時間以内に完了:2時間
          deleteAfter: cdk.Duration.days(1)                                                                       // 保持期間:1日
        })
      ]
    });

    // 日次バックアップのリソース割り当て
    const dailyBackupResource = new backup.CfnBackupSelection(this, 'DailyBackupResource', {                      
      backupPlanId: dailyBackupPlan.backupPlanId,                                                                 // バックアッププランを指定
      backupSelection: {
        iamRoleArn: backupRole.roleArn,                                                                           // IAMロールを指定
        selectionName: 'daily-backup-resource',                                                                   // リソース割り当て名
        resources: ['arn:aws:ec2:*:*:instance/*'],                                                                // 特定のリソースタイプを含める:EC2のすべてのインスタンス
        conditions: {                                                                                             // タグを使用して選択を絞り込む
          StringEquals: [{                                                                                        // 次と等しい
            ConditionKey: 'aws:ResourceTag/BackupScheduleDaily',                                                  // キー
            ConditionValue: 'True'                                                                                // 値
          }]
        }
      }
    });
  }
}
});

まとめ

今回は、AWS Backupサービスを使用した包括的なバックアップソリューションをAWS CDKで実装しました。
IaCとして管理することで、環境間での一貫したバックアップポリシーの展開や、設定変更の履歴管理も可能になります。 コンプライアンス要件に応じた保持期間の調整や、運用時間に合わせたスケジュール変更も容易に行えます。

皆さんのお役に立てば幸いです。

タイトルとURLをコピーしました