Packaged bundles of Infrastructure through Terraform

Creating bundles containing executing Terraform for deploying applications

Table Of Contents

Today I Explained

Terraform configuration files have three different ways in which they are able to impose some requirements about dependencies they have within the terraform ecosystem. The first is the lockfile, which is used to pin the specific versions of the Terraform Providers to use when executing Terraform. This can be fairly important for both performance and security, as it allows more providers to make use of the same precached version of a given Terraform provider.

The second is using the Terraform version configuration file, which allows requiring certain versions of Terraform to be leveraged for executing the configuration files. To properly ensure that this works, it becomes a requirement that some mechanism exists to specify the Terraform version to use when working with a given Terraform configuration. For some tools, this can be configured per tooling, or will be configured based on the current Terraform version installed within the Terraform executor.

The final configuration property, are the source references for the Terraform modules. These will reference either a local file (./), or reference files located in remote (potential authenticated) sources for retrieving the module dependencies.

Given these configuration options, it can be frustrating if one wishes to create an air-gapped, self-contained Terraform module, as the possibility of pulling from random remote source exists. One option to reduce this impact, is the introduction of the idea of terraform bundles, which is a fully self-contained archive for the Terraform configuration files.

All of the remote source modules are retrieved ahead of time at build time, allowing for the deployment environment to not require downloading of the remote modules. Using the lockfile, it is possible to have all of the terraform providers pre-cached onto the executors, and require only local (approved) executors to be made use of. This requires that the executor expose the pre-approved list of providers, to ensure preflighting whether a module is capable of being deployed by the executor.

A straightforward way of generating these bundles is running terraform init in the module, then packaging up all of the files (excluding the providers) into an archive. These ensures that all modules are pre-downloaded, and no dependencies need to be computed at deploytime. This works, but rather than a proper build process, feels more like a precomputation.

An alternative that exists is having a formal build process, that is responsible for downloading modules instead of Terraform, which makes them available using local path references.