465 lines
19 KiB
Markdown
465 lines
19 KiB
Markdown
---
|
|
layout: "docs"
|
|
page_title: "Configuring Resources"
|
|
sidebar_current: "docs-config-resources"
|
|
description: |-
|
|
Resources are the most important element in a Terraform configuration.
|
|
Each resource corresponds to an infrastructure object, such as a virtual
|
|
network or compute instance.
|
|
---
|
|
|
|
# Resources
|
|
|
|
_Resources_ are the most important element in the Terraform language.
|
|
Each resource block describes one ore more infrastructure objects, such
|
|
as virtual networks, compute instances, or higher-level components such
|
|
as DNS records.
|
|
|
|
## Resource Syntax
|
|
|
|
Resource declarations can include a number of advanced features, but only
|
|
a small subset are required for initial use. More advanced syntax features,
|
|
such as single resource declarations that produce multiple similar remote
|
|
objects, are described later in this page.
|
|
|
|
```hcl
|
|
resource "aws_instance" "web" {
|
|
ami = "ami-a1b2c3d4"
|
|
instance_type = "t2.micro"
|
|
}
|
|
```
|
|
|
|
A `resource` block declares a resource of a given type ("aws_instance")
|
|
with a given local name ("web"). The name is used to refer to this resource
|
|
from elsewhere in the same Terraform module, but has no significance outside
|
|
of the scope of a module.
|
|
|
|
The resource type and name together serve as an identifier for a given
|
|
resource and so must be unique within a module.
|
|
|
|
Within the block body (between `{` and `}`) are the configuration arguments
|
|
for the resource itself. Most arguments in this section depend on the
|
|
resource type, and indeed in this example both `ami` and `instance_type` are
|
|
arguments defined specifically for [the `aws_instance` resource type](/docs/providers/aws/r/instance.html).
|
|
|
|
## Resource Types and Arguments
|
|
|
|
Each resource is associated with a single _resource type_, which determines
|
|
the kind of infrastructure object it manages and what arguments and other
|
|
attributes are supported for each resource.
|
|
|
|
Each resource type in turn belongs to a [provider](/docs/configuration/providers.html),
|
|
which is a plugin for Terraform that offers a collection of resource types that
|
|
most often belong to a single cloud or on-premises infrastructure platform.
|
|
|
|
Most of the items within the body of a `resource` block are defined by and
|
|
specific to the selected resource type, and these arguments can make full
|
|
use of [expressions](/docs/configuration/expressions.html) and other dynamic
|
|
Terraform language features.
|
|
|
|
However, there are some "meta-arguments" that are defined by Terraform itself
|
|
and apply across all resource types. These arguments often have additional
|
|
restrictions on what language features can be used with them, and are described
|
|
in more detail in the following sections.
|
|
|
|
## Resource Behavior
|
|
|
|
A `resource` block describes your intent for a particular infrastructure object
|
|
to exist with the given settings. If you are writing a new configuration for
|
|
the first time, the resources it defines will exist _only_ in the configuration,
|
|
and will not yet represent real infrastructure objects in the target platform.
|
|
|
|
_Applying_ a Terraform configuration is the process of creating, updating,
|
|
and destroying real infrastructure objects in order to make their settings
|
|
match the configuration.
|
|
|
|
When Terraform creates a new infrastructure object represented by a `resource`
|
|
block, the identifier for that real object is saved in Terraform's
|
|
[state](/docs/state/index.html), allowing it to be updated and destroyed
|
|
in response to future changes. For resource blocks that already have an
|
|
associated infrastructure object in the state, Terraform compares the
|
|
actual configuration of the object with the arguments given in the
|
|
configuration and, if necessary, updates the object to match the configuration.
|
|
|
|
This general behavior applies for all resources, regardless of type. The
|
|
details of what it means to create, update, or destroy a resource are different
|
|
for each resource type, but this standard set of verbs is common across them
|
|
all.
|
|
|
|
The "meta-arguments" within `resource` blocks, defined in the following
|
|
sections, allow some details of this standard resource behavior to be
|
|
customized on a per-resource basis.
|
|
|
|
## Resource Dependencies
|
|
|
|
As with other elements in the Terraform language, Terraform analyses any
|
|
[expressions](/docs/configuration/expressions.html) within a `resource`
|
|
block to find references to other objects, and infers from this a correct
|
|
dependency ordering for creating, updating, or destroying each resource.
|
|
Because of this, in most cases it is not necessary to mention explicitly
|
|
any dependencies between resources.
|
|
|
|
However, in some less-common situations there are dependencies between
|
|
resources that cannot be recognized implicitly in configuration. For example,
|
|
if Terraform is being used to both manage access control policies _and_ take
|
|
actions that require those policies to be present, there may be a hidden
|
|
dependency between the access policy and a resource whose creation depends
|
|
on it.
|
|
|
|
In these rare cases, the `depends_on` meta-argument can be used to explicitly
|
|
specify a dependency. This argument is available in all `resource` blocks,
|
|
regardless of resource type. For example:
|
|
|
|
```hcl
|
|
resource "aws_iam_role" "example" {
|
|
name = "example"
|
|
|
|
# assume_role_policy is omitted for brevity in this example. See the
|
|
# documentation for aws_iam_role for a complete example.
|
|
assume_role_policy = "..."
|
|
}
|
|
|
|
resource "aws_iam_instance_profile" "example" {
|
|
# Because this expression refers to the role, Terraform can infer
|
|
# automatically that the role must be created first.
|
|
role = aws_iam_role.example.name
|
|
}
|
|
|
|
resource "aws_iam_role_policy" "example" {
|
|
name = "example"
|
|
role = aws_iam_role.example.name
|
|
policy = jsonencode({
|
|
"Statement" = [{
|
|
# This policy allows software running on the EC2 instance to
|
|
# access the S3 API.
|
|
"Action" = "s3:*",
|
|
"Effect" = "Allow",
|
|
}],
|
|
})
|
|
}
|
|
|
|
resource "aws_instance" "example" {
|
|
ami = "ami-a1b2c3d4"
|
|
instance_type = "t2.micro"
|
|
|
|
# Terraform can infer from this that the instance profile must
|
|
# be created before the EC2 instance.
|
|
iam_instance_profile = aws_iam_instance_profile.example
|
|
|
|
# However, if software running in this EC2 instance needs access
|
|
# to the S3 API in order to boot properly, there is also a "hidden"
|
|
# dependency on the aws_iam_role_policy that Terraform cannot
|
|
# automatically infer, so it must be declared explicitly:
|
|
depends_on = [
|
|
aws_iam_role_policy.example,
|
|
]
|
|
}
|
|
```
|
|
|
|
The `depends_on` meta-argument, if present, must be a list of references
|
|
to other resources in the same module. Arbitrary expressions are not allowed
|
|
in the `depends_on` argument value, because its value must be known before
|
|
Terraform knows resource relationships and thus before it can safely
|
|
evaluate expressions.
|
|
|
|
The `depends_on` argument should be used only as a last resort. When using it,
|
|
always include a comment explaining why it is being used, to help future
|
|
maintainers understand the purpose of the additional dependency.
|
|
|
|
## Multiple Resource Instances
|
|
|
|
By default, a single `resource` block corresponds to only one real
|
|
infrastructure object. Sometimes it is desirable to instead manage a set
|
|
of _similar_ objects of the same type, such as a fixed pool of compute
|
|
instances. You can achieve this by using the `count` meta-argument,
|
|
which is allowed in all `resource` blocks:
|
|
|
|
```hcl
|
|
resource "aws_instance" "server" {
|
|
count = 4 # create four similar EC2 instances
|
|
|
|
ami = "ami-a1b2c3d4"
|
|
instance_type = "t2.micro"
|
|
|
|
tags {
|
|
Name = "Server ${count.index}"
|
|
}
|
|
}
|
|
```
|
|
|
|
When the `count` meta-argument is present, a distinction exists between
|
|
the resource block itself -- identified as `aws_instance.server` --
|
|
and the multiple _resource instances_ associated with it, identified
|
|
as `aws_instance.server[0]`, `aws_instance.server[1]`, etc. When `count`
|
|
is _not_ present, a resource block has only a single resource instance,
|
|
which has no associated index.
|
|
|
|
For resource blocks where `count` is set, an additional `count` object
|
|
is available for use in expressions, which has an attribute `count.index`
|
|
that provides the distinct index for each instance.
|
|
|
|
The _Resource Behavior_ section above described how each resource corresponds
|
|
to a real infrastructure object. It is in fact resource _instances_ that
|
|
correspond to infrastructure objects, and so when `count` is used a particular
|
|
resource block has a distinct infrastructure object associated with each of its
|
|
instances, and each is separtely created, updated, or destroyed when the
|
|
configuration is applied.
|
|
|
|
The `count` meta argument accepts [expressions](/docs/configuration/expressions.html)
|
|
in its value, similar to the resource-type-specific arguments for a resource.
|
|
However, Terraform must interpret the `count` argument _before_ any actions
|
|
are taken from remote resources, and so (unlike the resource-type-specifc arguments)
|
|
the `count` expressions may not refer to any resource attributes that are
|
|
not known until after a configuration is applied, such as a unique id
|
|
generated by the remote API when an object is created.
|
|
|
|
For example, `count` can be used with an input variable that carries a list
|
|
value, to create one instance for each element of the list:
|
|
|
|
```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}"
|
|
}
|
|
}
|
|
```
|
|
|
|
Note that the separate resource instances created by `count` are still
|
|
identified by their _index_, and not by the string values in the given
|
|
list. This means that if an element is removed from the middle of the list,
|
|
all of the indexed instances _after_ it will see their `subnet_id` values
|
|
change, which will cause more remote object changes than were probably
|
|
intended. The practice of generating multiple instances from lists should
|
|
be used sparingly, and with due care given to what will happen if the list is
|
|
changed later.
|
|
|
|
## Selecting a Non-default Provider Configuration
|
|
|
|
As described in [the _providers_ guide](/docs/configuration/providers.html),
|
|
Terraform optionally allows the definition of multiple alternative ("aliased")
|
|
configurations for a single provider, to allow management of resources
|
|
in different regions in multi-region services, etc.
|
|
The `provider` meta-argument overrides Terraform's default behavior of
|
|
selecting a provider configuration based on the resource type name.
|
|
|
|
By default, Terraform takes the initial word in the resource type name
|
|
(separated by underscores) and selects the default configuration for that
|
|
named provider. For example, the resource type `google_compute_instance`
|
|
is associated automatically with the default configuration for the provider
|
|
named `google`.
|
|
|
|
By using the `provider` meta-argument, an aliased provider configuration
|
|
can be selected:
|
|
|
|
```hcl
|
|
# default configuration
|
|
provider "google" {
|
|
region = "us-central1"
|
|
}
|
|
|
|
# alternative, aliased configuration
|
|
provider "google" {
|
|
alias = "europe"
|
|
region = "europe-west1"
|
|
}
|
|
|
|
resource "google_compute_instance" "example" {
|
|
# This "provider" meta-argument selects the google provider
|
|
# configuration whose alias is "europe", rather than the
|
|
# default configuration.
|
|
provider = google.europe
|
|
|
|
# ...
|
|
}
|
|
```
|
|
|
|
A resource always has an implicit dependency on its associated provider, to
|
|
ensure that the provider is fully configured before any resource actions
|
|
are taken.
|
|
|
|
The `provider` meta-argument value must always be a literal provider name
|
|
followed by an alias name separated by a dot. Arbitrary expressions are
|
|
not permitted for `provider` because it must be resolved while Terraform
|
|
is constructing the dependency graph, before it is safe to evaluate
|
|
expressions.
|
|
|
|
## Lifecycle Customizations
|
|
|
|
The general lifecycle for resources is described above in the section
|
|
_Resource Behavior_. Some details of that behavior can be customized
|
|
using the special nested block `lifecycle` within a resource block body:
|
|
|
|
```
|
|
resource "azurerm_resource_group" "example" {
|
|
# ...
|
|
|
|
lifecycle {
|
|
create_before_destroy = true
|
|
}
|
|
}
|
|
```
|
|
|
|
The `lifecycle` block and its contents are meta-arguments, available
|
|
for all `resource` blocks regardless of type. The following lifecycle
|
|
meta-arguments are supported:
|
|
|
|
* `create_before_destroy` (bool) - By default, when Terraform must make a
|
|
change to a resource argument that cannot be updated in-place due to
|
|
remote API limitations Terraform will instead destroy the existing object
|
|
and then create a new replacement object with the new configured arguments.
|
|
|
|
The `create_before_destroy` meta-argument changes this behavior so that
|
|
the new, replacement object is created _first_, and then the prior object
|
|
is destroyed only once the replacement is created.
|
|
|
|
This is an opt-in behavior because many remote object types have unique
|
|
name requirements or other constraints that must be accommodated for
|
|
both a new and an old object to exist concurrently. Some resource types
|
|
offer special options to append a random suffix onto each object name to
|
|
avoid collisions, for example. Terraform Core cannot automatically activate
|
|
such features, so you must understand the constrants for each resource
|
|
type before using `create_before_destroy` with it.
|
|
|
|
* `prevent_destroy` (bool) - This meta-argument, when set to `true`, will
|
|
cause Terraform to reject with an error any plan that would destroy the
|
|
infrastructure object associated with the resource, as long as the argument
|
|
remains present in the configuration.
|
|
|
|
This can be used as a measure of safety against the accidental replacement
|
|
of objects that may be costly to reproduce, such as database instances.
|
|
However, it will make certain configuration changes impossible to apply,
|
|
and will prevent the use of the `terraform destroy` command once such
|
|
objects are created, and so this option should be used sparingly.
|
|
|
|
Since this argument must be present in configuration for the protection to
|
|
apply, note that this setting does not prevent the remote object from
|
|
being destroyed if the `resource` block were removed from configuration
|
|
entirely: in that case, the `prevent_destroy` setting is removed along
|
|
with it, and so Terraform will allow the destroy operation to succeed.
|
|
|
|
* `ignore_changes` (list of attribute names) - By default, Terraform detects
|
|
any difference between the current settings of a real infrastructure object
|
|
and plans to update the remote object to match configuration.
|
|
|
|
In some rare cases, settings of a remote object are modified by processes
|
|
outside of Terraform, which Terraform would then attempt to "fix" on the
|
|
next run. In order to make Terraform share management responsibilities
|
|
of a single object with a separate process, the `ignore_changes`
|
|
meta-argument specifies resource attributes that Terraform should ignore
|
|
when planning updates to the associated remote object.
|
|
|
|
The arguments corresponding to the given attribute names are considered
|
|
when planning a _create_ operation, but are ignored when planning an
|
|
_update_.
|
|
|
|
```hcl
|
|
resource "aws_instance" "example" {
|
|
# ...
|
|
|
|
lifecycle {
|
|
ignore_changes = [
|
|
# Ignore changes to tags, e.g. because a management agent
|
|
# updates these based on some ruleset managed elsewhere.
|
|
tags,
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Instead of a list, the special keyword `all` may be used to instruct
|
|
Terraform to ignore _all_ attributes, which means that Terraform can
|
|
create and destroy the remote object but will never propose updates to it.
|
|
|
|
Only attributes defined by the resource type can be ignored.
|
|
`ignore_changes` cannot be applied to itself or to any other meta-arguments.
|
|
|
|
The `lifecycle` settings all effect how Terraform constructs and traverses
|
|
the dependency graph. As a result, only literal values can be used because
|
|
the processing happens to early for arbitrary expression evaluation.
|
|
|
|
## Local-only Resources
|
|
|
|
While most resource types correspond to an infrastructure object type that
|
|
is managed via a remote network API, there are certain specialized resource
|
|
types that operate only within Terraform itself, calculating some results and
|
|
saving those results in the state for future use.
|
|
|
|
For example, local-only resource types exist for
|
|
[generating private keys](/docs/providers/tls/r/private_key.html),
|
|
[issuing self-signed TLS certificates](/docs/providers/tls/r/self_signed_cert.html),
|
|
and even [generating random ids](https://www.terraform.io/docs/providers/random/r/id.html).
|
|
While these resource types often have a more marginal purpose than those
|
|
managing "real" infrastructure objects, they can be useful as glue to help
|
|
connect together other resources.
|
|
|
|
The behavior of local-only resources is the same as all other resources, but
|
|
their result data exists only within the Terraform state. "Destroying" such
|
|
a resource means only to remove it from the state, discarding its data.
|
|
|
|
## Operation Timeouts
|
|
|
|
Some resource types provide a special `timeouts` nested block argument that
|
|
allows you to customize how long certain operations are allowed to take
|
|
before being considered to have failed.
|
|
For example, [`aws_db_instance`](/docs/providers/aws/r/db_instance.html)
|
|
allows configurable timeouts for `create`, `update` and `delete` operations.
|
|
|
|
Timeouts are handled entirely by the resource type implementation in the
|
|
provider, but resource types offering these features follow the convention
|
|
of defining a child block called `timeouts` that has a nested argument
|
|
named after each operation that has a configurable timeout value.
|
|
Each of these arguments takes a string representation of a duration, such
|
|
as `"60m"` for 60 minutes, `"10s"` for ten seconds, or `"2h"` for two hours.
|
|
|
|
```hcl
|
|
resource "aws_db_instance" "example" {
|
|
# ...
|
|
|
|
timeouts {
|
|
create = "60m"
|
|
delete = "2h"
|
|
}
|
|
}
|
|
```
|
|
|
|
The set of configurable operations is chosen by each resource type. Most
|
|
resource types do not support the `timeouts` block at all. Consult the
|
|
documentation for each resource type to see which operations it offers
|
|
for configuration, if any.
|
|
|
|
## Resource Provisioners
|
|
|
|
Some infrastructure objects require some special actions to be taken after they
|
|
are created before they can become fully functional. For example, compute
|
|
instances may require configuration to be uploaded or a configuration management
|
|
program to be run before they can begin their intended operation.
|
|
|
|
Create-time actions like these can be described using _resource provisioners_.
|
|
A provisioner is another type of plugin supported by Terraform, and each
|
|
provisioner takes a different kind of action in the context of a resource
|
|
being created.
|
|
|
|
Provisioning steps should be used sparingly, since they represent
|
|
non-declarative actions taken during the creation of a resource and so
|
|
Terraform is not able to model changes to them as it can for the declarative
|
|
portions of the Terraform language.
|
|
|
|
Provisioners can also be defined to run when a resource is _destroyed_, with
|
|
certain limitations.
|
|
|
|
The `provisioner` and `connection` block types within `resource` blocks are
|
|
meta-arguments available across all resource types. Provisioners and their
|
|
usage are described in more detail in
|
|
[the _Provisioners_ section](/docs/provisioners/index.html).
|