github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/website/docs/provisioners/index.html.markdown (about)

     1  ---
     2  layout: "docs"
     3  page_title: "Provisioners"
     4  sidebar_current: "docs-provisioners"
     5  description: |-
     6    Provisioners are used to execute scripts on a local or remote machine as part of resource creation or destruction.
     7  ---
     8  
     9  # Provisioners
    10  
    11  Provisioners can be used to model specific actions on the local machine or on
    12  a remote machine in order to prepare servers or other infrastructure objects
    13  for service.
    14  
    15  ## Provisioners are a Last Resort
    16  
    17  Terraform includes the concept of provisioners as a measure of pragmatism,
    18  knowing that there will always be certain behaviors that can't be directly
    19  represented in Terraform's declarative model.
    20  
    21  However, they also add a considerable amount of complexity and uncertainty to
    22  Terraform usage. Firstly, Terraform cannot model the actions of provisioners
    23  as part of a plan because they can in principle take any action. Secondly,
    24  successful use of provisioners requires coordinating many more details than
    25  Terraform usage usually requires: direct network access to your servers,
    26  issuing Terraform credentials to log in, making sure that all of the necessary
    27  external software is installed, etc.
    28  
    29  The following sections describe some situations which can be solved with
    30  provisioners in principle, but where better solutions are also available. We do
    31  not recommend using provisioners for any of the use-cases described in the
    32  following sections.
    33  
    34  Even if your specific use-case is not described in the following sections, we
    35  still recommend attempting to solve it using other techniques first, and use
    36  provisioners only if there is no other option.
    37  
    38  ### Passing data into virtual machines and other compute resources
    39  
    40  When deploying virtual machines or other similar compute resources, we often
    41  need to pass in data about other related infrastructure that the software on
    42  that server will need to do its job.
    43  
    44  The various provisioners that interact with remote servers over SSH or WinRM
    45  can potentially be used to pass such data by logging in to the server and
    46  providing it directly, but most cloud computing platforms provide mechanisms
    47  to pass data to instances at the time of their creation such that the data
    48  is immediately available on system boot. For example:
    49  
    50  * Alibaba Cloud: `user_data` on
    51    [`alicloud_instance`](/docs/providers/alicloud/r/instance.html)
    52    or [`alicloud_launch_template`](/docs/providers/alicloud/r/launch_template.html).
    53  * Amazon EC2: `user_data` or `user_data_base64` on
    54    [`aws_instance`](/docs/providers/aws/r/instance.html),
    55    [`aws_launch_template`](/docs/providers/aws/r/launch_template.html),
    56    and [`aws_launch_configuration`](/docs/providers/aws/r/launch_configuration.html).
    57  * Amazon Lightsail: `user_data` on
    58    [`aws_lightsail_instance`](/docs/providers/aws/r/lightsail_instance.html).
    59  * Microsoft Azure: `custom_data` on
    60    [`azurerm_virtual_machine`](/docs/providers/azurerm/r/virtual_machine.html)
    61    or [`azurerm_virtual_machine_scale_set`](/docs/providers/azurerm/r/virtual_machine_scale_set.html).
    62  * Google Cloud Platform: `metadata` on
    63    [`google_compute_instance`](/docs/providers/google/r/compute_instance.html)
    64    or [`google_compute_instance_group`](/docs/providers/google/r/compute_instance_group.html).
    65  * Oracle Cloud Infrastructure: `metadata` or `extended_metadata` on
    66    [`oci_core_instance`](/docs/providers/oci/r/core_instance.html)
    67    or [`oci_core_instance_configuration`](/docs/providers/oci/r/core_instance_configuration.html).
    68  * VMware vSphere: Attach a virtual CDROM to
    69    [`vsphere_virtual_machine`](/docs/providers/vsphere/r/virtual_machine.html)
    70    using the `cdrom` block, containing a file called `user-data.txt`.
    71  
    72  Many official Linux distribution disk images include software called
    73  [cloud-init](https://cloudinit.readthedocs.io/en/latest/) that can automatically
    74  process in various ways data passed via the means described above, allowing
    75  you to run arbitrary scripts and do basic system configuration immediately
    76  during the boot process and without the need to access the machine over SSH.
    77  
    78  If you are building custom machine images, you can make use of the "user data"
    79  or "metadata" passed by the above means in whatever way makes sense to your
    80  application, by referring to your vendor's documentation on how to access the
    81  data at runtime.
    82  
    83  This approach is _required_ if you intend to use any mechanism in your cloud
    84  provider for automatically launching and destroying servers in a group,
    85  because in that case individual servers will launch unattended while Terraform
    86  is not around to provision them.
    87  
    88  Even if you're deploying individual servers directly with Terraform, passing
    89  data this way will allow faster boot times and simplify deployment by avoiding
    90  the need for direct network access from Terraform to the new server and for
    91  remote access credentials to be provided.
    92  
    93  ### Running configuration management software
    94  
    95  As a convenience to users who are forced to use generic operating system
    96  distribution images, Terraform includes a number of specialized provisioners
    97  for launching specific configuration management products.
    98  
    99  We strongly recommend not using these, and instead running system configuration
   100  steps during a custom image build process. For example,
   101  [HashiCorp Packer](https://packer.io/) offers a similar complement of
   102  configuration management provisioners and can run their installation steps
   103  during a separate build process, before creating a system disk image that you
   104  can deploy many times.
   105  
   106  If you are using configuration management software that has a centralized server
   107  component, you will need to delay the _registration_ step until the final
   108  system is booted from your custom image. To achieve that, use one of the
   109  mechanisms described above to pass the necessary information into each instance
   110  so that it can register itself with the configuration management server
   111  immediately on boot, without the need to accept commands from Terraform over
   112  SSH or WinRM.
   113  
   114  ### First-class Terraform provider functionality may be available
   115  
   116  It is technically possible to use the `local-exec` provisioner to run the CLI
   117  for your target system in order to create, update, or otherwise interact with
   118  remote objects in that system.
   119  
   120  If you are trying to use a new feature of the remote system that isn't yet
   121  supported in its Terraform provider, that might be the only option. However,
   122  if there _is_ provider support for the feature you intend to use, prefer to
   123  use that provider functionality rather than a provisioner so that Terraform
   124  can be fully aware of the object and properly manage ongoing changes to it.
   125  
   126  Even if the functionality you need is not available in a provider today, we
   127  suggest to consider `local-exec` usage a temporary workaround and to also
   128  open an issue in the relevant provider's repository to discuss adding
   129  first-class provider support. Provider development teams often prioritize
   130  features based on interest, so opening an issue is a way to record your
   131  interest in the feature.
   132  
   133  Provisioners are used to execute scripts on a local or remote machine
   134  as part of resource creation or destruction. Provisioners can be used to
   135  bootstrap a resource, cleanup before destroy, run configuration management, etc.
   136  
   137  ## How to use Provisioners
   138  
   139  -> **Note:** Provisioners should only be used as a last resort. For most
   140  common situations there are better alternatives. For more information, see
   141  the sections above.
   142  
   143  If you are certain that provisioners are the best way to solve your problem
   144  after considering the advice in the sections above, you can add a
   145  `provisioner` block inside the `resource` block of a compute instance.
   146  
   147  ```hcl
   148  resource "aws_instance" "web" {
   149    # ...
   150  
   151    provisioner "local-exec" {
   152      command = "echo The server's IP address is ${self.private_ip}"
   153    }
   154  }
   155  ```
   156  
   157  The `local-exec` provisioner requires no other configuration, but most other
   158  provisioners must connect to the remote system using SSH or WinRM.
   159  You must include [a `connection` block](./connection.html) so that Terraform
   160  will know how to communicate with the server.
   161  
   162  Terraform includes several built-in provisioners; use the navigation sidebar to
   163  view their documentation. You can also install third-party provisioners in
   164  [the user plugins directory](../configuration/providers.html#third-party-plugins).
   165  
   166  All provisioners support the `when` and `on_failure` meta-arguments, which
   167  are described below (see [Destroy-Time Provisioners](#destroy-time-provisioners)
   168  and [Failure Behavior](#failure-behavior)).
   169  
   170  ### The `self` Object
   171  
   172  Expressions in `provisioner` blocks cannot refer to their parent resource by
   173  name. Instead, they can use the special `self` object.
   174  
   175  The `self` object represents the provisioner's parent resource, and has all of
   176  that resource's attributes. For example, use `self.public_ip` to reference an
   177  `aws_instance`'s `public_ip` attribute.
   178  
   179  -> **Technical note:** Resource references are restricted here because
   180  references create dependencies. Referring to a resource by name within its own
   181  block would create a dependency cycle.
   182  
   183  ## Creation-Time Provisioners
   184  
   185  By default, provisioners run when the resource they are defined within is
   186  created. Creation-time provisioners are only run during _creation_, not
   187  during updating or any other lifecycle. They are meant as a means to perform
   188  bootstrapping of a system.
   189  
   190  If a creation-time provisioner fails, the resource is marked as **tainted**.
   191  A tainted resource will be planned for destruction and recreation upon the
   192  next `terraform apply`. Terraform does this because a failed provisioner
   193  can leave a resource in a semi-configured state. Because Terraform cannot
   194  reason about what the provisioner does, the only way to ensure proper creation
   195  of a resource is to recreate it. This is tainting.
   196  
   197  You can change this behavior by setting the `on_failure` attribute,
   198  which is covered in detail below.
   199  
   200  ## Destroy-Time Provisioners
   201  
   202  If `when = "destroy"` is specified, the provisioner will run when the
   203  resource it is defined within is _destroyed_.
   204  
   205  ```hcl
   206  resource "aws_instance" "web" {
   207    # ...
   208  
   209    provisioner "local-exec" {
   210      when    = "destroy"
   211      command = "echo 'Destroy-time provisioner'"
   212    }
   213  }
   214  ```
   215  
   216  Destroy provisioners are run before the resource is destroyed. If they
   217  fail, Terraform will error and rerun the provisioners again on the next
   218  `terraform apply`. Due to this behavior, care should be taken for destroy
   219  provisioners to be safe to run multiple times.
   220  
   221  Destroy-time provisioners can only run if they remain in the configuration
   222  at the time a resource is destroyed. If a resource block with a destroy-time
   223  provisioner is removed entirely from the configuration, its provisioner
   224  configurations are removed along with it and thus the destroy provisioner
   225  won't run. To work around this, a multi-step process can be used to safely
   226  remove a resource with a destroy-time provisioner:
   227  
   228  * Update the resource configuration to include `count = 0`.
   229  * Apply the configuration to destroy any existing instances of the resource, including running the destroy provisioner.
   230  * Remove the resource block entirely from configuration, along with its `provisioner` blocks.
   231  * Apply again, at which point no further action should be taken since the resources were already destroyed.
   232  
   233  This limitation may be addressed in future versions of Terraform. For now,
   234  destroy-time provisioners must be used sparingly and with care.
   235  
   236  ~> **NOTE:** A destroy-time provisioner within a resource that is tainted _will not_ run. This includes resources that are marked tainted from a failed creation-time provisioner or tainted manually using `terraform taint`.
   237  
   238  ## Multiple Provisioners
   239  
   240  Multiple provisioners can be specified within a resource. Multiple provisioners
   241  are executed in the order they're defined in the configuration file.
   242  
   243  You may also mix and match creation and destruction provisioners. Only
   244  the provisioners that are valid for a given operation will be run. Those
   245  valid provisioners will be run in the order they're defined in the configuration
   246  file.
   247  
   248  Example of multiple provisioners:
   249  
   250  ```hcl
   251  resource "aws_instance" "web" {
   252    # ...
   253  
   254    provisioner "local-exec" {
   255      command = "echo first"
   256    }
   257  
   258    provisioner "local-exec" {
   259      command = "echo second"
   260    }
   261  }
   262  ```
   263  
   264  ## Failure Behavior
   265  
   266  By default, provisioners that fail will also cause the Terraform apply
   267  itself to fail. The `on_failure` setting can be used to change this. The
   268  allowed values are:
   269  
   270  - `"continue"` - Ignore the error and continue with creation or destruction.
   271  
   272  - `"fail"` - Raise an error and stop applying (the default behavior). If this is a creation provisioner,
   273      taint the resource.
   274  
   275  Example:
   276  
   277  ```hcl
   278  resource "aws_instance" "web" {
   279    # ...
   280  
   281    provisioner "local-exec" {
   282      command    = "echo The server's IP address is ${self.private_ip}"
   283      on_failure = "continue"
   284    }
   285  }
   286  ```