はじめに
こんにちは、アノテーション構築チームの荒川です。
今回は 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.tf
のplans
変数で定義した値が設定されていて、IAM ロールも正常に割り当てられています。
バックアップ対象リソースや条件指定も意図した通りに設定できました。以上で、想定の構成が満たせました。
バックアップの復元時に各種ポリシーが不足した場合は、文末の参考情報をもとに IAM ロールのポリシーを変更してください。
おわりに
Terraform を 2 週間くらい業務で触ってみて、自分には結構合っていると感じました。
バックアッププランをコンソールで作ると IAM ロールの作成やセレクションの作成をよしなにやってくれますが、Terraform では自分で作らないといけないので、意外とハマるかと思います。
そのような方へ参考になりましたら幸いです。
参考
- Yasuhisa/terraform-aws-backup-sample: AWS Backup Sample Template with Terraform.
- aws_backup_vault | Resources | hashicorp/aws | Terraform Registry
- aws_backup_plan | Resources | hashicorp/aws | Terraform Registry
- aws_backup_selection | Resources | hashicorp/aws | Terraform Registry
- EC2 の AMI からは復元できるが、AWS Backup から復元しようとするとエラーになった際の対処方法 | DevelopersIO
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、さまざまな背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。