★★ 中級

18. AWS Backup

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

なぜ AWS Backup か

Backup Vault

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

resource "aws_backup_vault" "main" {
  name        = "myapp-backup"
  kms_key_arn = aws_kms_key.app.arn

  tags = { Project = "myapp" }
}

Backup Plan

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

resource "aws_backup_plan" "daily" {
  name = "daily-30d"

  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                      # 完了猶予

    lifecycle {
      delete_after = 30   # 30 日後に削除
    }

    recovery_point_tags = {
      Type = "daily"
    }
  }

  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(対象指定)

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

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"
    }]
  })
}

resource "aws_iam_role_policy_attachment" "backup_managed" {
  role       = aws_iam_role.backup.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup"
}

resource "aws_backup_selection" "tagged" {
  iam_role_arn = aws_iam_role.backup.arn
  name         = "tagged-resources"
  plan_id      = aws_backup_plan.daily.id

  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(削除不可化)

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

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 を整えていきます。