github.com/kcburge/terraform@v0.11.12-beta1/website/guides/running-terraform-in-automation.html.md (about)

     1  ---
     2  layout: "guides"
     3  page_title: "Running Terraform in Automation - Guides"
     4  sidebar_current: "guides-running-terraform-in-automation"
     5  description: |-
     6    Terraform can, with some caveats, be run in automated processes such as
     7    continuous delivery pipelines. Ths guide describes some techniques for
     8    doing so and some gotchas to watch out for.
     9  ---
    10  
    11  # Running Terraform in Automation
    12  
    13  ~> **This is an advanced guide!** When getting started with Terraform, it's
    14  recommended to use it locally from the command line. Automation can become
    15  valuable once Terraform is being used regularly in production, or by a larger
    16  team, but this guide assumes familiarity with the normal, local CLI
    17  workflow.
    18  
    19  For teams that use Terraform as a key part of a change management and
    20  deployment pipeline, it can be desirable to orchestrate Terraform runs in some
    21  sort of automation in order to ensure consistency between runs, and provide
    22  other interesting features such as integration with version control hooks.
    23  
    24  Automation of Terraform can come in various forms, and to varying degrees.
    25  Some teams continue to run Terraform locally but use _wrapper scripts_ to
    26  prepare a consistent working directory for Terraform to run in, while other
    27  teams run Terraform entirely within an orchestration tool such as Jenkins.
    28  
    29  This guide covers some things that should be considered when implementing
    30  such automation, both to ensure safe operation of Terraform and to accommodate
    31  some current limitations in Terraform's workflow that require careful
    32  attention in automation.
    33  
    34  The guide assumes that Terraform will be running in an _non-interactive_
    35  environment, where it is not possible to prompt for input at the terminal.
    36  This is not necessarily true for wrapper scripts, but is often true when
    37  running in orchestration tools.
    38  
    39  This is a general guide, giving an overview of things to consider when
    40  implementing orchestration of Terraform. Due to its general nature, it is not
    41  possible to go into specifics about any particular tools, though other
    42  tool-specific guides may be produced later if best practices emerge around
    43  such a tool.
    44  
    45  ## Automated Workflow Overview
    46  
    47  When running Terraform in automation, the focus is usually on the core
    48  plan/apply cycle. The main path, then, is broadly the same as for CLI
    49  usage:
    50  
    51  1. Initialize the Terraform working directory.
    52  2. Produce a plan for changing resources to match the current configuration.
    53  3. Have a human operator review that plan, to ensure it is acceptable.
    54  4. Apply the changes described by the plan.
    55  
    56  Steps 1, 2 and 4 can be carried out using the familiar Terraform CLI commands,
    57  with some additional options:
    58  
    59  * `terraform init -input=false` to initialize the working directory.
    60  * `terraform plan -out=tfplan -input=false` to create a plan and save it to the local file `tfplan`.
    61  * `terraform apply -input=false tfplan` to apply the plan stored in the file `tfplan`.
    62  
    63  The `-input=false` option indicates that Terraform should not attempt to
    64  prompt for input, and instead expect all necessary values to be provided by
    65  either configuration files or the command line. It may therefore be necessary
    66  to use the `-var` and `-var-file` options on `terraform plan` to specify any
    67  variable values that would traditionally have been manually-entered under
    68  interactive usage.
    69  
    70  It is strongly recommended to use a backend that supports
    71  [remote state](/docs/state/remote.html), since that allows Terraform to
    72  automatically save the state in a persistent location where it can be found
    73  and updated by subsequent runs. Selecting a backend that supports
    74  [state locking](/docs/state/locking.html) will additionally provide safety
    75  against race conditions that can be caused by concurrent Terraform runs.
    76  
    77  ## Controlling Terraform Output in Automation
    78  
    79  By default, some Terraform commands conclude by presenting a description
    80  of a possible next step to the user, often including a specific command
    81  to run next.
    82  
    83  An automation tool will often abstract away the details of exactly which
    84  commands are being run, causing these messages to be confusing and
    85  un-actionable, and possibly harmful if they inadvertently encourage a user to
    86  bypass the automation tool entirely.
    87  
    88  When the environment variable `TF_IN_AUTOMATION` is set to any non-empty
    89  value, Terraform makes some minor adjustments to its output to de-emphasize
    90  specific commands to run. The specific changes made will vary over time,
    91  but generally-speaking Terraform will consider this variable to indicate that
    92  there is some wrapping application that will help the user with the next
    93  step.
    94  
    95  To reduce complexity, this feature is implemented primarily for the main
    96  workflow commands described above. Other ancillary commands may still produce
    97  command line suggestions, regardless of this setting.
    98  
    99  ## Plan and Apply on different machines
   100  
   101  When running in an orchestration tool, it can be difficult or impossible to
   102  ensure that the `plan` and `apply` subcommands are run on the same machine,
   103  in the same directory, with all of the same files present.
   104  
   105  Running `plan` and `apply` on different machines requires some additional
   106  steps to ensure correct behavior. A robust strategy is as follows:
   107  
   108  * After `plan` completes, archive the entire working directory, including the
   109    `.terraform` subdirectory created during `init`, and save it somewhere
   110    where it will be available to the apply step. A common choice is as a
   111    "build artifact" within the chosen orchestration tool.
   112  * Before running `apply`, obtain the archive created in the previous step
   113    and extract it _at the same absolute path_. This re-creates everything
   114    that was present after plan, avoiding strange issues where local files
   115    were created during the plan step.
   116  
   117  Terraform currently makes some assumptions which must be accommodated by
   118  such an automation setup:
   119  
   120  * The saved plan file can contain absolute paths to child modules and other
   121    data files referred to by configuration. Therefore it is necessary to ensure
   122    that the archived configuration is extracted at an identical absolute path.
   123    This is most commonly achieved by running Terraform in some sort of isolation,
   124    such as a Docker container, where the filesystem layout can be controlled.
   125  * Terraform assumes that the plan will be applied on the same operating system
   126    and CPU architecture as where it was created. For example, this means that
   127    it is not possible to create a plan on a Windows computer and then apply it
   128    on a Linux server.
   129  * Terraform expects the provider plugins that were used to produce a
   130    plan to be available and identical when the plan is applied, to ensure
   131    that the plan is interpreted correctly. An error will be produced if
   132    Terraform or any plugins are upgraded between creating and applying a plan.
   133  * Terraform can't automatically detect if the credentials used to create a
   134    plan grant access to the same resources used to apply that plan. If using
   135    different credentials for each (e.g. to generate the plan using read-only
   136    credentials) it is important to ensure that the two are consistent
   137    in which account on the corresponding service they belong to.
   138  
   139  ~> The plan file contains a full copy of the configuration, the state that
   140  the plan applies to, and any variables passed to `terraform plan`. If any of
   141  these contain sensitive data then the archived working directory containing
   142  the plan file should be protected accordingly. For provider authentication
   143  credentials, it is recommended to use environment variables instead where
   144  possible since these are _not_ included in the plan or persisted to disk
   145  by Terraform in any other way.
   146  
   147  ## Interactive Approval of Plans
   148  
   149  Another challenge with automating the Terraform workflow is the desire for an
   150  interactive approval step between plan and apply. To implement this robustly,
   151  it is important to ensure that either only one plan can be outstanding at a
   152  time or that the two steps are connected such that approving a plan passes
   153  along  enough information to the apply step to ensure that the correct plan is
   154  applied, as opposed to some later plan that also exists.
   155  
   156  Different orchestration tools address this in different ways, but generally
   157  this is implemented via a _build pipeline_ feature, where different steps
   158  can be applied in sequence, with later steps having access to data produced
   159  by earlier steps.
   160  
   161  The recommended approach is to allow only one plan to be outstanding at a
   162  time. When a plan is applied, any other existing plans that were produced
   163  against the same state are invalidated, since they must now be recomputed
   164  relative to the new state. By forcing plans to be approved (or dismissed) in
   165  sequence, this can be avoided.
   166  
   167  ## Auto-Approval of Plans
   168  
   169  While manual review of plans is strongly recommended for production
   170  use-cases, it is sometimes desirable to take a more automatic approach
   171  when deploying in pre-production or development situations.
   172  
   173  Where manual approval is not required, a simpler sequence of commands
   174  can be used:
   175  
   176  * `terraform init -input=false`
   177  * `terraform apply -input=false -auto-approve`
   178  
   179  This variant of the `apply` command implicitly creates a new plan and then
   180  immediately applies it. The `-auto-approve` option tells Terraform not
   181  to require interactive approval of the plan before applying it.
   182  
   183  ~> When Terraform is empowered to make destructive changes to infrastructure,
   184  manual review of plans is always recommended unless downtime is tolerated
   185  in the event of unintended changes. Use automatic approval **only** with
   186  non-critical infrastructure.
   187  
   188  ## Testing Pull Requests with `terraform plan`
   189  
   190  `terraform plan` can be used as a way to perform certain limited verification
   191  of the validity of a Terraform configuration, without affecting real
   192  infrastructure. Although the plan step updates the state to match real
   193  resources, thus ensuring an accurate plan, the updated state is _not_
   194  persisted, and so this command can safely be used to produce "throwaway" plans
   195  that are created only to aid in code review.
   196  
   197  When implementing such a workflow, hooks can be used within the code review
   198  tool in question (for example, Github Pull Requests) to trigger an orchestration
   199  tool for each new commit under review. Terraform can be run in this case
   200  as follows:
   201  
   202  * `terraform plan -input=false`
   203  
   204  As in the "main" workflow, it may be necessary to provide `-var` or `-var-file`
   205  as appropriate. The `-out` option is not used in this scenario because a
   206  plan produced for code review purposes will never be applied. Instead, a
   207  new plan can be created and applied from the primary version control branch
   208  once the change is merged.
   209  
   210  ~> Beware that passing sensitive/secret data to Terraform via
   211  variables or via environment variables will make it possible for anyone who
   212  can submit a PR to discover those values, so this flow must be
   213  used with care on an open source project, or on any private project where
   214  some or all contributors should not have direct access to credentials, etc.
   215  
   216  ## Multi-environment Deployment
   217  
   218  Automation of Terraform often goes hand-in-hand with creating the same
   219  configuration multiple times to produce parallel environments for use-cases
   220  such as pre-release testing or multi-tenant infrastructure. Automation
   221  in such a situation can help ensure that the correct settings are used for
   222  each environment, and that the working directory is properly configured
   223  before each operation.
   224  
   225  The two most interesting commands for multi-environment orchestration are
   226  `terraform init` and `terraform workspace`. The former can be used with
   227  additional options to tailor the backend configuration for any differences
   228  between environments, while the latter can be used to safely switch between
   229  multiple states for the same config stored in a single backend.
   230  
   231  Where possible, it's recommended to use a single backend configuration for
   232  all environments and use the `terraform workspace` command to switch
   233  between workspaces:
   234  
   235  * `terraform init -input=false`
   236  * `terraform workspace select QA`
   237  
   238  In this usage model, a fixed naming scheme is used within the backend
   239  storage to allow multiple states to exist without any further configuration.
   240  
   241  Alternatively, the automation tool can set the environment variable
   242  `TF_WORKSPACE` to an existing workspace name, which overrides any selection
   243  made with the `terraform workspace select` command. Using this environment
   244  variable is recommended only for non-interactive usage, since in a local shell
   245  environment it can be easy to forget the variable is set and apply changes
   246  to the wrong state.
   247  
   248  In some more complex situations it is impossible to share the same
   249  [backend configuration](/docs/backends/config.html) across environments. For
   250  example, the environments may exist in entirely separate accounts within the
   251  target service, and thus need to use different credentials or endpoints for the
   252  backend itself. In such situations, backend configuration settings can be
   253  overridden via
   254  [the `-backend-config` option to `terraform init`](/docs/commands/init.html#backend-config).
   255  
   256  ## Pre-installed Plugins
   257  
   258  In default usage, [`terraform init`](/docs/commands/init.html#backend-config)
   259  downloads and installs the plugins for any providers used in the configuration
   260  automatically, placing them in a subdirectory of the `.terraform` directory.
   261  This affords a simpler workflow for straightforward cases, and allows each
   262  configuration to potentially use different versions of plugins.
   263  
   264  In automation environments, it can be desirable to disable this behavior
   265  and instead provide a fixed set of plugins already installed on the system
   266  where Terraform is running. This then avoids the overhead of re-downloading
   267  the plugins on each execution, and allows the system administrator to control
   268  which plugins are available.
   269  
   270  To use this mechanism, create a directory somewhere on the system where
   271  Terraform will run and place into it the plugin executable files. The
   272  plugin release archives are available for download on
   273  [releases.hashicorp.com](https://releases.hashicorp.com/). Be sure to
   274  download the appropriate archive for the target operating system and
   275  architecture.
   276  
   277  After extracting the necessary plugins, the contents of the new plugin
   278  directory will look something like this:
   279  
   280  ```
   281  $ ls -lah /usr/lib/custom-terraform-plugins
   282  -rwxrwxr-x 1 user user  84M Jun 13 15:13 terraform-provider-aws-v1.0.0-x3
   283  -rwxrwxr-x 1 user user  84M Jun 13 15:15 terraform-provider-rundeck-v2.3.0-x3
   284  -rwxrwxr-x 1 user user  84M Jun 13 15:15 terraform-provider-mysql-v1.2.0-x3
   285  ```
   286  
   287  The version information at the end of the filenames is important so that
   288  Terraform can infer the version number of each plugin. Multiple versions of the
   289  same provider plugin can be installed, and Terraform will use the newest one
   290  that matches the
   291  [provider version constraints](/docs/configuration/providers.html#provider-versions)
   292  in the Terraform configuration.
   293  
   294  With this directory populated, the usual auto-download and
   295  [plugin discovery](/docs/extend/how-terraform-works.html#discovery)
   296  behavior can be bypassed using the `-plugin-dir` option to `terraform init`:
   297  
   298  * `terraform init -input=false -plugin-dir=/usr/lib/custom-terraform-plugins`
   299  
   300  When this option is used, only the plugins in the given directory are
   301  available for use. This gives the system administrator a high level of
   302  control over the execution environment, but on the other hand it prevents
   303  use of newer plugin versions that have not yet been installed into the
   304  local plugin directory. Which approach is more appropriate will depend on
   305  unique constraints within each organization.
   306  
   307  Plugins can also be provided along with the configuration by creating a
   308  `terraform.d/plugins/OS_ARCH` directory, which will be searched before
   309  automatically downloading additional plugins. The `-get-plugins=false` flag can
   310  be used to prevent Terraform from automatically downloading additional plugins.
   311  
   312  ## Terraform Enterprise
   313  
   314  As an alternative to home-grown automation solutions, Hashicorp offers
   315  [Terraform Enterprise](https://www.hashicorp.com/products/terraform/).
   316  
   317  Internally, Terraform Enterprise runs the same Terraform CLI commands
   318  described above, using the same release binaries offered for download on this
   319  site.
   320  
   321  Terraform Enterprise builds on the core Terraform CLI functionality to add
   322  additional features such as role-based access control, orchestration of the
   323  plan and apply lifecycle, a user interface for reviewing and approving plans,
   324  and much more.
   325  
   326  It will always be possible to run Terraform via in-house automation, to
   327  allow for usage in situations where Terraform Enterprise is not appropriate.
   328  It is recommended to consider Terraform Enterprise as an alternative to
   329  in-house solutions, since it provides an out-of-the-box solution that
   330  already incorporates the best practices described in this guide and can thus
   331  reduce time spent developing and maintaining an in-house alternative.