top of page
  • Writer: Tony Stiles
    Tony Stiles
  • Jan 31, 2023
  • 11 min read

Updated: Jul 2, 2024


HashiCorp Terraform Associate


1. Understand Infrastructure as Code (IaC) concepts

1a. What is IaC?

Infrastructure as Code (IaC) is describing computing infrastructure through a written high-level syntax.


As well as Terraform, other IaC tools include AWS CloudFormation, Pulumi and Azure Resource Manager templates.


Infrastructure as Code enables numerous benefits including;

  • Versioning of your infrastructure - See what your infrastructure was like at a point in time, and the change that have been made.

  • Reusable Code - Separate distinct sets of identical infrastructure can be built from the same code.

  • Code Modularity - Components can be broken down into discrete, composable pieces that be reused in different situations.

  • Shareable Infrastructure - Infrastructure designs can be shared in Open Source and Inner Source repositories, to allow others to reuse the same code.

Terraform can take advantage of all of these benefits.


Reading Material


1b. Describe advantages of IaC patterns

Infrastructure as Code allows for several beneficial patterns to be used;

  • Service APIs (Application Programming Interfaces) can be consumed to utilize Cloud and On-Premises resources.

  • Trivial to consume elasticly scalable cloud resources repeatedly.

  • Version Control Systems can be used for historical tracking and control of code.

  • Continuous Integration and Continuous Deployment (CI/CD) can be implemented to test and deploy your infrastructure.

  • Code as documentation - Not only does your code deploy the infrastructure, it also describes how it all joins together.


Documentation


Tutorial


2. Understand Terraform's purpose (vs other IaC)

2a. Explain multi-cloud and provider-agnostic benefits


Documentation


Notes

  • Spreading infrastructure across clouds to increase fault tolerance

  • Don't have to be reliant upon a single region or even a single cloud

  • Provider-agnostic design allows for a single configuration to provision resources across multiple platforms

  • Simplifying management, by keeping it under the same

2b. Explain the benefits of state


Documentation


Tutorial


Notes

  • Necessary for Terraform to function

  • A source of truth to know if things have changed or not


Mapping Real Objects to Terraform Resources

  • Need a database of what to map Terraform data to in the real world

  • Has to be agnostic; not all providers support tagging or other concepts

  • Even within the providers, not all resources necessarily support tagging

  • Each distinct state object needs to be mapped to a distinct resource, to avoid ambiguous data


Metadata

  • Metadata such as dependencies needs to be tracked

  • Typically configurations are used to determine the dependency order

  • However, when you delete a resource, it will disappear from the configurations however

  • Need the state to know that the resources need deleting

  • Having the state means that order of deletion can also be determined

  • Other methods would increase the complexity, especially given that deletions across providers may also need to be performed


Performance

  • State allows for the attribute values to be cached

  • Refreshing the state can be made optional to speed up Terraform for large state files


Syncing

  • Remote state allows for everyone to operate on the same state at the same time

  • Implementing locking means that you’re always going to have the latest state to work with

3. Understand Terraform basics

3a. Handle Terraform and provider installation and versioning


Documentation


Tutorial


Notes

  • Terraform releases are available on the Terraform website

  • Homebrew tap contains the latest release as well

  • Providers are requested via the provider block in the root module.

  • terraform init will download them

  • Can also define them in the terraform block within required_providers

terraform {
  required_providers {
    aws = {
      version = ">= 2.7.0"
      source = "hashicorp/aws"
    }
  }
}
  • No longer recommended to set the provider version at the provider block level

  • The name defined in the required_providers block is the local name of the provider, which the provider block refers to

  • You should try to use the preferred local name, which prefixes the resource names, unless necessary, to avoid confusion

3b. Describe plug-in based architecture

Tutorial

Notes

  • Plugin architecture where providers are downloaded and installed to allow access to various services

  • Providers are installed during the terraform init phase

  • Plugins installed to the .terraform folder

3c. Demonstrate using multiple providers

Tutorial

Notes

  • Define multiple provider blocks in the configurations to set them up

  • Define them all in required_providers block as well, just like when you define a single provider

  • Resource types are aligned to the specific providers, so automatically use the providers they come from

  • Don’t forget about local names and how those relate to them

3d. Describe how Terraform finds and fetches providers


Documentation


Tutorial


Notes

  • By default, Terraform will look to the Terraform Registry for providers

  • However, you can define a source in the required_providers block to pull specific providers from certain locations

  • This is defined in the source parameter as described here

  • You also define the version constraint to select a specific version of the provider

terraform {
  required_providers {
    local_name = {
    source = [<HOSTNAME>/]<NAMESPACE>/<TYPE>
    version =
    }
  }
}

3e. Explain when to use and not use provisioners and when to use local-exec or remote-exec


Documentation


Tutorial


Notes

  • Provisioners are now considered a last resort for Terraform

  • Instead, use infrastructure provisioning tools like Packer and cloud-init, user data or metadata, and other tooling like Chef, etc

  • Provisioners require login rights to instances, which you really want to avoid for a reliable build and to remove direct network access to instances

  • If you don’t have support in a provider, then that may be a good reason to use local-exec as a temporary workaround


4. Use the Terraform CLI (outside of core workflow)

4a. Given a scenario: choose when to use terraform fmt to format code


Documentation

Notes

  • Best to use terraform fmt when you’re writing code yourself

  • The canonical format can change between terraform versions, so you may need to re-run if upgrading

  • Tools that generate Terraform configurations will generate it to this style, so it’s best to follow the canonical style where ever possible

4b. Given a scenario: choose when to use terraform taint to taint Terraform resources


Documentation

Notes

  • taint only impacts the state, it doesn’t modify the infrastructure until terraform is next applied

  • Might want to use taint to force a provisioner to run

  • May cause other resources to rebuild if they are dependent upon it

  • Could be good to use if some resource attributes are not seen by Terraform

4c. Given a scenario: choose when to use terraform import to import existing infrastructure into your Terraform state


Documentation


Notes

  • Imports an existing resource into Terraform

  • Useful when you have existing resources that you don’t want to or cannot rebuild at that point managed by Terraform

4d. Given a scenario: choose when to use terraform workspace to create workspaces


Documentation


Notes

  • This is discussing CLI workspaces, not Terraform Cloud/Enterprise Workspaces

  • Remember; you’re using a single configuration with a single backend, but then slotting multiple states into that one backend

  • Could be using feature branches to map to workspaces, for changes to infrastructure code

  • Good for testing changes, so there is a primary workspace, with other workspaces for that testing

  • Workspaces not great for avoiding tight coupling; system composition would be better done through a combination of strategies including separating your configurations out with clear boundaries

4e. Given a scenario: choose when to use terraform state to view Terraform state


Documentation


Notes

  • Use the state command instead of interrogating terraform state files directly where possible

  • Much safer to use than handling things manually where you can corrupt the files

  • Can use it to manage and change state details of resources;

  • list list resources within the state file

  • mv to move items around in the state

  • pull to download a remote state

  • push to replace a remote state

  • replace-provider to replace the provider for a specific resource in state

  • rm remove items from the state; will not remove the underlying resource

  • show show the attributes of an item within state


4f. Given a scenario: choose when to enable verbose logging and what the outcome/value is


Documentation


Notes

  • Use TF_LOG to set log levels, so TRACE, DEBUG, INFO, WARN or ERROR

  • TF_LOG_PATH to push the log to a specific location

  • Good to provide logs in case of a bug within Terraform for error reporting

  • crash.log will be written out on a panic error, doesn’t need TF_LOG to be set


5. Interact with Terraform modules

5a. Contrast module source options


Documentation


Tutorial


Notes

  • Modules can be sourced locally or from remote sources

  • Can pull modules from the public Terraform repository or use private repositories

  • Public modules can be listed as “verified” where HashiCorp has validated them

  • Not actively maintained by HashiCorp themselves, but rater partners

  • Local Paths, Terraform Registry, GitHub, BitBucket, Git/Mercurial, HTTP, S3 buckets, GCS buckets

  • Good to use versioning where possible

  • HTTP, GCS, S3 can pull down compressed files as well if supported versions


5b. Interact with module inputs and outputs


Tutorial


Notes

  • Try using modules!

  • Awareness of defined output and input variables, how to pass them into the modules themselves

5c. Describe variable scope within modules/child modules


Documentation


Notes

  • Variables scoped within modules

  • Have to explicitly pass them out from modules via outputs


5d. Discover modules from the public Terraform Module Registry


Documentation


Tutorial


Notes

5e. Defining module version


Documentation


Notes

  • Use the version parameter

  • If using VCS sources, you might have to set it within the source parameter instead

6. Navigate Terraform workflow

6a. Describe Terraform workflow ( Write -> Plan -> Create )


Documentation


Tutorial


Notes

6b. Initialize a Terraform working directory (terraform init)


Documentation


Tutorial


Notes

6c. Validate a Terraform configuration (terraform validate)


Documentation

Notes

6d. Generate and review an execution plan for Terraform (terraform plan)


Documentation


Notes

6e. Execute changes to infrastructure with Terraform (terraform apply)


Documentation


Tutorial

Notes

6f. Destroy Terraform managed infrastructure (terraform destroy)

Documentation

Tutorial

Notes

7. Implement and maintain state

7a. Describe default local backend

Documentation

Notes

  • Defaults to writing the state out to file

  • Uses system APIs to lock the state

  • Can set the path

7b. Outline state locking

Documentation

Notes

  • Locks the state for all operations that could write

  • Prevents others from locking the state and causing corruption

  • Does not show a message if it happens

  • Shows a message if the lock fails

  • Can optionally disable locking, but not recommended

  • If it takes time to find the lock, it will show a message

  • Not all backends support locking; it is on a per-backend basis

  • You can force-unlock a lock with the terraform force-unlock command

  • Requires the Lock ID which is shown during the lock failure error message

7c. Handle backend authentication methods

Documentation

Notes

  • Different backends require different authentication methods, detailed in their documentation

  • Typically, it’s specific to how the backend’s platform handles authentication;

  • artifactory supports usernames and passwords

  • azurerm (Azure Blob Storage) supports several different auth methods

  • Managed Service Identity

  • SAS Token

  • Storage Account Access Key

  • Service Principal with Client Certificate

  • Service Principal with Client Secret

  • consul supports username/password over Basic HTTP auth and certificate based auth

  • cos (Tencent Object Storage) supports secret ID and key auth

  • etc supports username/password auth

  • etcdv3 supports username/password or certificate based auth

  • gcs (Google Cloud Storage) supports JSON credentials or access tokens

  • http supports HTTP basic username/password auth

  • kubernetes uses secrets and supports HTTP basic username/password auth, certificate auth and service account tokens

  • manta (Joyent Triton) supports private key based auth

  • oss (Alibaba Object Storage Service with Cloud Table Store for locking) supports RAM roles, access keys, assumed roles and credential files

  • pg (PostgreSQL) supports connection string auth

  • s3 (AWS Simple Storage Service with DynamoDB for locking) requires IAM credentials

  • swift (OpenStack) supports secret, token, certificate and username/password based auth

  • remote (Terraform Cloud/Enterprise) backend supports token based auth

7d. Describe remote state storage mechanisms and supported standard backends

Documentation

Tutorial

Notes

7e. Describe effect of Terraform refresh on state

Documentation

Notes

7f. Describe backend block in configuration and best practices for partial configurations

Documentation

Tutorial

Notes

  • Partial configuration good for keeping secrets out of your configuration

  • Keep them out of code storage

  • No interpolations allowed in the backend configuration however!

  • Pass in interactively, via a backend configuration file or via command line options when you want to hide secrets

7g. Understand secret management in state files

Documentation

Notes

  • State file can hold sensitive data

  • Therefore, treat the state as a whole like it is sensitive data

  • Encrypt in transit and at reset

  • Local state is plain text, so use remote state

8. Read, generate, and modify configuration

8a. Demonstrate use of variables and outputs

Tutorial

Notes

variable "name" {
  default = "value"
  type = string
  description = "What the variable is for"

  validation {
    condition     = ""
    error_message = ""
  }
}

8b. Describe secure secret injection best practice

Documentation

Tutorial

Notes

8c. Understand the use of collection and structural types

Documentation

Notes

8d. Create and differentiate resource and data configuration

Documentation

Notes

8e. Use resource addressing and resource parameters to connect resources together

Documentation

Notes

8f. Use Terraform built-in functions to write configuration

Documentation

Notes

8g. Configure resource using a dynamic block

Documentation


Notes

dynamic "setting" {
  for_each = var.settings
  content {
    foo = setting.value["foo"]
    bar = setting.value["bar"]
}

8h. Describe built-in dependency management (order of execution based)


Tutorial


Notes

9. Understand Terraform Cloud and Enterprise capabilities

9a. Describe the benefits of Sentinel, registry, and workspaces


Documentation


Tutorial


Notes

9b. Differentiate OSS and Terraform Cloud workspaces


Documentation

Notes

9c. Summarise features of Terraform Cloud


Documentation


Tutorial

bottom of page