【AWS-Backup】時間経過を問わずに最新のバックアップから7世代分隔地保管する

![AWS-Backup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/262d1b0b-3269-d943-52c7-8fded67991c6.png)

## はじめに
本記事は要件からAWSを触っていく中での
個人的な知見を基に作成しております。

AWSのベストプラクティスを参考にもっといいものが作れる
一部分をブラッシュアップできる
場合は後学で参考にしますのでコメントいただけますと嬉しいです。

## 本記事で実現できること
東京リージョンから大阪リージョンへ
時間経過を問わずに最新のバックアップから7世代分隔地保管を行う

## 背景
災対環境を考慮した際、数日間システムが止まった場合、
AWS Backupで7日保管した場合、7世代分の隔地保管が
保たれない可能性がある

## 構成図
![【AWS-Backup】日付に依存せず、 常に最新の7世代を確保して隔地保管.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/dbad4c09-9767-8000-70d0-6b1f5978be84.png)


## 目次
１．AWS Backup 大阪リージョンへのコピーを100年に設定
２．Lambdaで数をカウントして7個分は保持、8個以上だったら古い方から削除(7世代保管)
３．大阪リージョンへのバックアップコピー完了をトリガにLambdaを実行
Appendex:　IAM権限周り
## １．AWS Backup 大阪リージョンへのコピーを100年に設定
※該当箇所のみピックアップ
　その他、AWS Backupの設定は省略

- コピー先：大阪リージョン
- 送信先バックアップボールト：test-bk-db-server
- 合計保持期間：100年　※100年に指定、実質無期限。

 ![【AWS-Backup】日付に依存せず、 常に最新の7世代を確保して隔地保管 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/82797b63-a01b-6787-7330-6681f3e09c38.png)

大阪リージョンにバックアップボールトを作っておく
- ボールト名：test-bk-db-server
- ボールト ARN：arn:aws:backup:ap-northeast-3:xxxxxxxx:backup-vault:test-bk-db-server

![【AWS-Backup】日付に依存せず、 常に最新の7世代を確保して隔地保管 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/557d3379-d5fe-94e4-55a6-542f5a83cc7d.png)


## ２．Lambdaで数をカウントして7個分は保持、8個以上だったら古い方から削除(7世代保管)

大阪リージョンに下記、Lambdaを作成
### Lambda関数の作成
- 関数名：bkp-db-server-Lambda
- ランタイム：Python3.12
- アーキテクチャ：x86_64
- 実行ロール：基本的なLambdaアクセス権限で新しいロールを作成

![【AWS-Backup】日付に依存せず、 常に最新の7世代を確保して隔地保管 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/4e5f1212-59c2-87c6-7d49-5501b93c538f.png)

### 基本設定
既存のロールを使用する
既存のロール：LambdaBackupRole

![【AWS-Backup】日付に依存せず、 常に最新の7世代を確保して隔地保管 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/9157cf72-c8a0-e1b4-472f-4241e719df20.png)

### Lambdaコードソース
```ruby:title: DBのバックアップボールトのLambda
import boto3

def lambda_handler(event, context):
    # AWS Backupクライアントの作成
    backup_client = boto3.client('backup')

    # ボールト名
    vault_name = 'test-bk-db-server'

    # バックアップ復旧ポイントのリスト取得
    response = backup_client.list_recovery_points_by_backup_vault(
        BackupVaultName=vault_name
    )

    # 復旧ポイントが7つ以上ある場合、古い順に並び替え
    if 'RecoveryPoints' in response and len(response['RecoveryPoints']) > 7:
        sorted_recovery_points = sorted(response['RecoveryPoints'], key=lambda x: x['CreationDate'])

        # 削除する復旧ポイントの数
        num_recovery_points_to_delete = len(sorted_recovery_points) - 7

        # 古い順に復旧ポイントを削除
        for i in range(num_recovery_points_to_delete):
            recovery_point_arn = sorted_recovery_points[i]['RecoveryPointArn']
            print(f"Deleting Recovery Point: {recovery_point_arn}")
            backup_client.delete_recovery_point(BackupVaultName=vault_name, RecoveryPointArn=recovery_point_arn)

        print(f"{num_recovery_points_to_delete} old Recovery Points deleted.")

    return {
        'statusCode': 200,
        'body': 'Recovery Point management completed.'
    }

```
![【AWS-Backup】日付に依存せず、 常に最新の7世代を確保して隔地保管 (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/496b37dd-aa87-148d-724e-b29ba78f7013.png)



## ３．大阪リージョンへのバックアップコピー完了をトリガにLambdaを実行

 Backupでは直接Lambdaをトリガーとして使用することが難しい場合があるため、AWS CloudWatch Eventsを使用してこのタスクを実現

- 名前：bk-db-server-rule
- ルールタイプ：イベントパターンを持つルール
![【AWS-Backup】日付に依存せず、 常に最新の7世代を確保して隔地保管 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/c9113bfb-6a8d-149a-89f0-2815c61aaee5.png)

### イベントパターン
- イベントソース：その他
![【AWS-Backup】日付に依存せず、 常に最新の7世代を確保して隔地保管 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/8226c62b-8416-569f-4a3a-ca78c13e3f98.png)

```ruby:title: イベントパターン
{
  "source": ["aws.backup"]
}

```
※AWS Backupのすべてのイベント(何らかのイベントがあった際)
　をトリガーにLambda実行可能

### ターゲット
 - ターゲットタイプ：AWSのサービス
 - ターゲット選択：Lambda関数
 - Lambda関数：bkp-db-server-Lambda
 - バージョン/エイリアス：デフォルト
 - ターゲット入力：一致したイベント
 - 他: デフォルト設定
![【AWS-Backup】日付に依存せず、 常に最新の7世代を確保して隔地保管 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/0c2255d4-00b7-f325-5426-741a570a940e.png)



## Appendex:　IAM権限周り
IAMロール：AWSLambdaRole
カスタムポリシー：LambdaBackupPolicy

```ruby:title: LambdaBackupPolicy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "backup:DeleteRecoveryPoint",
                "backup:ListRecoveryPointsByBackupVault"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "backup:StartBackupJob",
                "backup:ListBackupJobs",
                "backup:ListBackupPlans"
            ],
            "Resource": [
                "arn:aws:backup:ap-northeast-3:xxxxxxxx:backup-vault:test-bk-db-server",
                "arn:aws:rds:ap-northeast-3:xxxxxxxx:snapshot:awsbackup:copyjob-*",
                "arn:aws:rds:ap-northeast-3:xxxxxxxx:snapshot:awsbackup:job-*",
                "arn:aws:backup:ap-northeast-1:xxxxxxxx:recovery-point:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:*:*:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "arn:aws:backup:ap-northeast-3:xxxxxxxx:backup-vault:backup-vault:test-bk-db-server",
                "arn:aws:rds:ap-northeast-3:xxxxxxxx:snapshot:awsbackup:copyjob-*",
                "arn:aws:rds:ap-northeast-3:xxxxxxxx:snapshot:awsbackup:job-*",
                "arn:aws:backup:ap-northeast-1:xxxxxxxx:recovery-point:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "events:PutTargets",
                "events:PutRule"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:DetachRolePolicy"
            ],
            "Resource": [
                "arn:aws:iam::xxxxxxxx:role/LambdaBackupRole"
            ]
        }
    ]
}

```

信頼されたエンティティ
```ruby:title: 信頼されたエンティティ
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

## まとめ
本稿が、時間経過を問わずに最新のバックアップから7世代分隔地保管したい方の参考になれば嬉しいです。

ITエンジニア向け、AWS資格取得を目指す方向けに個人ブログで記事も投稿していますので、
合わせて読んでもらえると嬉しいです。
[ことなの学校(個人ブログ)](https://kotona-school.com)

更によりレベル感の高そうなAWS関連の発信はZennの方で行います。
こちらももしよければフォロー、ご確認いただけると嬉しいです。
[Zenn個人アカウント](https://zenn.dev/tomo_itbizblog)

Twitterでも役立つ情報を発信しますのでフォローしてもらえると嬉しいです 
→ [@tomo_ITBizBlog](https://twitter.com/tomo_ITBizBlog)