diff --git a/website/docs/provisioners/chef.html.markdown b/website/docs/provisioners/chef.html.markdown index 67c34b59a..245db62a6 100644 --- a/website/docs/provisioners/chef.html.markdown +++ b/website/docs/provisioners/chef.html.markdown @@ -12,6 +12,10 @@ The `chef` provisioner installs, configures and runs the Chef Client on a remote resource. The `chef` provisioner supports both `ssh` and `winrm` type [connections](/docs/provisioners/connection.html). +-> **Note:** Provisioners should only be used as a last resort. For most +common situations there are better alternatives. For more information, see +[the main Provisioners page](./). + ## Requirements The `chef` provisioner has some prerequisites for specific connection types: diff --git a/website/docs/provisioners/connection.html.markdown b/website/docs/provisioners/connection.html.markdown index 56dabe442..e2931d723 100644 --- a/website/docs/provisioners/connection.html.markdown +++ b/website/docs/provisioners/connection.html.markdown @@ -11,6 +11,10 @@ description: |- Many provisioners require access to the remote resource. For example, a provisioner may need to use SSH or WinRM to connect to the resource. +-> **Note:** Provisioners should only be used as a last resort. For most +common situations there are better alternatives. For more information, see +[the main Provisioners page](./). + Terraform uses a number of defaults when connecting to a resource, but these can be overridden using a `connection` block in either a `resource` or `provisioner`. Any `connection` information provided in a `resource` will apply @@ -62,7 +66,7 @@ provisioner "file" { * `password` - The password we should use for the connection. In some cases this is specified by the provider. -* `host` - (Required) The address of the resource to connect to. This is usually specified by the provider. +* `host` - (Required) The address of the resource to connect to. * `port` - The port to connect to. Defaults to `22` when using type `ssh` and defaults to `5985` when using type `winrm`. diff --git a/website/docs/provisioners/file.html.markdown b/website/docs/provisioners/file.html.markdown index c3b8602e8..5b3c80b0c 100644 --- a/website/docs/provisioners/file.html.markdown +++ b/website/docs/provisioners/file.html.markdown @@ -12,6 +12,10 @@ The `file` provisioner is used to copy files or directories from the machine executing Terraform to the newly created resource. The `file` provisioner supports both `ssh` and `winrm` type [connections](/docs/provisioners/connection.html). +-> **Note:** Provisioners should only be used as a last resort. For most +common situations there are better alternatives. For more information, see +[the main Provisioners page](./). + ## Example usage ```hcl diff --git a/website/docs/provisioners/habitat.html.markdown b/website/docs/provisioners/habitat.html.markdown index f96239b8e..8ed2edb2c 100644 --- a/website/docs/provisioners/habitat.html.markdown +++ b/website/docs/provisioners/habitat.html.markdown @@ -9,6 +9,11 @@ description: |- # Habitat Provisioner The `habitat` provisioner installs the [Habitat](https://habitat.sh) supervisor and loads configured services. This provisioner only supports Linux targets using the `ssh` connection type at this time. + +-> **Note:** Provisioners should only be used as a last resort. For most +common situations there are better alternatives. For more information, see +[the main Provisioners page](./). + ## Requirements The `habitat` provisioner has some prerequisites for specific connection types: diff --git a/website/docs/provisioners/index.html.markdown b/website/docs/provisioners/index.html.markdown index b2ab93911..c3a536ce1 100644 --- a/website/docs/provisioners/index.html.markdown +++ b/website/docs/provisioners/index.html.markdown @@ -8,25 +8,156 @@ description: |- # Provisioners +Provisioners can be used to model specific actions on the local machine or on +a remote machine in order to prepare servers or other infrastructure objects +for service. + +## Provisioners are a Last Resort + +Terraform includes the concept of provisioners as a measure of pragmatism, +knowing that there will always be certain behaviors that can't be directly +represented in Terraform's declarative model. + +However, they also add a considerable amount of complexity and uncertainty to +Terraform usage. Firstly, Terraform cannot model the actions of provisioners +as part of a plan because they can in principle take any action. Secondly, +successful use of provisioners requires coordinating many more details than +Terraform usage usually requires: direct network access to your servers, +issuing Terraform credentials to log in, making sure that all of the necessary +external software is installed, etc. + +The following sections describe some situations which can be solved with +provisioners in principle, but where better solutions are also available. We do +not recommend using provisioners for any of the use-cases described in the +following sections. + +Even if your specific use-case is not described in the following sections, we +still recommend attempting to solve it using other techniques first, and use +provisioners only if there is no other option. + +### Passing data into virtual machines and other compute resources + +When deploying virtual machines or other similar compute resources, we often +need to pass in data about other related infrastructure that the software on +that server will need to do its job. + +The various provisioners that interact with remote servers over SSH or WinRM +can potentially be used to pass such data by logging in to the server and +providing it directly, but most cloud computing platforms provide mechanisms +to pass data to instances at the time of their creation such that the data +is immediately available on system boot. For example: + +* Alibaba Cloud: `user_data` on + [`alicloud_instance`](/docs/providers/alicloud/r/instance.html) + or [`alicloud_launch_template`](/docs/providers/alicloud/r/launch_template.html). +* Amazon EC2: `user_data` or `user_data_base64` on + [`aws_instance`](/docs/providers/aws/r/instance.html), + [`aws_launch_template`](/docs/providers/aws/r/launch_template.html), + and [`aws_launch_configuration`](/docs/providers/aws/r/launch_configuration.html). +* Amazon Lightsail: `user_data` on + [`aws_lightsail_instance`](/docs/providers/aws/r/lightsail_instance.html). +* Microsoft Azure: `custom_data` on + [`azurerm_virtual_machine`](/docs/providers/azurerm/r/virtual_machine.html) + or [`azurerm_virtual_machine_scale_set`](/docs/providers/azurerm/r/virtual_machine_scale_set.html). +* Google Cloud Platform: `metadata` on + [`google_compute_instance`](/docs/providers/google/r/compute_instance.html) + or [`google_compute_instance_group`](/docs/providers/google/r/compute_instance_group.html). +* Oracle Cloud Infrastructure: `metadata` or `extended_metadata` on + [`oci_core_instance`](/docs/providers/oci/r/core_instance.html) + or [`oci_core_instance_configuration`](/docs/providers/oci/r/core_instance_configuration.html). +* VMWare vSphere: Attach a virtual CDROM to + [`vsphere_virtual_machine`](/docs/providers/vsphere/r/virtual_machine.html) + using the `cdrom` block, containing a file called `user-data.txt`. + +Many official Linux distribution disk images include software called +[cloud-init](https://cloudinit.readthedocs.io/en/latest/) that can automatically +process in various ways data passed via the means described above, allowing +you to run arbitrary scripts and do basic system configuration immediately +during the boot process and without the need to access the machine over SSH. + +If you are building custom machine images, you can make use of the "user data" +or "metadata" passed by the above means in whatever way makes sense to your +application, by referring to your vendor's documentation on how to access the +data at runtime. + +This approach is _required_ if you intend to use any mechanism in your cloud +provider for automatically launching and destroying servers in a group, +because in that case individual servers will launch unattended while Terraform +is not around to provision them. + +Even if you're deploying individual servers directly with Terraform, passing +data this way will allow faster boot times and simplify deployment by avoiding +the need for direct network access from Terraform to the new server and for +remote access credentials to be provided. + +### Running configuration management software + +As a convenience to users who are forced to use generic operating system +distribution images, Terraform includes a number of specialized provisioners +for launching specific configuration management products. + +We strongly recommend not using these, and instead running system configuration +steps during a custom image build process. For example, +[HashiCorp Packer](https://packer.io/) offers a similar complement of +configuration management provisioners and can run their installation steps +during a separate build process, before creating a system disk image that you +can deploy many times. + +If you are using configuration management software that has a centralized server +component, you will need to delay the _registration_ step until the final +system is booted from your custom image. To achieve that, use one of the +mechanisms described above to pass the necessary information into each instance +so that it can register itself with the configuration management server +immediately on boot, without the need to accept commands from Terraform over +SSH or WinRM. + +### First-class Terraform provider functionality may be available + +It is technically possible to use the `local-exec` provisioner to run the CLI +for your target system in order to create, update, or otherwise interact with +remote objects in that system. + +If you are trying to use a new feature of the remote system that isn't yet +supported in its Terraform provider, that might be the only option. However, +if there _is_ provider support for the feature you intend to use, prefer to +use that provider functionality rather than a provisioner so that Terraform +can be fully aware of the object and properly manage ongoing changes to it. + +Even if the functionality you need is not available in a provider today, we +suggest to consider `local-exec` usage a temporary workaround and to also +open an issue in the relevant provider's repository to discuss adding +first-class provider support. Provider development teams often prioritize +features based on interest, so opening an issue is a way to record your +interest in the feature. + Provisioners are used to execute scripts on a local or remote machine as part of resource creation or destruction. Provisioners can be used to bootstrap a resource, cleanup before destroy, run configuration management, etc. -Provisioners are added directly to any resource: +## How to use Provisioners + +-> **Note:** Provisioners should only be used as a last resort. For most +common situations there are better alternatives. For more information, see +the sections above. + +If you are certain that provisioners are the best way to solve your problem +after considering the advice in the sections above, you can add a +`provisioner` block inside the `resource` block for your compute instance. ```hcl resource "aws_instance" "web" { # ... provisioner "local-exec" { - command = "echo ${self.private_ip} > file.txt" + command = "echo The server's IP address is ${self.private_ip}" } } ``` -For provisioners other than local execution, you must specify -[connection settings](/docs/provisioners/connection.html) so Terraform knows -how to communicate with the resource. +The `local-exec` provisioner requires no other configuration, but most other +provisioners must connect to the remote system using SSH or WinRM. +You must write [a `connection` block](./connection.html) so that Terraform +will know how to communicate with the server. ## Creation-Time Provisioners @@ -127,7 +258,7 @@ resource "aws_instance" "web" { # ... provisioner "local-exec" { - command = "echo ${self.private_ip} > file.txt" + command = "echo The server's IP address is ${self.private_ip}" on_failure = "continue" } } diff --git a/website/docs/provisioners/local-exec.html.markdown b/website/docs/provisioners/local-exec.html.markdown index 8472d2312..2f8cf628f 100644 --- a/website/docs/provisioners/local-exec.html.markdown +++ b/website/docs/provisioners/local-exec.html.markdown @@ -18,6 +18,10 @@ Note that even though the resource will be fully created when the provisioner is run, there is no guarantee that it will be in an operable state - for example system services such as `sshd` may not be started yet on compute resources. +-> **Note:** Provisioners should only be used as a last resort. For most +common situations there are better alternatives. For more information, see +[the main Provisioners page](./). + ## Example usage ```hcl diff --git a/website/docs/provisioners/puppet.html.markdown b/website/docs/provisioners/puppet.html.markdown index f211a72ab..f4d598145 100644 --- a/website/docs/provisioners/puppet.html.markdown +++ b/website/docs/provisioners/puppet.html.markdown @@ -12,6 +12,10 @@ The `puppet` provisioner installs, configures and runs the Puppet agent on a remote resource. The `puppet` provisioner supports both `ssh` and `winrm` type [connections](/docs/provisioners/connection.html). +-> **Note:** Provisioners should only be used as a last resort. For most +common situations there are better alternatives. For more information, see +[the main Provisioners page](./). + ## Requirements The `puppet` provisioner has some prerequisites for specific connection types: diff --git a/website/docs/provisioners/remote-exec.html.markdown b/website/docs/provisioners/remote-exec.html.markdown index 87b45ebe8..3085bb335 100644 --- a/website/docs/provisioners/remote-exec.html.markdown +++ b/website/docs/provisioners/remote-exec.html.markdown @@ -14,6 +14,9 @@ into a cluster, etc. To invoke a local process, see the `local-exec` [provisioner](/docs/provisioners/local-exec.html) instead. The `remote-exec` provisioner supports both `ssh` and `winrm` type [connections](/docs/provisioners/connection.html). +-> **Note:** Provisioners should only be used as a last resort. For most +common situations there are better alternatives. For more information, see +[the main Provisioners page](./). ## Example usage diff --git a/website/docs/provisioners/salt-masterless.html.md b/website/docs/provisioners/salt-masterless.html.md index ad439918f..a50274906 100644 --- a/website/docs/provisioners/salt-masterless.html.md +++ b/website/docs/provisioners/salt-masterless.html.md @@ -13,6 +13,10 @@ Type: `salt-masterless` The `salt-masterless` Terraform provisioner provisions machines built by Terraform using [Salt](http://saltstack.com/) states, without connecting to a Salt master. The `salt-masterless` provisioner supports `ssh` [connections](/docs/provisioners/connection.html). +-> **Note:** Provisioners should only be used as a last resort. For most +common situations there are better alternatives. For more information, see +[the main Provisioners page](./). + ## Requirements The `salt-masterless` provisioner has some prerequisites. `cURL` must be available on the remote host.