はじめに
久しぶりの投稿になります。
現場が変わり、今までよく使っていたAWS CDKではなく、Terraformを使う機会が増えました。
改めてTerraformに向き合う中で新たに知ったcount引数について、色々と使うケースがありそうだと感じたので、簡単にまとめておきます。
対象読者
- Terraformをある程度理解している方
- countについて知らない方
- count関数について知ってるけど、使ったことない・使うべきシーンがわからない方
この記事でわかること
- count引数の挙動
- count引数の使い道について
count関数の概要
count引数とは
count引数は、Terraformのresourceおよびmoduleブロック内で使用できるメタ引数の1つです。
この引数に0以上の整数値を設定することで、同じ設定を持つ複数のインスタンスをまとめて作成することができます。
これにより、コードの重複を大幅に削減し、スケールアウトを容易に実現します。
例えば、「同じスペックのWebサーバを3台デプロイしたい」といった場合に、リソースブロックを3つ記述する代わりに、count = 3
と設定するだけで済みます。
count引数の挙動
- リソースの生成
countに設定された数(N)に基づき、Terraformは0 ~ N-1までのインデックスを持つリソースインスタンスを生成 - count.indexの利用
生成された各インスタンスの設定内で、特殊な変数count.index
を使用して、現在のインスタンスのインデックス番号を参照できる - インスタンスの識別
count.indexを利用することで、各インスタンスにユニークな名前や設定を与えることができ、区別されたリソース群を作成できる
count引数を実際に使った例
ここでは、複数のEC2インスタンスを異なる設定でデプロイする例を示します。
準備:変数とデータソースの定義
variable "az_names" {
description = "インスタンスをデプロイするAZのリスト"
type = list(string)
default = ["ap-northeast-1a", "ap-northeast-1c"]
}
# AZのデータソースを取得
data "aws_availability_zones" "available" {
state = "available"
}
EC2リソースブロックでのcount利用
resource "aws_instance" "web" {
# count = 2 と同義。variableのaz-namesの数と同じだけインスタンスを生成する
count = length(var.az_names)
ami = "ami-0abcdef....."
instance_type = "t2.micro"
# 🌟 count.indexを使って、インスタンスgoogletに異なるAZを割り当てる
availability_zone = element(var.az_names, count.index)
# 🌟 count.indexを使って、インスタンスごとにユニークな名前をつける
tags = {
Name = "web-server-${count.index + 1}"
Index = count.index
AZ_Name = element(var.az_names, count.index)
}
}
実行結果としては、
Nameタグが"web-server-1" の aws_instance.web[0] が ap-northeast-1aにデプロイされ、
Nameタグが"web-server-2" の aws_instance.web[1] が ap-northeast-1cにデプロイされます。
count引数を活用したリソースの条件付き作成
リソースの複数同時生成のほかに、count引数の特性を活用した”リソースを作成するかどうか”を制御する条件文としての使い方も紹介しておきます。
variable "enable_nat_gateway" {
type = bool
default = true
}
resource "aws_nat_gateway" "nat" {
# var.enable_nat_gatewayがtrueの場合に1を返し、リソースを返す
# falseの場合は0が返り、リソースを作成しない
count = var.enable_nat_gateway ? 1 : 0
# NAT Gatewayの設定
...
..
.
}
上記はenable_nat_gateway
という引数の値によって、リソースを作成するかどうかを条件づけている書き方になります。
count = var.environment = "prod" ? 1 : 0
のようにして、環境ごとにリソース差分を吸収させる記述も良さそうです。
参考
Terraform公式リファレンス:https://developer.hashicorp.com/terraform/language/meta-arguments#count