TerraformでAurora Serverless v2を自動構築する

# はじめに
2022/4/22についにGAされた待望のAurora Serverless v2。
v1の弱点であるスケーラビリティを確保して瞬時にスケール可能という夢のようなDBインスタンスの登場だ。

だが、構築が難しくては意味がない。

今回は、~~2022/4/23時点でTerraform未対応の~~Aurora Serverless v2を自動構築をして冪等性を高めてみる。
⇒ 2022/4/28に対応した。

なお、ベースとなるTerraformは[過去の記事](https://qiita.com/neruneruo/items/15d6c5c50cf225bcd1fc)のものを流用している。
周辺リソースについては上記記事を参照していただきたい。

# IaC(過去のバージョンのProviderを使う場合)
全体像としてはこのようになる。

```HCL
################################################################################
# Aurora                                                                       #
################################################################################
resource "aws_rds_cluster" "example" {
  cluster_identifier                  = local.aurora_cluster_identifier
  engine                              = "aurora-postgresql"
  engine_version                      = "13.6"
  engine_mode                         = "provisioned"
  master_username                     = local.aurora_master_username
  master_password                     = local.aurora_master_password
  port                                = 5432
  database_name                       = local.aurora_database_name
  vpc_security_group_ids              = [aws_security_group.aurora.id]
  db_subnet_group_name                = aws_db_subnet_group.example.name
  db_cluster_parameter_group_name     = aws_rds_cluster_parameter_group.example.name

  skip_final_snapshot = true
  apply_immediately   = true
}

resource "aws_rds_cluster_instance" "example" {
  depends_on = [
    null_resource.aws_rds_cluster_add_serverless_v2_scaling_configuration,
  ]

  cluster_identifier = aws_rds_cluster.example.id
  identifier         = "${local.aurora_cluster_identifier}-serverless-instance"

  engine                  = aws_rds_cluster.example.engine
  engine_version          = aws_rds_cluster.example.engine_version
  instance_class          = "db.serverless"
  db_subnet_group_name    = aws_db_subnet_group.example.name
  db_parameter_group_name = aws_db_parameter_group.example.name

  monitoring_role_arn = aws_iam_role.aurora_monitoring.arn
  monitoring_interval = 60

  publicly_accessible = true
}

resource "aws_db_subnet_group" "example" {
  name       = local.db_subnet_group_name
  subnet_ids = data.aws_subnet_ids.my_vpc.ids
}

resource "aws_rds_cluster_parameter_group" "example" {
  name   = local.rdscluster_parameter_group_name
  family = "aurora-postgresql13"
}

resource "aws_db_parameter_group" "example" {
  name   = local.db_parameter_group_name
  family = "aurora-postgresql13"

  parameter {
    apply_method = "pending-reboot"
    name         = "shared_preload_libraries"
    value        = "pg_stat_statements,pg_hint_plan"
  }
}

################################################################################
# Modify DB Cluster                                                            #
#   Add Serverless v2 Scaling Configuration                                    #
################################################################################
resource "null_resource" "aws_rds_cluster_add_serverless_v2_scaling_configuration" {
  depends_on = [
    aws_rds_cluster.example,
  ]

  provisioner "local-exec" {
    command = <<-EOF
      aws rds modify-db-cluster \
        --db-cluster-identifier ${aws_rds_cluster.example.cluster_identifier} \
        --serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=1
    EOF

    on_failure = fail
  }
}
```

Aurora Serverless v1は、クラスタ全体でサーバレスにするため、```aws_rds_cluster```を```engine_mode = "serverless"```で構築するが、v2の場合はインスタンスとして扱われるため、```engine_mode = "provisioned"```で構築し、```aws_rds_cluster_instance```で```instance_class = "db.serverless"```を指定する。

ただし、上記を指定するためには、クラスタに

```JSON:CLIの実行結果抜粋
        "ServerlessV2ScalingConfiguration": {
            "MinCapacity": 0.5,
            "MaxCapacity": 1.0
        }
```

のように```ServerlessV2ScalingConfiguration```が設定されていないといけないため、

aws_rds_cluster
↓
null_resource(CLI実行)
↓
aws_rds_cluster_instance

の順で作成するように```depends_on```の指定をした。

~~現在はちょっと捻ったことをしないと構築できないが、じきにTerraformが対応したら```aws_rds_cluster```で指定ができるようになるだろう。~~
⇒ 2022/4/28にTerraformがAWS Providerバージョン4.12.0で、```serverlessv2_scaling_configuration```に対応したので追記。


# IaC(AWS Providerバージョン4.12.0以降を扱う場合)
以下のブロックを追記すれば、CLIの呼び出しが不要になる。

```diff_HCL
################################################################################
# Aurora                                                                       #
################################################################################
resource "aws_rds_cluster" "example" {
  cluster_identifier                  = local.aurora_cluster_identifier
  engine                              = "aurora-postgresql"
  engine_version                      = "13.6"
  engine_mode                         = "provisioned"
  master_username                     = local.aurora_master_username
  master_password                     = local.aurora_master_password
  port                                = 5432
  database_name                       = local.aurora_database_name
  vpc_security_group_ids              = [aws_security_group.aurora.id]
  db_subnet_group_name                = aws_db_subnet_group.example.name
  db_cluster_parameter_group_name     = aws_rds_cluster_parameter_group.example.name
  iam_database_authentication_enabled = true

+  serverlessv2_scaling_configuration {
+    min_capacity = 0.5
+    max_capacity = 1.0
+  }

  skip_final_snapshot = true
  apply_immediately   = true

  tags = {
    Name = "r-kubota"
  }
}

resource "aws_rds_cluster_instance" "example" {
  cluster_identifier = aws_rds_cluster.example.id
  identifier         = "${local.aurora_cluster_identifier}-serverless-instance"

  engine                  = aws_rds_cluster.example.engine
  engine_version          = aws_rds_cluster.example.engine_version
  instance_class          = "db.serverless"
  db_subnet_group_name    = aws_db_subnet_group.example.name
  db_parameter_group_name = aws_db_parameter_group.example.name

  monitoring_role_arn = aws_iam_role.aurora_monitoring.arn
  monitoring_interval = 60

  publicly_accessible = true
}

resource "aws_db_subnet_group" "example" {
  name       = local.db_subnet_group_name
  subnet_ids = data.aws_subnet_ids.my_vpc.ids

  tags = {
    Name = "r-kubota"
  }
}

resource "aws_rds_cluster_parameter_group" "example" {
  name   = local.rdscluster_parameter_group_name
  family = "aurora-postgresql13"

  tags = {
    Name = "r-kubota"
  }
}

resource "aws_db_parameter_group" "example" {
  name   = local.db_parameter_group_name
  family = "aurora-postgresql13"

  parameter {
    apply_method = "pending-reboot"
    name         = "shared_preload_libraries"
    value        = "pg_stat_statements,pg_hint_plan"
  }
}
```

これで、よりスケーラブルなサーバレス構成を組むことができるようになった！