My Note

自己理解のためのブログ

Terraform ( v0.11.14 ) でAWSの環境構築 (Redis)

やったこと

  • TerraformでAWSのElastiCache( redis ) を構築する
    • vpc_id はssmパラメータから取得
    • subnet_id はTerraformの機能でフィルタ ( NameTag ) をかけて動的に取得
    • security-group_id はTerraformの機能でフィルタ ( NameTag ) をかけて動的に取得
    • Envは workspace で管理
    • dev/stgは自動フェイルオーバはFalse、prodはTrue
    • dev/stgはcluster-nodeは1台、prodは2台
    • 実行するTerraformのバージョンは 0.11.14

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

f:id:yhidetoshi:20190621223242p:plain

Redisクラスタを構築するために必要な情報を取得する

■ ssmパラメータに格納しているvpc_idの値を取得する

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

AWSに存在するsecurit-group_idをNameTagが cache のidを取得する

// dbのSecurityGroupのidを取得する
data "aws_security_group" "cache" {
  vpc_id = "${data.aws_ssm_parameter.vpc_id.value}"

  tags {
    Name = "cache"
  }
}

AWSに存在するsubnet-idをNameTagが cache-ccache-d の値をそれぞれ取得する

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

  tags {
    Name = "cache-c"
  }
}

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

  tags {
    Name = "cache-d"
  }
}

Envによってリソースを変更する

workspace でEnv毎に処理を切り替えることをします。 ${terraform.workspace} の値にEnvの値のdev, stg, prodとなる。 以下のようにworkspaceを作成・切り替え・一覧などの操作ができる。

■ terraform workspaceコマンド例

// terraform workspaceコマンド
$ terraform workspace help
Usage: terraform workspace

  New, list, select and delete Terraform workspaces.

// workspaceを作成
$ terraform workspace new prod
Created and switched to workspace "prod"!

// workspaceを切り替える
$ terraform workspace select dev
Switched to workspace "dev".

// workspaceのlist表示
$ terraform workspace list
  default
* dev
  prod
  stg

■ Terraformのif文 ( conditionals )

Terraformの公式ドキュメント ( Conditionals ) を利用して構築する環境 ( dev / stg / prod ) を変更する。

redisの構築環境を dev/stgとprodで条件分岐させてみる。

■ redis.tfのコード抜粋

  number_cache_clusters         = "${terraform.workspace == "prod" ? 2 : 1}"
  automatic_failover_enabled    = "${terraform.workspace == "prod" ? true : false}"
  • number_cache_clusters
    • prod だったら 2, それ以外( dev / stg ) だったら 1 がセットされる
  • automatic_failover_enabled
    • prod だったら true, それ以外 ( dev / stg )だったら false がセットされる

コード全体

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

├── modules
│   ├── elasticache
│   │   └── redis
│   │       └── main.tf ( resource側 )
├── redis.tf            ( module側 )
├── s3-backend.tf

■ module側 ( redis.tf )

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

// dbのSecurityGroupのidを取得する
data "aws_security_group" "cache" {
  vpc_id = "${data.aws_ssm_parameter.vpc_id.value}"

  tags {
    Name = "cache"
  }
}

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

  tags {
    Name = "cache-c"
  }
}

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

  tags {
    Name = "cache-d"
  }
}

locals {
  vpc_security_group_redis_ids_anyenv = ["${data.aws_security_group.cache.id}"]
  cache_subnet_ids_anyenv             = ["${data.aws_subnet_ids.cache-c.ids}", "${data.aws_subnet_ids.cache-d.ids}"]
  vpc_security_group_redis_ids        = "${split(",",join(",",local.vpc_security_group_redis_ids_anyenv))}"
  cache_subnet_ids                    = "${split(",",join(",",local.cache_subnet_ids_anyenv))}"
}

module "redis-cluster" {
  source                        = "./modules/elasticache/redis"
  parameter_group_name          = "default.redis3.2"
  engine_version                = "3.2.4"
  port                          = 6379
  subnet_group_name             = "redis"
  node_type                     = "cache.t2.small"
  replication_group_description = "test description"
  name                          = "redis"
  snapshot_retention_limit      = 0
  replication_group_id          = "redis-${terraform.workspace}"
  security_group_ids            = "${split(",",join(",",local.vpc_security_group_redis_ids_anyenv))}"
  subnet_ids                    = "${split(",",join(",",local.cache_subnet_ids))}"
  number_cache_clusters         = "${terraform.workspace == "prod" ? 2 : 1}"
  automatic_failover_enabled    = "${terraform.workspace == "prod" ? true : false}"
}

■ resource側 ( main.tf )

variable "security_group_ids" {
  default = []
}

variable "subnet_ids" {
  default = []
}

variable "parameter_group_name" {}
variable "engine_version" {}
variable "port" {}
variable "node_type" {}
variable "replication_group_description" {}
variable "replication_group_id" {}
variable "snapshot_retention_limit" {}
variable "subnet_group_name" {}
variable "automatic_failover_enabled" {}
variable "name" {}
variable "number_cache_clusters" {}

resource "aws_elasticache_replication_group" "redis" {
  replication_group_id          = "${var.replication_group_id}"
  replication_group_description = "${var.replication_group_description}"
  node_type                     = "${var.node_type}"
  port                          = "${var.port}"
  engine_version                = "${var.engine_version}"
  security_group_ids            = ["${var.security_group_ids}"]
  parameter_group_name          = "${var.parameter_group_name}"
  subnet_group_name             = "${var.subnet_group_name}"
  automatic_failover_enabled    = "${var.automatic_failover_enabled}"
  number_cache_clusters         = "${var.number_cache_clusters}"
  snapshot_retention_limit      = "${var.snapshot_retention_limit}"
  depends_on                    = ["aws_elasticache_subnet_group.redis"]
}

resource "aws_elasticache_subnet_group" "redis" {
  name       = "${var.name}"
  subnet_ids = ["${var.subnet_ids}"]
}

まとめ

今回は以下のことに取り組み、環境(Env)に応じたRedis Clusterを構築した。

  • vpc_id はssmパラメータから取得
  • subnet_id はTerraformの機能で動的取得
  • security-group_id はTerraformの機能で動的取得
  • terraform workspace コマンドでEnv分離
  • terraformのcondition を利用

conditionでRedisの engine_versionnode_type もEnvに応じた定義をすることができる。