★★ 中級

18. AWS Backup

EBS・RDS・DynamoDB・EFS・FSx 等のバックアップを 1 つの計画で一元管理。タグベースで対象を選び、保管期間・コピー・削除保護を運用化できる。

なぜ AWS Backup か

Backup Vault

バックアップを保管する箱。KMS キーで暗号化。

# Backup Vault:バックアップ(リカバリポイント)の保管箱
# KMS CMK で暗号化し、ポリシーで削除権限を絞り込む
resource "aws_backup_vault" "main" {
  name        = "myapp-backup"
  kms_key_arn = aws_kms_key.app.arn

  tags = { Project = "myapp" }
}

Backup Plan

「いつ・どれくらい保持・どこにコピー」を定義。

# Backup Plan:複数の rule を持つ計画書
resource "aws_backup_plan" "daily" {
  name = "daily-30d"

  # rule #1: 毎日のバックアップ
  rule {
    rule_name         = "daily"
    target_vault_name = aws_backup_vault.main.name
    schedule          = "cron(0 17 * * ? *)"   # UTC 17:00 = JST 02:00
    start_window      = 60                       # 開始遅延を許容(分)
    completion_window = 360                      # 完了猶予

    # 保管期間:30 日経過後に自動削除
    lifecycle {
      delete_after = 30   # 30 日後に削除
    }

    # 生成された recovery point に付くタグ
    recovery_point_tags = {
      Type = "daily"
    }
  }

  # rule #2: 月次の長期保持+DR コピー
  rule {
    rule_name         = "monthly"
    target_vault_name = aws_backup_vault.main.name
    schedule          = "cron(0 17 1 * ? *)"   # 毎月 1 日 UTC 17:00

    lifecycle {
      cold_storage_after = 90    # 90 日後に Glacier 相当へ
      delete_after       = 365   # 1 年保持
    }

    # 別リージョンへコピー(DR)
    # 災害対策:プライマリ消失時もコピー先から復元可
    copy_action {
      destination_vault_arn = aws_backup_vault.dr.arn  # 別リージョンの vault
      lifecycle {
        delete_after = 365
      }
    }
  }
}

Backup Selection(対象指定)

「タグでマッチしたリソースを対象に」が最も実用的。

# AWS Backup サービス用のロール
resource "aws_iam_role" "backup" {
  name = "backup-service"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = { Service = "backup.amazonaws.com" }
      Action = "sts:AssumeRole"
    }]
  })
}

# AWS 提供のマネージドポリシーで権限を一括付与(バックアップ用)
resource "aws_iam_role_policy_attachment" "backup_managed" {
  role       = aws_iam_role.backup.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup"
}

# Selection:「どのリソースを plan に組み入れるか」
# selection_tag でタグ一致するリソースを自動で対象に
resource "aws_backup_selection" "tagged" {
  iam_role_arn = aws_iam_role.backup.arn
  name         = "tagged-resources"
  plan_id      = aws_backup_plan.daily.id

  # タグ Backup=daily が付いたリソースが対象
  selection_tag {
    type  = "STRINGEQUALS"
    key   = "Backup"
    value = "daily"
  }
}

あとは各リソースに tags = { Backup = "daily" } を付けるだけで、自動でバックアップ計画に組み込まれます。

# リソース側の修正例:タグを足すだけ
resource "aws_db_instance" "main" {
  # ...
  tags = {
    Name   = "myapp"
    Backup = "daily"   # ← これだけで AWS Backup 対象に
  }
}

resource "aws_ebs_volume" "data" {
  # ...
  tags = {
    Name   = "data"
    Backup = "daily"
  }
}

Vault Lock(削除不可化)

バックアップを「保護期間中は誰も消せない」状態にする。ランサムウェア対策・コンプライアンス対応。

# Vault Lock:保管庫を「保持期間中は誰も消せない」状態にロック
# Compliance モードと Governance モードがあるが、これは Compliance モード相当
resource "aws_backup_vault_lock_configuration" "main" {
  backup_vault_name   = aws_backup_vault.main.name
  changeable_for_days = 3       # この日数間は設定変更可(テスト用)
  min_retention_days  = 30      # 最低 30 日保持
  max_retention_days  = 365     # 最大 365 日
}
Vault Lock の不可逆性 changeable_for_days を過ぎると AWS サポートでも変更・削除不可。本番投入前に開発環境で動作確認を。

完成形

下記でリソース側に Backup=daily タグを付けるだけの運用が確立。

terraform/
├── backup.tf       # vault, plan, selection, role, kms
├── rds.tf          # tags = { Backup = "daily" }
├── ebs.tf          # tags = { Backup = "daily" }
└── dynamodb.tf     # tags = { Backup = "daily" }
AWS セクション完了 お疲れ様でした。次は GitHub セクション でチーム開発と CI/CD を整えていきます。