本文へスキップ

count メタ引数

デフォルトでは、リソースブロックは1つの実際のインフラストラクチャオブジェクトを設定します。(同様に、モジュールブロックは、子モジュールの内容を1回だけ設定に含めます。)しかし、時には、それぞれに個別のブロックを作成することなく、いくつかの類似したオブジェクト(計算インスタンスの固定プールなど)を管理したい場合があります。OpenTofuには、これを行うための2つの方法があります:countfor_eachです。

リソースまたはモジュールブロックに、整数を値とするcount引数が含まれている場合、OpenTofuはその数だけインスタンスを作成します。

基本構文

countは、OpenTofu言語で定義されたメタ引数です。モジュールとすべてのリソースタイプで使用できます。

countメタ引数は整数を許容し、その数だけリソースまたはモジュールのインスタンスを作成します。各インスタンスにはそれぞれ異なるインフラストラクチャオブジェクトが関連付けられ、設定が適用されるときにそれぞれ個別に作成、更新、または削除されます。

コードブロック
resource "aws_instance" "server" {
count = 4 # create four similar EC2 instances

ami = "ami-a1b2c3d4"
instance_type = "t2.micro"

tags = {
Name = "Server ${count.index}"
}
}

countオブジェクト

countが設定されているブロックでは、式に追加のcountオブジェクトが使用可能になり、各インスタンスの設定を変更できます。このオブジェクトには1つの属性があります。

  • count.index — このインスタンスに対応する一意のインデックス番号(0から開始)。

countでの式の使用

countメタ引数は数値を受け入れます。ただし、ほとんどの引数とは異なり、countの値は、OpenTofuがリモートリソースアクションを実行する*前*に判明している必要があります。つまり、countは、設定が適用された後に初めて判明するリソース属性(オブジェクトが作成されたときにリモートAPIによって生成された一意のIDなど)を参照できません。

インスタンスへの参照

countが設定されている場合、OpenTofuはブロック自体と、それに関連付けられた複数のリソースまたはモジュールインスタンスを区別します。インスタンスは、0から始まるインデックス番号で識別されます。

  • <TYPE>.<NAME>またはmodule.<NAME>(例:aws_instance.server)はリソースブロックを参照します。
  • <TYPE>.<NAME>[<INDEX>]またはmodule.<NAME>[<INDEX>](例:aws_instance.server[0]aws_instance.server[1]など)は個々のインスタンスを参照します。

これは、countまたはfor_eachのないリソースやモジュールとは異なり、インデックスやキーなしで参照できます。

同様に、複数のインスタンスを持つ子モジュールからのリソースは、プラン出力やUIの他の場所でmodule.<NAME>[<KEY>]というプレフィックスが付けられます。countまたはfor_eachのないモジュールの場合、モジュールの名前でモジュールを参照できるため、アドレスにモジュールインデックスは含まれません。

countの代わりにfor_eachを使用する場合

インスタンスがほぼ同一である場合、countが適切です。一部の引数に整数から直接導出できない異なる値が必要な場合は、for_eachを使用する方が安全です。

for_eachが利用可能になる前は、リストの長さからcountを導出し、count.indexを使用して元のリストの値を検索することが一般的でした。

コードブロック
variable "subnet_ids" {
type = list(string)
}

resource "aws_instance" "server" {
# Create one instance for each subnet
count = length(var.subnet_ids)

ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
subnet_id = var.subnet_ids[count.index]

tags = {
Name = "Server ${count.index}"
}
}

これは脆弱でした。なぜなら、リソースインスタンスはリスト内の文字列値ではなく、その*インデックス*によって識別されていたからです。リストの中央から要素が削除された場合、その要素の後のすべてのインスタンスのsubnet_id値が変更され、意図しないリモートオブジェクトの変更が多くなります。for_eachを使用すると、余分な変更なしに同じ柔軟性が得られます。