Terraformで構築したRDSの、即時反映用のパラメータ設定の詰めが甘かった話

    Terraformで構築したRDSの、即時反映用のパラメータ設定の詰めが甘かった話

    目次

      はじめに

      クラウドインテグレーション部の渡邊です。
      今回は、Terraformを利用して、RDSを構築する際に設定可能なapply_immediatelyについて検証しました。
      apply_immediatelyは設定値の変更を、すぐに適用するための設定です。
      aws_rds_clusterapply_immediatelytrueにしている状況でca_cert_identifierの設定値を変更したところ、設定が即時反映されていない事象が確認されました。
      なぜこのようなことが起こってしまったか、動作確認しながら見ていきましょう。

      環境情報

      • Terraform v1.2.6
      • macOS 13.4

      発生事象詳細

      今回使用した初期コードはこちらです。
      ネットワークリソース等は、既存環境の値を用いる想定でコードを作成しました。
      variableは省略しているため、ご自身の環境に合ったものをご用意ください。

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

      terraform {
      required_version = "~> 1.6.5"
      backend "s3" {
      bucket = "test-bucket"
      key = "actions/rds/terraform.tfstate"
      region = "ap-northeast-1"
      }
      required_providers {
      aws = {
      source = "hashicorp/aws"
      version = "~> 5.29.0"
      }
      }
      }

      resource "aws_db_subnet_group" "db-subgp" {
      name = "test-dbsg"
      subnet_ids = [
      var.subnet-1a,
      var.subnet-1c
      ]
      }

      resource "aws_rds_cluster" "db" {
      cluster_identifier = "test-db-cluster"
      db_cluster_parameter_group_name = "default.aurora-mysql8.0"
      db_subnet_group_name = aws_db_subnet_group.db-subgp.name
      vpc_security_group_ids = [var.sg]
      engine_mode = "provisioned"
      master_username = "admin"
      master_password = "Passw0rd!"
      engine = "aurora-mysql"
      engine_version = "8.0.mysql_aurora.3.02.0"
      port = 3306
      apply_immediately = false
      serverlessv2_scaling_configuration {
      max_capacity = 64
      min_capacity = 0.5
      }
      }

      resource "aws_rds_cluster_instance" "db-instance" {
      identifier = "test-db-instance-01"
      cluster_identifier = aws_rds_cluster.db.id
      instance_class = "db.serverless"
      engine = aws_rds_cluster.db.engine
      engine_version = aws_rds_cluster.db.engine_version
      ca_cert_identifier = "rds-ca-2019"
      }

      aws_rds_clusterapply_immediatelyTrueにしている状況で、ca_cert_identifierの値を、rds-ca-2019からrds-ca-rsa2048-g1に変更します。
      その後、terraform planコマンドで、設定変更されるリソースを確認します。

      $ terraform plan               
      aws_db_subnet_group.db-subgp: Refreshing state... [id=test-dbsg]
      aws_rds_cluster.db: Refreshing state... [id=test-db-cluster]
      aws_rds_cluster_instance.db-instance: Refreshing state... [id=test-db-instance-01]

      Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
      symbols:
      ~ update in-place

      Terraform will perform the following actions:

      # aws_rds_cluster.db will be updated in-place
      ~ resource "aws_rds_cluster" "db" {
      ~ apply_immediately = false -> true
      id = "test-db-cluster"
      tags = {}
      # (37 unchanged attributes hidden)

      # (1 unchanged block hidden)
      }

      # aws_rds_cluster_instance.db-instance will be updated in-place
      ~ resource "aws_rds_cluster_instance" "db-instance" {
      ~ ca_cert_identifier = "rds-ca-2019" -> "rds-ca-rsa2048-g1"
      id = "test-db-instance-01"
      tags = {}
      # (26 unchanged attributes hidden)
      }

      Plan: 0 to add, 2 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.

      terraform applyコマンドで設定を適用します。

      $ terraform apply -auto-approve
      aws_db_subnet_group.db-subgp: Refreshing state... [id=test-dbsg]
      aws_rds_cluster.db: Refreshing state... [id=test-db-cluster]
      aws_rds_cluster_instance.db-instance: Refreshing state... [id=test-db-instance-01]

      Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
      symbols:
      ~ update in-place

      Terraform will perform the following actions:

      # aws_rds_cluster.db will be updated in-place
      ~ resource "aws_rds_cluster" "db" {
      ~ apply_immediately = false -> true
      id = "test-db-cluster"
      tags = {}
      # (37 unchanged attributes hidden)

      # (1 unchanged block hidden)
      }

      # aws_rds_cluster_instance.db-instance will be updated in-place
      ~ resource "aws_rds_cluster_instance" "db-instance" {
      ~ ca_cert_identifier = "rds-ca-2019" -> "rds-ca-rsa2048-g1"
      id = "test-db-instance-01"
      tags = {}
      # (26 unchanged attributes hidden)
      }

      Plan: 0 to add, 2 to change, 0 to destroy.
      aws_rds_cluster.db: Modifying... [id=test-db-cluster]
      aws_rds_cluster.db: Still modifying... [id=test-db-cluster, 10s elapsed]
      aws_rds_cluster.db: Still modifying... [id=test-db-cluster, 20s elapsed]
      aws_rds_cluster.db: Still modifying... [id=test-db-cluster, 30s elapsed]
      aws_rds_cluster.db: Modifications complete after 31s [id=test-db-cluster]
      aws_rds_cluster_instance.db-instance: Modifying... [id=test-db-instance-01]
      aws_rds_cluster_instance.db-instance: Still modifying... [id=test-db-instance-01, 10s elapsed]
      aws_rds_cluster_instance.db-instance: Still modifying... [id=test-db-instance-01, 20s elapsed]
      aws_rds_cluster_instance.db-instance: Still modifying... [id=test-db-instance-01, 30s elapsed]
      aws_rds_cluster_instance.db-instance: Modifications complete after 31s [id=test-db-instance-01]

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

      設定変更に成功しましたが、実機の値を確認すると設定変更が行われていません。
      202401_terraform_applyimmediately_01

      aws rds describe-db-instancesコマンドで情報を確認すると、設定変更が次回のメンテナンスウィンドウで適用されることがわかります(抜粋)。

                  "PreferredMaintenanceWindow": "sun:14:40-sun:15:10",
      "PendingModifiedValues": {
      "CACertificateIdentifier": "rds-ca-rsa2048-g1"
      }

      terraform planコマンドで、変更されるリソースを確認すると、以下の通りステートファイルと実機の値に差異があります(抜粋)。
      ステートファイルは、Terraformが管理対象とするインフラの状態を保存するものです。

        # aws_rds_cluster_instance.db-instance will be updated in-place
      ~ resource "aws_rds_cluster_instance" "db-instance" {
      ~ ca_cert_identifier = "rds-ca-2019" -> "rds-ca-rsa2048-g1"
      id = "test-db-instance-01"
      tags = {}
      # (27 unchanged attributes hidden)
      }

      ドキュメントの情報から以下がわかります。

      • クラスターの設定変更を即時反映させたい場合は、aws_rds_clusterapply_immediatelyの値をtrueにする(デフォルトはfalse
      • インスタンスの設定変更を即時反映させたい場合は、aws_rds_cluster_instanceapply_immediatelyの値をtrueにする(デフォルトはfalse

      apply_immediately - (Optional) Specifies whether any database modifications are applied immediately, or during the next maintenance window. Default isfalse.

      引用元:Resource: aws_rds_cluster_instance

      apply_immediately - (Optional) Specifies whether any cluster modifications are applied immediately, or during the next maintenance window. Default is false. See Amazon RDS Documentation for more information.

      引用元:Resource: aws_rds_cluster

      今回は、aws_rds_cluster_instanceapply_immediatelyの値をtrueに設定していなかったため、即時反映されていないと考えられます。
      apply_immediatelytrueにして、再度設定変更を適用します。

      $ terraform apply -auto-approve
      aws_db_subnet_group.db-subgp: Refreshing state... [id=test-dbsg]
      aws_rds_cluster.db: Refreshing state... [id=test-db-cluster]
      aws_rds_cluster_instance.db-instance: Refreshing state... [id=test-db-instance-01]

      Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
      ~ update in-place

      Terraform will perform the following actions:

      # aws_rds_cluster_instance.db-instance will be updated in-place
      ~ resource "aws_rds_cluster_instance" "db-instance" {
      ~ apply_immediately = false -> true
      ~ ca_cert_identifier = "rds-ca-2019" -> "rds-ca-rsa2048-g1"
      id = "test-db-instance-01"
      tags = {}
      # (26 unchanged attributes hidden)
      }

      Plan: 0 to add, 1 to change, 0 to destroy.
      aws_rds_cluster_instance.db-instance: Modifying... [id=test-db-instance-01]
      aws_rds_cluster_instance.db-instance: Still modifying... [id=test-db-instance-01, 10s elapsed]
      aws_rds_cluster_instance.db-instance: Still modifying... [id=test-db-instance-01, 20s elapsed]
      aws_rds_cluster_instance.db-instance: Still modifying... [id=test-db-instance-01, 30s elapsed]
      aws_rds_cluster_instance.db-instance: Modifications complete after 32s [id=test-db-instance-01]

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

      設定変更が即時反映され、ステートファイルと実機の値に、差異はないことが以下の情報からわかります。
      202401_terraform_applyimmediately_02

      $ terraform plan               
      aws_db_subnet_group.db-subgp: Refreshing state... [id=test-dbsg]
      aws_rds_cluster.db: Refreshing state... [id=test-db-cluster]
      aws_rds_cluster_instance.db-instance: Refreshing state... [id=test-db-instance-01]

      No changes. Your infrastructure matches the configuration.

      Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

       

      即時反映の設定値の注意点

      以上で本件は解決ですが、apply_immediatelyの設定において、apply_immediatelyの値を保持する事象が、執筆時点(2023/11/9)で確認されたので注意してください。

      まず、apply_immediatelyの値がtrueの状態から、apply_immediatelyをコメントアウトします。

      resource "aws_rds_cluster_instance" "db-instance" {
      identifier = "test-db-instance-01"
      cluster_identifier = aws_rds_cluster.db.id
      instance_class = "db.serverless"
      engine = aws_rds_cluster.db.engine
      engine_version = aws_rds_cluster.db.engine_version
      # apply_immediately = true
      ca_cert_identifier = "rds-ca-rsa2048-g1"
      }

      ドキュメントの記述(再掲)の通り、デフォルト値はfalseなのでコメントアウトしたらfalseに変更される想定です。

      apply_immediately - (Optional) Specifies whether any database modifications are applied immediately, or during the next maintenance window. Default is false. See Amazon RDS Documentation for more information.

      引用元:Resource: aws_rds_cluster_instance

      ただ、設定変更予定のリソースを確認すると、以下の通り、変更はない旨のメッセージが表示されます。

      $ terraform plan
      aws_db_subnet_group.db-subgp: Refreshing state... [id=test-dbsg]
      aws_rds_cluster.db: Refreshing state... [id=test-db-cluster]
      aws_rds_cluster_instance.db-instance: Refreshing state... [id=test-db-instance-01]

      No changes. Your infrastructure matches the configuration.

      つまりapply_immediatelyの最後に指定した値trueを保持しているということになります。
      apply_immediatelyをコメントアウトした状態で、ca_cert_identifierの値をrds-ca-rsa2048-g1からrds-ca-2019に変更します。
      terraform applyコマンドで設定変更を適用します(抜粋)。

      Terraform will perform the following actions:

      # aws_rds_cluster_instance.db-instance will be updated in-place
      ~ resource "aws_rds_cluster_instance" "db-instance" {
      ~ ca_cert_identifier = "rds-ca-rsa2048-g1" -> "rds-ca-2019"
      id = "test-db-instance-01"
      tags = {}
      # (27 unchanged attributes hidden)
      }

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

      (略)

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

      設定の適用に成功したため、設定値を確認すると、設定変更が即時反映されてました。
      202401_terraform_applyimmediately_01

      では、apply_immediatelyfalseにして、ca_cert_identifierの値をrds-ca-2019からrds-ca-rsa2048-g1に変更して、再確認します。

      $ terraform apply -auto-approve
      aws_db_subnet_group.db-subgp: Refreshing state... [id=test-dbsg]
      aws_rds_cluster.db: Refreshing state... [id=test-db-cluster]
      aws_rds_cluster_instance.db-instance: Refreshing state... [id=test-db-instance-01]

      Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
      ~ update in-place

      Terraform will perform the following actions:

      # aws_rds_cluster_instance.db-instance will be updated in-place
      ~ resource "aws_rds_cluster_instance" "db-instance" {
      ~ apply_immediately = true -> false
      ~ ca_cert_identifier = "rds-ca-2019" -> "rds-ca-rsa2048-g1"
      id = "test-db-instance-01"
      tags = {}
      # (26 unchanged attributes hidden)
      }

      Plan: 0 to add, 1 to change, 0 to destroy.
      aws_rds_cluster_instance.db-instance: Modifying... [id=test-db-instance-01]
      aws_rds_cluster_instance.db-instance: Still modifying... [id=test-db-instance-01, 10s elapsed]
      aws_rds_cluster_instance.db-instance: Still modifying... [id=test-db-instance-01, 20s elapsed]
      aws_rds_cluster_instance.db-instance: Still modifying... [id=test-db-instance-01, 30s elapsed]
      aws_rds_cluster_instance.db-instance: Modifications complete after 31s [id=test-db-instance-01]

      すると、コンソールの設定値とaws rds describe-db-instances実行結果(抜粋)から、設定がまだ反映されていないことが確認できました。
      202401_terraform_applyimmediately_01

                  "PendingModifiedValues": {
      "CACertificateIdentifier": "rds-ca-rsa2048-g1"
      },

      今回は、ca_cert_identifierのみ検証対象としているため、他の設定が同様の挙動であるかわかりませんのでご注意ください。

      まとめ

      • apply_immediatelyはクラスター(aws_rds_cluster)およびインスタンス(aws_rds_cluster_instance)に設定可能である
        • クラスターの設定変更を即時反映させたい場合は、aws_rds_clusterapply_immediatelyの値をtrueにする(デフォルトはfalse
        • インスタンスの設定変更を即時反映させたい場合は、aws_rds_cluster_instanceapply_immediatelyの値をtrueにする(デフォルトはfalse
      • apply_immediatelytrueの設定適用後、apply_immediatelyを設定値ごと消した場合、デフォルト値のfalseにならない

       

      【参考】
      Resource: aws_rds_cluster
      Resource: aws_rds_cluster_instance