- OpenTofu言語
- メタ引数
- count メタ引数
count
メタ引数
特定のリソースまたはモジュールブロックでは、count
とfor_each
の両方を同時に使用することはできません。
デフォルトでは、リソースブロックは1つの実際のインフラストラクチャオブジェクトを設定します。(同様に、モジュールブロックは、子モジュールの内容を1回だけ設定に含めます。)しかし、時には、それぞれに個別のブロックを作成することなく、いくつかの類似したオブジェクト(計算インスタンスの固定プールなど)を管理したい場合があります。OpenTofuには、これを行うための2つの方法があります:count
とfor_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
のないモジュールの場合、モジュールの名前でモジュールを参照できるため、アドレスにモジュールインデックスは含まれません。
ネストされたprovisioner
またはconnection
ブロック内では、特別なself
オブジェクトはリソースブロック全体ではなく、現在の*リソースインスタンス*を参照します。
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
を使用すると、余分な変更なしに同じ柔軟性が得られます。