My Note

自己理解のためのブログ

Terraform ( v0.12.0 ) でSSMパラメータと連携してAurora ( MySQL ) を構築する

やったこと

yhidetoshi.hatenablog.com

で書いたコードをTerraformのバージョンを0.11.14から0.12.0アップデートして書き直してみた。 RDSクラスターを作成する説明については上記リンクのブログに記載しています。

■ 構築する構成図 (workspace=prod)

f:id:yhidetoshi:20190618080124p:plain
terraform-rds-latest

変更点

  • サブネットIDを取得するためにNameTagの検索で * を活用 ( redis-cとredis-dを取得する )
// subnet-idを取得する
data "aws_subnet_ids" "redis" {
  vpc_id = data.aws_ssm_parameter.redis_vpc_id.value

  tags = {
    Name = "redis-*"
  }
}
  • vpcを作成するコードで0.12.0で書き直したところは 変数を以下のように書き換えができる。
    • First-Class Expressions
      • (変更前): "${var.hoge}"
      • (変更後): var.hoge

■ 参考: HashiCorp Terraform 0.12 Preview: First-Class Expressions

サブネットIDをセットする方法を変更した

ディレクトリ構造

── modules
│   ├── rds
│   │   └── aurora-mysql
│   │       └── main.tf
├── rds.tf
├── s3-backend.tf

■ 変更前 (subnet_idに関わるところを抜粋)

///////////////////////
// module側 (rds.tf) //
///////////////////////

// dbサブネットのidを取得する
data "aws_subnet_ids" "db-c" {
  vpc_id = "${data.aws_ssm_parameter.vpc_id.value}"

  tags {
    Name = "db-c"
  }
}

// dbサブネットのidを取得する
data "aws_subnet_ids" "db-d" {
  vpc_id = "${data.aws_ssm_parameter.vpc_id.value}"

  tags {
    Name = "db-d"
  }
}

locals {
  ・・・
  db_subnet_ids_anyenv          = ["${data.aws_subnet_ids.db-c.ids}", "${data.aws_subnet_ids.db-d.ids}"]
  db_subnet_ids                 = "${split(",",join(",",local.db_subnet_ids_anyenv))}"
  ・・・
}

module "create-aurora-mysql" {
  ・・・
  db_subnet_ids               = "${split(",",join(",",local.db_subnet_ids))}"
  ・・・
}

/////////////////////////
// resouce側 (main.tf) //
/////////////////////////

variable "db_subnet_ids" {
  default = []
}

resource "aws_db_subnet_group" "default" {
  name        = "${var.db_subnet_group_name}"
  subnet_ids  = ["${var.db_subnet_ids}"]
  description = "${var.description}"
}

■ 変更後

  • vpc_idを取得してsubnet_id情報を取得する処理りをresouce側だけの処理で完結させた。
/////////////////////////
// resource側 (main.tf) //
/////////////////////////


// subnet-idを取得する
data "aws_subnet_ids" "db" {
  vpc_id = data.aws_ssm_parameter.redis_vpc_id.value

  tags = {
    Name = "db-*"
  }
}

resource "aws_db_subnet_group" "default" {
  name        = var.db_subnet_group_name
  subnet_ids  = data.aws_subnet_ids.db.ids
  description = var.description
}

→ subnet-idをlistで取得して、 resource "aws_db_subnet_group" "default" で取得した subnet_idsは data.aws_subnet_ids.db.idsを参照でき、 subnet_ids にlistで渡すようにした。処理もかなりシンプルにすることができた。

Terraformのコード全体

ディレクトリ構造(一部抜粋)

├── modules
│   ├── rds
│   │   └── aurora-mysql
│   │       └── main.tf ( resource側 )
├── rds.tf         ( module側 )
├── s3-backend.tf

■ Module側 ( rds.tf )

variable "availability_zone_prod" {
  default = ["ap-northeast-1c", "ap-northeast-1d"]
}
variable "availability_zone_stg" {
  default = ["ap-northeast-1c"]
}
variable "availability_zone_dev" {
  default = ["ap-northeast-1c"]
}

locals {
  instance_class_prod = "db.r4.large"
  instance_class_stg  = "db.t2.medium"
  instance_class_dev  = "db.t2.medium"
  availability_zone   = "${split(",", (terraform.workspace == "prod" && terraform.workspace != "stg" && terraform.workspace != "dev") ? join(",", var.availability_zone_prod) : join(",", var.availability_zone_dev))}"
}

module "create-aurora-mysql" {
  source                                = "./modules/rds/aurora-mysql"
  description                           = "for app"
  cluster_identifier                    = "app-db-${terraform.workspace}-cluster"
  identifier                            = "app-db-${terraform.workspace}"
  database_name                         = "app"
  master_username                       = "root"
  engine                                = "aurora-mysql"
  engine_version                        = "5.7.12"
  db_subnet_group_name                  = "app_db"
  db_parameter_group_name               = "app-aurora57"
  db_parameter_group_family             = "aurora-mysql5.7"
  cluster_parameter_group_family        = "aurora-mysql5.7"
  cluster_parameter_group_name          = "app-cluster-aurora57"
  preferred_backup_window_cluster       = "20:06-20:36"
  preferred_maintenance_window_instance = "sun:19:00-sun:19:30"
  preferred_maintenance_window_cluster  = "sun:19:00-sun:19:30"
  final_snapshot_identifier             = true
  backup_retention_period               = 7
  auto_minor_version_upgrade            = true
  publicly_accessible                   = false
  storage_encrypted                     = "${terraform.workspace == "prod" ? true : false}"
  instance_class                        = "${terraform.workspace == "prod" ? local.instance_class_prod : terraform.workspace == "stg" ? local.instance_class_stg : local.instance_class_dev}"
  availability_zone                     = "${split(",", (terraform.workspace != "prod" && terraform.workspace == "stg" && terraform.workspace != "dev") ? join(",", var.availability_zone_stg) : join(",", local.availability_zone))}"
}

■ Resource側 ( rds/aurora-mysql/main.tf )

variable "instance_class" {}
variable "description" {}
variable "identifier" {}
variable "cluster_identifier" {}
variable "database_name" {}
variable "master_username" {}
variable "engine" {}
variable "engine_version" {}
variable "db_subnet_group_name" {}
variable "db_parameter_group_name" {}
variable "db_parameter_group_family" {}
variable "cluster_parameter_group_name" {}
variable "cluster_parameter_group_family" {}
variable "preferred_backup_window_cluster" {}
variable "preferred_maintenance_window_cluster" {}
variable "preferred_maintenance_window_instance" {}
variable "final_snapshot_identifier" {}
variable "backup_retention_period" {}
variable "auto_minor_version_upgrade" {}
variable "publicly_accessible" {}
variable "storage_encrypted" {}

variable "availability_zone" {
  default = []
}

// vpc_idを取得する
data "aws_ssm_parameter" "redis_vpc_id" {
  name = "vpc_id"
}

// subnet-idを取得する
data "aws_subnet_ids" "db" {
  vpc_id = data.aws_ssm_parameter.redis_vpc_id.value

  tags = {
    Name = "db-*"
  }
}
// dbのSecurityGroupのidを取得する
data "aws_security_group" "db" {
  vpc_id = data.aws_ssm_parameter.redis_vpc_id.value

  tags = {
    Name = "db"
  }
}
// dbのpasswordをssmパラメータから取得する
data "aws_ssm_parameter" "db_password" {
  name = "db_password"
}


resource "aws_rds_cluster" "aurora_cluster" {
  cluster_identifier              = var.cluster_identifier
  availability_zones              = var.availability_zone
  database_name                   = var.database_name
  engine                          = var.engine
  master_username                 = var.master_username
  master_password                 = data.aws_ssm_parameter.db_password.value
  db_cluster_parameter_group_name = var.cluster_parameter_group_name
  db_subnet_group_name            = aws_db_subnet_group.default.name
  vpc_security_group_ids          = [data.aws_security_group.db.id]
  preferred_backup_window         = var.preferred_backup_window_cluster
  preferred_maintenance_window    = var.preferred_maintenance_window_cluster
  final_snapshot_identifier       = var.final_snapshot_identifier
  backup_retention_period         = var.backup_retention_period
  storage_encrypted               = var.storage_encrypted
}

resource "aws_rds_cluster_instance" "cluster_instances" {
  count                        = "${length(var.availability_zone)}"
  identifier                   = "${var.identifier}-${count.index+1}"
  cluster_identifier           = aws_rds_cluster.aurora_cluster.id
  instance_class               = var.instance_class
  engine                       = var.engine
  db_subnet_group_name         = aws_db_subnet_group.default.name
  db_parameter_group_name      = var.db_parameter_group_name
  auto_minor_version_upgrade   = var.auto_minor_version_upgrade
  publicly_accessible          = var.publicly_accessible
  preferred_maintenance_window = var.preferred_maintenance_window_instance
}

resource "aws_db_subnet_group" "default" {
  name        = var.db_subnet_group_name
  subnet_ids  = data.aws_subnet_ids.db.ids
  description = var.description
}

resource "aws_db_parameter_group" "default" {
  name        = var.db_parameter_group_name
  family      = var.db_parameter_group_family
  description = var.description
}

resource "aws_rds_cluster_parameter_group" "default" {
  name        = var.cluster_parameter_group_name
  family      = var.cluster_parameter_group_family
  description = var.description
}

まとめ

Terraformのバージョンを 0.11.14 から 0.12.0 にバージョンを上げた。 今回は、以前に作成したRDS(MySQL Aurora)のコードを 0.12.0版に修正した。 付与するサブネットを動的に割り当てる処理をresource側に定義・修正してシンプル化した。 また、変数に "${}" が不要になったので、コードとしてもすっきりするし、書くのが楽になった。