Terraform で ElastiCache for Redis を正しく定義する

Posted on

Terraform で ElastiCache for Redis を定義するには少しコツが必要です。社内で間違った定義がコピペされていたので、忘れないようにポイントをまとめておきます。目新しい内容ではなく、ほとんどは公式ドキュメントにちゃんと載っています。

Terraform で ElastiCache for Redis (cluster mode disabled) を定義するには aws_elasticache_clusteraws_elasticache_replication_group の 2 つのリソースがあります。

基本的には aws_elasticache_replication_group を使えば良いです。 Multi-AZ で可用性を高めるなら number_cache_clusters を 2 以上にして automatic_failover_enabled を true にします。

resource "aws_elasticache_replication_group" "example" {
  replication_group_id          = "example"
  replication_group_description = "example"
  node_type                     = "cache.t3.micro"
  number_cache_clusters         = 2
  automatic_failover_enabled    = true
  engine_version                = "5.0.6"
  parameter_group_name          = "default.redis5.0"
}

staging 環境など可用性を落としてコストを抑えたい場合は、ノード数を変数にして automatic_failover_enabled を切り替えます。

variable "node_count" {
  type    = number
  default = 1
}

resource "aws_elasticache_replication_group" "example" {
  replication_group_id          = "example"
  replication_group_description = "example"
  node_type                     = "cache.t3.micro"
  number_cache_clusters         = var.node_count
  automatic_failover_enabled    = var.node_count == 1 ? false : true
  engine_version                = "5.0.6"
  parameter_group_name          = "default.redis5.0"
}

automatic_failover_enabled の値を後から変更する場合は apply_immediately を指定しないと次のメンテナンスウィンドウで適用されます(それまでは意図しない差分が出てしまうので要注意)。

リードレプリカの追加

読み込み性能を上げるためにリードレプリカを追加する場合は aws_elasticache_cluster で明示的にノードを増やします。

resource "aws_elasticache_replication_group" "example" {
  replication_group_id          = "example"
  replication_group_description = "example"
  node_type                     = "cache.t3.micro"
  number_cache_clusters         = 2
  automatic_failover_enabled    = true
  engine_version                = "5.0.6"
  parameter_group_name          = "default.redis5.0"

  lifecycle {
    ignore_changes = ["number_cache_clusters"]
  }
}

resource "aws_elasticache_cluster" "replica" {
  cluster_id           = "replica"
  replication_group_id = aws_elasticache_replication_group.example.id
}

このとき aws_elasticache_replication_group 側に lifecycleignore_changes を指定しないと、ノードを削除したときに意図しないエラーが発生します。

Error: error deleting Elasticache Cache Cluster (<node name>) (removing replica): CacheClusterNotFound: CacheCluster not found: <node name>

あとからタグの追加や変更はできない

ElastiCache のノードにタグを設定する場合は注意が必要です。初回の作成時には付与できますが、あとから追加や変更はできません。たとえば、次のようにあとから tags を定義しても実際のノードには付与されません。

resource "aws_elasticache_replication_group" "example" {
  replication_group_id          = "example"
  replication_group_description = "example"
  node_type                     = "cache.t3.micro"
  number_cache_clusters         = 2
  automatic_failover_enabled    = true
  engine_version                = "5.0.6"
  parameter_group_name          = "default.redis5.0"

  tags = {
    stage = "production"
  }
}

これは Terraform のバグではなく ElastiCache API の仕様です。これは公式ドキュメントにも記載がなく GitHub の Issue で知りました。

最初に知ったときは「えっ、本当に?」と思ったのですが、たしかに AWS CLI にもオプションがありません。 ModifyReplicationGroup の API 仕様を読むとタグは一切見ていないようです。その証拠に Management Console から手動で変更して plan や apply しても差分が出ません。

既存の ElastiCache にコスト配分タグを付けるときなどは注意が必要です(手動で付けて回るしかない)。

おわりに

タグが付与されないのは、当初 Terraform 側のバグを疑っていました。推測ではなく起きている事象をちゃんと観察して、ドキュメントや API 仕様を確認することが大切ですね。