🦊

TerraformでProvisionedとServerlessが混在するAurora MySQLクラスターを作成する

2022/05/14に公開

先日一般公開されたAurora Serverless v2ではProvisionedクラスター内にProvisionedインスタンスとServerlessインスタンスを混在させることができます。
いきなり全部Serverlessにするのはちょっと、、という場合に試しにReaderだけServerlessにしてみるといったことが可能です。
こちらをTerraformで試してみました。
https://aws.amazon.com/jp/blogs/news/amazon-aurora-serverless-v2-is-generally-available-instant-scaling-for-demanding-workloads/

サンプルコード

https://github.com/kishii4726/mixed-provisioned-and-serverless-with-aurora

解説

aws providerのバージョン

まずTerraformでAurora Serverless v2を扱うためにaws providerのバージョンを4.12.0以上にします。

https://github.com/hashicorp/terraform-provider-aws/releases/tag/v4.12.0

version.tf
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.12.0"
    }
  }

クラスター

Provisionedクラスターの中にServerlessインスタンスを作成する形になるためengine_modeprovisionedにします。
Aurora Serverless v2が対応しているのは20220513時点でAurora MySQL 3.02.0もしくはAurora PostgreSQL 13.6のみなのでengine_versionでは8.0.mysql_aurora.3.02.0を指定します。
serverlessv2_scaling_configurationでACUの下限と上限を設定します。

aws_rds_cluster
resource "aws_rds_cluster" "this" {
  engine          = "aurora-mysql"
  engine_mode     = "provisioned"
  engine_version  = local.engine_version
  master_username = local.master_username
  master_password = data.aws_ssm_parameter.db_password.value
  port            = 3306
  availability_zones = [
    "ap-northeast-1a",
    "ap-northeast-1c",
    "ap-northeast-1d",
  ]
  cluster_identifier = "${local.prefix}-cluster"
  serverlessv2_scaling_configuration {
    min_capacity = local.min_capacity
    max_capacity = local.max_capacity
  }
  storage_encrypted               = true
  kms_key_id                      = aws_kms_key.this.arn
  backup_retention_period         = local.backup_retention_period
  db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.this.name
  db_subnet_group_name            = aws_db_subnet_group.this.name
  enabled_cloudwatch_logs_exports = [
    "audit",
    "error",
    "general",
    "slowquery",
  ]
  preferred_backup_window      = "18:00-18:30"
  preferred_maintenance_window = "sun:17:00-sun:17:30"
  skip_final_snapshot          = true
  tags = {
    "Name" = "${local.prefix}-cluster"
  }
  vpc_security_group_ids = [
    aws_security_group.this.id,
  ]
  lifecycle {
    ignore_changes = [
      availability_zones,
    ]
  }
}

ACU(Aurora Capacity Unit)

ACUはAurora Serverlessのスペック設定を行うための単位です。
1ACUで2GiBのメモリとそれに関連するCPUとネットワークが提供されます。
Aurora Serverless v2では0.5~128GiBの間で0.5刻みで下限と上限が設定可能です。
ACUUtilizationというメトリクスでACUの使用率を確認することができます。

インスタンス

Provisioned用とServerless用の2つのaws_rds_cluster_instanceを用意します。
それぞれcountで指定された数だけインスタンスが作成されます。

aws_rds_cluster_instance
resource "aws_rds_cluster_instance" "provisioned" {
  count                        = local.provisioned.count
  identifier                   = "${local.prefix}-instance-provisioned-${count.index}"
  cluster_identifier           = aws_rds_cluster.this.id
  instance_class               = local.provisioned.instance_class
  engine                       = aws_rds_cluster.this.engine
  engine_version               = aws_rds_cluster.this.engine_version
  db_parameter_group_name      = aws_db_parameter_group.this.name
  auto_minor_version_upgrade   = false
  performance_insights_enabled = local.provisioned.performance_insights_enabled
}

resource "aws_rds_cluster_instance" "serverless" {
  # Create Provisioned instance first so that Provisioned becomes a writer
  depends_on                   = [aws_rds_cluster_instance.provisioned]
  count                        = local.serverless.count
  identifier                   = "${local.prefix}-aurora-instance-serverless-${count.index}"
  cluster_identifier           = aws_rds_cluster.this.id
  instance_class               = local.serverless.instance_class
  engine                       = aws_rds_cluster.this.engine
  engine_version               = aws_rds_cluster.this.engine_version
  db_parameter_group_name      = aws_db_parameter_group.this.name
  auto_minor_version_upgrade   = false
  performance_insights_enabled = local.serverless.performance_insights_enabled
}

aws_rds_cluster_instanceではwriter/readerを明示的に指定する方法がありません。
writerはProvisionedになるようにしたいので、以下のようにリソース間で依存関係を作り、Serverlessは必ずProvisionedの後に作られるようにします。このようにすることで最初に作られるProvisionedがwriterになります。

depends_on = [aws_rds_cluster_instance.provisioned]

instance_classでインスタンスタイプを指定するとProvisioned、db,serverlessとするとServerlessになります。

# Aurora MySQL 3系ではt3.mediumもしくはt4g.mediumが最小です
instance_class = t4g.medium ##Provisioned
instance_class = db.serverless ##Serverless

構築

サンプルコードをapplyすると以下のようにProvisionedとServerlessが混在したAuroraクラスターを作成することができました。

https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.how-it-works.html#aurora-serverless-v2.how-it-works.scaling

Discussion