Terraform で東京リージョンの AWS Backup を大阪リージョンへコピーする構成を作成してみた

2022.08.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは、アノテーション構築チームの荒川です。

今回は Terraform を使って AWS Backup の東京リージョンのバックアップを大阪リージョンへコピーする構成例を紹介します。

各ファイルの説明などは簡単に紹介します。詳細な設定項目などは公式のリソースドキュメントを参考にしてください。

環境情報

$ terraform -v
Terraform v1.2.6
on darwin_arm64
+ provider registry.terraform.io/hashicorp/aws v3.75.2

構成

東京リージョンのバックアップを大阪リージョンへコピーするには最小で以下の構成が必要です。

  • Vault: 東京リージョン、大阪リージョン各 1 つ
  • Plan: 必要なバックアップ計画数分
  • Selection: プランと同数
    • IAM Role: 東京リージョンに 1 つ

マネジメントコンソールから操作した場合、デフォルトの Vault(Default)と IAM サービスロール(AWSBackupDefaultServiceRole)が作られますが、Terraform で管理する場合はトラブル回避のために使用しない方が良いです。

Creating a backup vault - AWS Backup

You must create at least one vault before creating a backup plan or starting a backup job.
When you first use the AWS Backup console in an AWS Region, the console automatically creates a default vault.
However, if you use AWS Backup through the AWS CLI, AWS SDK, or AWS CloudFormation, a default vault is not created. You must create your own vault.

テンプレート

詳細なコードは GitHub をご参照ください。この記事では重要な部分のみ解説します。

今回は Modulesを使った構成としていますが、シンプルに main.tf へ記述していく形でも問題ありません。

.
├── main.tf
├── modules
│   ├── backup.tf
│   └── variables.tf
└── providers.tf

Providers

まず、大阪リージョンをエイリアスとしてproviders.tfへ定義します。

providers.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

provider "aws" {
  alias  = "osaka"
  region = "ap-northeast-3"
}

alias を記載しない東京リージョンはデフォルトのリージョンとなります。各 resource 定義でproviderを代入しなければ、東京リージョンへリソースが作られます。

Modules

次に、module の定義を追加します。東京リージョンの AWS Backup 関連リソースが依存する大阪リージョンのボールトは、module 外で作成します。

また、ブログの構成上 terraform.tfvars の内容を直接代入していますが、変数は外部ファイルへ書き分けることも可能です。GitHub では以下 3 ファイルで分割しています。

main.tf

resource "aws_backup_vault" "copy" {
  provider = aws.osaka
  name     = "CopyVaultFromTokyo"
}

module "backup" {
  source                = "./modules"
  destination_vault_arn = aws_backup_vault.copy.arn
  backup_vault_name     = "BackupVault"
  iam_role_name         = "BackupRole"
  selection_name        = "BackupSelection"
  plans = {
    # キー名はプラン名
    ec2_plan = {
      rules = {
        # キー名はルール名
        ec2_daily_backup_rule = {
          schedule                 = "cron(0 15 ? * * *)" // 毎日 00:00 JST
          enable_continuous_backup = false                // ポイントインタイムリカバリ
          start_window             = 60                   // バックアップ開始までの時間(分)、最小 60
          completion_window        = 120                  // バックアップ完了までの時間(分)
          delete_after             = 7                    // バックアップ保持期間
          copy_action = {
            delete_after = 14 // コピーの保持期間
          }
        }
      }
      condition = {
        resources = ["arn:aws:ec2:*:*:instance/*"]
        key       = "aws:ResourceTag/aws-backup" // aws-backup の箇所は好みのタグに変える
        value     = true
      }
    }
    rds_plan = {
      rules = {
        rds_daily_backup_rule = {
          schedule                 = "cron(0 15 ? * * *)" // 毎日 00:00 JST
          enable_continuous_backup = false
          start_window             = 60
          completion_window        = 120
          delete_after             = 7
          copy_action = {
            delete_after = 14
          }
        }
        rds_hourly_backup_rule = {
          schedule                 = "cron(0 * ? * * *)" // 毎時 0 分に取得
          enable_continuous_backup = true                // ポイントインタイムリカバリ(PITR)バックアップ
          start_window             = 60
          completion_window        = 120
          delete_after             = 3
          copy_action              = { /* コピーしない */ }
        }
      }
      condition = {
        resources = ["arn:aws:rds:*:*:db:*"]
        key       = "aws:ResourceTag/aws-backup" // aws-backup の箇所は好みのタグに変える
        value     = "true"
      }
    }
  }
}

大阪リージョンのボールトを Terraform で管理しない場合は、resource箇所をdataへ変更してください。

Resource

バックアッププランとセレクションは以下のようにしました。

バックアッププラン

/modules/backup.tf

resource "aws_backup_plan" "main" {
  for_each = var.plans
  name     = each.key

  dynamic "rule" {
    for_each = each.value.rules
    content {
      rule_name                = rule.key
      target_vault_name        = aws_backup_vault.main.name
      schedule                 = rule.value.schedule
      enable_continuous_backup = rule.value.enable_continuous_backup
      start_window             = rule.value.start_window
      completion_window        = rule.value.completion_window

      lifecycle {
        delete_after = rule.value.delete_after
      }

      dynamic "copy_action" {
        for_each = rule.value.copy_action
        content {
          destination_vault_arn = var.destination_vault_arn

          lifecycle {
            delete_after = copy_action.value
          }
        }
      }
    }
  }
}

for_each を使ってプランの数だけリソースを作成しています。ループ処理内のブロックはdynamicを使うことで、可変的に記述できます。

公式ドキュメントのResource: aws_backup_planでは、以下の項目がブロック(hoge {})形式で記述されています。

  • rule
  • lifecycle
  • copy_action

lifecycle は今回複雑なことをやらないので dynamic を使わずに固定しています。
このプランをもとに、セレクションを作成することでリソースの指定やタグでの絞り込みが行えます。

セレクション

/modules/backup.tf

resource "aws_backup_selection" "main" {
  for_each     = var.plans
  iam_role_arn = aws_iam_role.main.arn
  name         = var.selection_name
  plan_id      = aws_backup_plan.main[each.key].id
  resources    = each.value.condition.resources

  condition {
    string_equals {
      key   = each.value.condition.key
      value = each.value.condition.value
    }
  }
}

バックアップのスケジュールや対象リソースの指定、タグ条件の変更はmain.tfの変数の値を変更することで管理できます。

コピー先の Vault が複数出てきた場合などは現在の変数定義では対応できませんので、型情報の変更を行ってください。

作成後のリソースをコンソールで確認

大阪リージョンでボールトが 1 つ作成されています。

東京リージョンでもボールトが 1 つ作成されています。

東京リージョンのプランに今回定義した 2 つのプランが作成されています。RDS のプランを確認します。

プランにはmain.tfplans変数で定義した値が設定されていて、IAM ロールも正常に割り当てられています。

バックアップ対象リソースや条件指定も意図した通りに設定できました。以上で、想定の構成が満たせました。

バックアップの復元時に各種ポリシーが不足した場合は、文末の参考情報をもとに IAM ロールのポリシーを変更してください。

おわりに

Terraform を 2 週間くらい業務で触ってみて、自分には結構合っていると感じました。

バックアッププランをコンソールで作ると IAM ロールの作成やセレクションの作成をよしなにやってくれますが、Terraform では自分で作らないといけないので、意外とハマるかと思います。

そのような方へ参考になりましたら幸いです。

参考

アノテーション株式会社について

アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、さまざまな背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。