terraform/website/docs/language/meta-arguments/count.html.md

125 lines
4.8 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
layout: "language"
page_title: "The count Meta-Argument - Configuration Language"
description: |-
Use the Terraform language `count` meta-argument to efficiently manage nearly identical resources without writing a separate block for each one.
---
# The `count` Meta-Argument
-> **Version note:** Module support for `count` was added in Terraform 0.13, and
previous versions can only use it with resources.
-> **Note:** A given resource or module block cannot use both `count` and `for_each`.
> **Hands-on:** Try the [Manage Similar Resources With Count](https://learn.hashicorp.com/tutorials/terraform/count?in=terraform/0-13&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn.
By default, a [resource block](/docs/language/resources/syntax.html) configures one real
infrastructure object. (Similarly, a
[module block](/docs/language/modules/syntax.html) includes a
child module's contents into the configuration one time.)
However, sometimes you want to manage several similar objects (like a fixed
pool of compute instances) without writing a separate block for each one.
Terraform has two ways to do this:
`count` and [`for_each`](/docs/language/meta-arguments/for_each.html).
If a resource or module block includes a `count` argument whose value is a whole number,
Terraform will create that many instances.
## Basic Syntax
`count` is a meta-argument defined by the Terraform language. It can be used
with modules and with every resource type.
The `count` meta-argument accepts a whole number, and creates that many
instances of the resource or module. Each instance has a distinct infrastructure object
associated with it, and each is separately created,
updated, or destroyed when the configuration is applied.
```hcl
resource "aws_instance" "server" {
count = 4 # create four similar EC2 instances
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
tags = {
Name = "Server ${count.index}"
}
}
```
## The `count` Object
In blocks where `count` is set, an additional `count` object is
available in expressions, so you can modify the configuration of each instance.
This object has one attribute:
- `count.index` The distinct index number (starting with `0`) corresponding
to this instance.
## Using Expressions in `count`
The `count` meta-argument accepts numeric [expressions](/docs/language/expressions/index.html).
However, unlike most arguments, the `count` value must be known
_before_ Terraform performs any remote resource actions. This means `count`
can't refer to any resource attributes that aren't known until after a
configuration is applied (such as a unique ID generated by the remote API when
an object is created).
## Referring to Instances
When `count` is set, Terraform distinguishes between the block itself
and the multiple _resource or module instances_ associated with it. Instances are
identified by an index number, starting with `0`.
- `<TYPE>.<NAME>` or `module.<NAME>` (for example, `aws_instance.server`) refers to the resource block.
- `<TYPE>.<NAME>[<INDEX>]` or `module.<NAME>[<INDEX>]` (for example, `aws_instance.server[0]`,
`aws_instance.server[1]`, etc.) refers to individual instances.
This is different from resources and modules without `count` or `for_each`, which can be
referenced without an index or key.
Similarly, resources from child modules with multiple instances are prefixed
with `module.<NAME>[<KEY>]` when displayed in plan output and elsewhere in the UI.
For a module without `count` or `for_each`, the address will not contain
the module index as the module's name suffices to reference the module.
-> **Note:** Within nested `provisioner` or `connection` blocks, the special
`self` object refers to the current _resource instance,_ not the resource block
as a whole.
## When to Use `for_each` Instead of `count`
If your instances are almost identical, `count` is appropriate. If some
of their arguments need distinct values that can't be directly derived from an
integer, it's safer to use `for_each`.
Before `for_each` was available, it was common to derive `count` from the
length of a list and use `count.index` to look up the original list value:
```hcl
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}"
}
}
```
This was fragile, because the resource instances were still identified by their
_index_ instead of the string values in the list. If an element was removed from
the middle of the list, every instance _after_ that element would see its
`subnet_id` value change, resulting in more remote object changes than intended.
Using `for_each` gives the same flexibility without the extra churn.