[アップデート] Aurora DSQLがTerraform AWS Provider v5.100.0でサポートされたので、デプロイしてみた

[アップデート] Aurora DSQLがTerraform AWS Provider v5.100.0でサポートされたので、デプロイしてみた

ようやくAurora DSQLがTerraform AWS Providerでデプロイできるようになっていました
Clock Icon2025.07.08

あしざわです。

Terraform AWS Provider の v5.100.0にて、Aurora DSQL がサポートされていました。

https://github.com/hashicorp/terraform-provider-aws/releases/tag/v5.100.0

数字で見た通り、バージョン5における100番目のマイナーバージョンです。これ以降WS Providerのメジャーバージョンはv6に更新されたので、なんだか感慨深いですね。

v5.99.1などの細かいマイナーバージョンが存在するので、「100個目のマイナーバージョン」ではないです。

この記事を執筆している2025年7月7日は、私が所属しているクラスメソッドの創立記念日です。なんだか不思議な縁を感じます(?)

それでは本編に入ります。

概要

現在、Terraform AWS ProviderでサポートされているAurora DSQL関連のリソースは2つです

前者はAurora DSQL クラスターです。このサービスの本体であるDBクラスターを作成できます。

後者はAurora DSQL ピアリングです。Aurora DSQLのマルチリージョンクラスターを作成する際に、2つのリージョンで作成したDBクラスターからウィットネスリージョンという監視(ウィットネス)リージョンに向けたピア接続に利用するリソースです。

マルチリージョンクラスターを作成すると、2つのリージョン同士の書き込みが複製され、どちらのクラスターでも読み取り・書き込みが行えます。両リージョンからピア接続されるウィットネスリージョンには暗号化されたトランザクションログが保存されます。

例えば、バージニア北部リージョンとオハイオリージョンにあるDSQLクラスターを同期したい場合、オレゴンリージョンをウィットネスリージョンとして両リージョンからのピア接続を行うことになります。

文章にするとわかりづらいので図で表してみました。

aurora-dsql-peer-connection

Aurora DSQLのマルチリージョンクラスターについては以下記事でも紹介されています。東京・大阪を含めたアジアリージョンでは最近作成できるようになったようです。

https://dev.classmethod.jp/articles/aurora-dsql-ap-multi-region/

リソースを作成してみた

それでは、実際にTerraformでAurora DSQLを作成してみましょう。

この記事では、DSQL関連のリソース2つのどちらとも使ってみたいので、「単一リージョンでのDSQLクラスター作成」および「DSQLマルチリージョンクラスターの作成」の2パターンで検証してみます。

検証で利用するTerraformテンプレートは以下に置いています。

https://github.com/h-ashisan/terraform_for_aurora_dsql

利用するプロバイダー設定は以下とします。

provider.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.100.0"
    }
  }
}

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

provider "aws" {
  alias  = "soul"
  region = "ap-northeast-2"
}

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

プロバイダー設定後、初期設定を実施しておきます。

> terraform init

Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "5.100.0"...
- Installing hashicorp/aws v5.100.0...
- Installed hashicorp/aws v5.100.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

これで準備完了です。

単一リージョンへのDSQLクラスター作成

利用したテンプレートはこちらです。

https://github.com/h-ashisan/terraform_for_aurora_dsql/blob/main/dsql-single-cluster.tf

リージョンの設定を除くと削除保護の設定以外に必須のパラメータがなく、とてもシンプルに記載できます。

問題なくplanコマンドが通りました。

> tf plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

Terraform will perform the following actions:

  # aws_dsql_cluster.single will be created
  + resource "aws_dsql_cluster" "single" {
      + arn                         = (known after apply)
      + deletion_protection_enabled = true
      + encryption_details          = (known after apply)
      + identifier                  = (known after apply)
      + kms_encryption_key          = (known after apply)
      + tags_all                    = {}
      + vpc_endpoint_service_name   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.

そのままapplyも実行。1分39秒でリソースの作成が完了しました

> tf apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

Terraform will perform the following actions:

  # aws_dsql_cluster.single will be created
  + resource "aws_dsql_cluster" "single" {
      + arn                         = (known after apply)
      + deletion_protection_enabled = true
      + encryption_details          = (known after apply)
      + identifier                  = (known after apply)
      + kms_encryption_key          = (known after apply)
      + tags_all                    = {}
      + vpc_endpoint_service_name   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_dsql_cluster.single: Creating...
aws_dsql_cluster.single: Still creating... [10s elapsed]
aws_dsql_cluster.single: Still creating... [20s elapsed]
aws_dsql_cluster.single: Still creating... [30s elapsed]
aws_dsql_cluster.single: Still creating... [40s elapsed]
aws_dsql_cluster.single: Still creating... [50s elapsed]
aws_dsql_cluster.single: Still creating... [1m0s elapsed]
aws_dsql_cluster.single: Still creating... [1m10s elapsed]
aws_dsql_cluster.single: Still creating... [1m20s elapsed]
aws_dsql_cluster.single: Still creating... [1m30s elapsed]
aws_dsql_cluster.single: Creation complete after 1m39s

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

AWSマネジメントコンソールで確認してみたところ、確かにリソースが作成されていました。Nameタグを空で作成するとそのまま「空」と表示されるんですね。

CleanShot 2025-07-08 at 02.18.38

DSQLマルチリージョンクラスターの作成

続いて、マルチリージョンクラスターの作成を検証します。

この検証におけるマルチリージョンクラスターのリージョン構成は以下としました。

  • ピアリージョン:東京、大阪
  • ウィットネスリージョン:ソウル

先ほど紹介したアップデートブログのリージョン構成がTerraformでも再現できるか試してみます。

使用したテンプレートはこちらにアップロードしています。

https://github.com/h-ashisan/terraform_for_aurora_dsql/blob/main/dsql-multi-cluster.tf

planでテンプレートをチェックします。

> tf plan
aws_dsql_cluster.single: Refreshing state...

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

Terraform will perform the following actions:

  # aws_dsql_cluster.osaka will be created
  + resource "aws_dsql_cluster" "osaka" {
      + arn                       = (known after apply)
      + encryption_details        = (known after apply)
      + identifier                = (known after apply)
      + kms_encryption_key        = (known after apply)
      + tags_all                  = {}
      + vpc_endpoint_service_name = (known after apply)

      + multi_region_properties {
          + clusters       = (known after apply)
          + witness_region = "ap-northeast-2"
        }
    }

  # aws_dsql_cluster.tokyo will be created
  + resource "aws_dsql_cluster" "tokyo" {
      + arn                       = (known after apply)
      + encryption_details        = (known after apply)
      + identifier                = (known after apply)
      + kms_encryption_key        = (known after apply)
      + tags_all                  = {}
      + vpc_endpoint_service_name = (known after apply)

      + multi_region_properties {
          + clusters       = (known after apply)
          + witness_region = "ap-northeast-2"
        }
    }

  # aws_dsql_cluster_peering.osaka_to_soul will be created
  + resource "aws_dsql_cluster_peering" "osaka_to_soul" {
      + clusters       = [
          + (known after apply),
        ]
      + identifier     = (known after apply)
      + witness_region = "ap-northeast-2"
    }

  # aws_dsql_cluster_peering.tokyo_to_soul will be created
  + resource "aws_dsql_cluster_peering" "tokyo_to_soul" {
      + clusters       = [
          + (known after apply),
        ]
      + identifier     = (known after apply)
      + witness_region = "ap-northeast-2"
    }

Plan: 4 to add, 0 to change, 0 to destroy.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.

applyでリソースを作成します (検証時に後述するエラーが発生したため、DSQLクラスターの削除→作成の流れになっています)

> tf apply
aws_dsql_cluster.tokyo: Refreshing state...
aws_dsql_cluster.single: Refreshing state...
aws_dsql_cluster.osaka: Refreshing state...

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # aws_dsql_cluster.osaka is tainted, so must be replaced
-/+ resource "aws_dsql_cluster" "osaka" {
      ~ arn                         = "arn:aws:dsql:ap-northeast-3:123456789012:cluster/xxxxxxxxxxxxxxxxxx" -> (known after apply)
      ~ deletion_protection_enabled = false -> true
      ~ encryption_details          = [
          - {
              - encryption_status = "ENABLED"
              - encryption_type   = "AWS_OWNED_KMS_KEY"
            },
        ] -> (known after apply)
      ~ identifier                  = "xxxxxxxxxxxxxxxxxx" -> (known after apply)
      ~ kms_encryption_key          = "AWS_OWNED_KMS_KEY" -> (known after apply)
      ~ vpc_endpoint_service_name   = "com.amazonaws.ap-northeast-3.dsql-f7me" -> (known after apply)
        # (1 unchanged attribute hidden)

      ~ multi_region_properties {
          ~ clusters       = [] -> (known after apply)
            # (1 unchanged attribute hidden)
        }
    }

  # aws_dsql_cluster.tokyo is tainted, so must be replaced
-/+ resource "aws_dsql_cluster" "tokyo" {
      ~ arn                         = "arn:aws:dsql:ap-northeast-1:123456789012:cluster/yyyyyyyyyyyyyyyyy" -> (known after apply)
      ~ deletion_protection_enabled = false -> true
      ~ encryption_details          = [
          - {
              - encryption_status = "ENABLED"
              - encryption_type   = "AWS_OWNED_KMS_KEY"
            },
        ] -> (known after apply)
      ~ identifier                  = "yyyyyyyyyyyyyyyyy" -> (known after apply)
      ~ kms_encryption_key          = "AWS_OWNED_KMS_KEY" -> (known after apply)
      ~ vpc_endpoint_service_name   = "com.amazonaws.ap-northeast-1.dsql-jmr4" -> (known after apply)
        # (1 unchanged attribute hidden)

      ~ multi_region_properties {
          ~ clusters       = [] -> (known after apply)
            # (1 unchanged attribute hidden)
        }
    }

  # aws_dsql_cluster_peering.osaka_to_soul will be created
  + resource "aws_dsql_cluster_peering" "osaka_to_soul" {
      + clusters       = [
          + (known after apply),
        ]
      + identifier     = (known after apply)
      + witness_region = "ap-northeast-2"
    }

  # aws_dsql_cluster_peering.tokyo_to_soul will be created
  + resource "aws_dsql_cluster_peering" "tokyo_to_soul" {
      + clusters       = [
          + (known after apply),
        ]
      + identifier     = (known after apply)
      + witness_region = "ap-northeast-2"
    }

Plan: 4 to add, 0 to change, 2 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_dsql_cluster.osaka: Destroying...
aws_dsql_cluster.tokyo: Destroying...
aws_dsql_cluster.osaka: Still destroying... [10s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [10s elapsed]
aws_dsql_cluster.osaka: Still destroying... [20s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [20s elapsed]
aws_dsql_cluster.osaka: Still destroying... [30s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [30s elapsed]
aws_dsql_cluster.osaka: Still destroying... [40s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [40s elapsed]
aws_dsql_cluster.osaka: Still destroying... [50s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [50s elapsed]
aws_dsql_cluster.osaka: Still destroying... [1m0s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [1m0s elapsed]
aws_dsql_cluster.osaka: Still destroying... [1m10s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [1m10s elapsed]
aws_dsql_cluster.osaka: Destruction complete after 1m17s
aws_dsql_cluster.osaka: Creating...
aws_dsql_cluster.osaka: Creation complete after 1s
aws_dsql_cluster.tokyo: Still destroying... [1m20s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [1m30s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [1m40s elapsed]
aws_dsql_cluster.tokyo: Still destroying... [1m50s elapsed]
aws_dsql_cluster.tokyo: Destruction complete after 1m58s
aws_dsql_cluster.tokyo: Creating...
aws_dsql_cluster.tokyo: Creation complete after 1s
aws_dsql_cluster_peering.tokyo_to_soul: Creating...
aws_dsql_cluster_peering.osaka_to_soul: Creating...
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [10s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [10s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [20s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [20s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [30s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [30s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [40s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [40s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [50s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [50s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [1m0s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [1m0s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [1m10s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [1m10s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [1m20s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [1m20s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [1m30s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [1m30s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [1m40s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [1m40s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [1m50s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [1m50s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [2m0s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [2m0s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Still creating... [2m10s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [2m10s elapsed]
aws_dsql_cluster_peering.tokyo_to_soul: Creation complete after 2m18s
aws_dsql_cluster_peering.osaka_to_soul: Still creating... [2m20s elapsed]
aws_dsql_cluster_peering.osaka_to_soul: Creation complete after 2m29s

Apply complete! Resources: 4 added, 0 changed, 2 destroyed.

問題なく作成されたようですね。DSQLクラスターの再作成の場合は1秒で起動されるという知見を得ました。

AWSマネジメントコンソール側も確認しましょう。

東京リージョンのDSQLでは、ピアリージョンに大阪のDSQLクラスターが。ウィットネスリージョンにソウルが設定されています。

CleanShot 2025-07-08 at 02.49.29

大阪リージョンのDSQLではその逆、ピアリージョンに東京のDSQLクラスターが。ウィットネスリージョンは同じくソウルが設定できています。

CleanShot 2025-07-08 at 02.50.35

想定通り設定できました。

検証時、一度エラーとなりマルチリージョンクラスターを作成し直したので、最後にその内容を紹介します。

当初は、aws_dsql_cluster_peeringのページに記載の Basic Usage を参考に以下のように記載していました。

dsql-multi-cluster.tf
resource "aws_dsql_cluster" "tokyo" {
  provider = aws.tokyo

  multi_region_properties {
    witness_region = "ap-northeast-2"
  }
}

resource "aws_dsql_cluster" "osaka" {
  provider = aws.osaka

  multi_region_properties {
    witness_region = "ap-northeast-2"
  }
}

resource "aws_dsql_cluster_peering" "tokyo_to_soul" {
  provider       = aws.tokyo
  identifier     = aws_dsql_cluster.tokyo.identifier
  clusters       = [aws_dsql_cluster.osaka.arn]
  witness_region = aws_dsql_cluster.tokyo.multi_region_properties[0].witness_region
}

resource "aws_dsql_cluster_peering" "osaka_to_soul" {
  provider       = aws.osaka
  identifier     = aws_dsql_cluster.osaka.identifier
  clusters       = [aws_dsql_cluster.tokyo.arn]
  witness_region = aws_dsql_cluster.osaka.multi_region_properties[0].witness_region
}

→ aws_dsql_cluster.tokyoおよびaws_dsql_cluster.osakaにて、deletion_protection_enabled = trueを定義していない点が差分

この記載だとDSQLクラスターの作成自体は成功しましたが、aws_dsql_clusterのリソース定義に必要なdeletion_protection_enabledが定義できていないためか、Provider produced inconsistent result after applyのエラーとなってしまいました。

> tf apply
aws_dsql_cluster.single: Refreshing state...

〜中略〜

aws_dsql_cluster.tokyo: Creating...
aws_dsql_cluster.osaka: Creating...
╷
│ Error: Provider produced inconsistent result after apply
│ 
│ When applying changes to aws_dsql_cluster.tokyo, provider "provider[\"registry.terraform.io/hashicorp/aws\"].tokyo" produced an
│ unexpected new value: .deletion_protection_enabled: was null, but now cty.True.
│ 
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.
╵
╷
│ Error: Provider produced inconsistent result after apply
│ 
│ When applying changes to aws_dsql_cluster.osaka, provider "provider[\"registry.terraform.io/hashicorp/aws\"].osaka" produced an
│ unexpected new value: .deletion_protection_enabled: was null, but now cty.True.
│ 
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.

AWS Providerのバグのように見えますが、直近はdeletion_protection_enabledを定義するようにしましょう。

さいごに

ここまで、Terraform AWS Provider v5.100.0でサポートされたAurora DSQLを検証環境でデプロイしてみた様子を紹介しました。

Aurora DSQLの念願のTerraformサポート、待ち焦がれた方もいたのではないでしょうか?今後、たくさん使い倒していきたいですね。

以上です。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.