Table of Contents

HashiCorp Terraform Associate

FIXME

Needed for terraform to provision on AWS: The Terraform CLI (1.2.0+) installed. The AWS CLI installed. An AWS account and associated credentials that allow you to create resources in the us-west-2 region, including an EC2 instance, VPC, and security groups.

:!: Infrastructure as Code is the practice of defining infrastructure deployments using machine-readable files that can be used to provision infrastructure in an automated fashion.

Infrastructure-as-Code (IaC) Concepts:

Terraform is an example of Infrastructure-as-Code (IaC), and therefore HashiCorp expects that you have a fundamental understanding of what IaC is and some of its concepts and patterns. This exam objective is not focused specifically around Terraform itself but covers general topics of Infrastructure-as-Code.

Infrastructure can be thought of as the resources an application runs on. Traditionally this was composed of servers, storage, and networking. With the advent of virtualization, servers were now split into both physical resources and virtual machines. Cloud providers created additional abstractions, starting with Infrastructure-as-a-Service (IaaS) and moving up to Platform-as-a- Service (PaaS) and Software-as-a-Service (SaaS). While traditional infrastructure was deployed using manual and cumbersome processes fraught with potential for mistakes and inconsistencies, the various services offered by cloud providers and other vendors introduce a software-driven model of creation and configuration.

Infrastructure-as-Code (IaC) is the practice of defining and provisioning infrastructure resources through a machine-readable format. The infrastructure provisioned and managed using IaC can include bare-metal servers, virtual machines, networking resources, storage volumes, or even databases provided as a service. While IaC is often used in a cloud environment, it is not necessary to use the cloud for IaC. As long as your infrastructure management system has a programmatic interface, it can participate in IaC.

The format can be declarative (defining the desired outcome) or imperative (defining the process of provisioning.) Declarative provisioning solutions, such as Terraform, are focused on the desired end state of a deployment and rely on an interpretation engine to create and configure the actual resources. Imperative provisioning solutions, such as a batch script, focus on the actual provisioning process and may reference a file containing a list of settings and configuration values. The code created for IaC may be stored in a Version Control System (VCS) to enable change tracking and team collaboration. IaC can also be combined with other common software development practices like automated testing, deployment pipelines, and reusable components.

:!: The key point behind Iac is that infrastructure is defined and provisioned through machine-readable code and is not provisioned by hand using a portal, command line, or API. If the commands or process is performed manually by a person, it is not IaC.

Advantages of IaC:

The advantages of using IaC can be broken down into a few key categories: consistency, repeatability, and efficiency.

Understanding Terraform’s Purpose (vs Other IaC):

Terraform is not the only player in town when it comes to working with Infrastructure-as-Code (IaC.) There are public cloud provider solutions, like CloudFormation from AWS or Azure Resource Manager (ARM) Templates from Microsoft.

Various IaC solutions all have different features and approaches to achieve the goal of automated infrastructure deployment. HashiCorp wants you to know what makes Terraform different from these other solutions.

:!: Terraform is agnostic when it comes to the public cloud. It leverages providers for each different cloud, as well as other solutions including VMware, Kubernetes, and MySQL. Rather than focusing on a specific cloud or service, Terraform is able to provide a common tool, process, and language (HashiCorp Configuration Language) to be used across multiple clouds and services.

Other IaC solutions are often cloud-specific like CloudFormation from AWS or Azure Resource Manager from Microsoft.

State:

The creation and manipulation of resources managed by Terraform needs to be tracked in some manner. Terraform achieves this through the implementation of state. When a resource is created, such as an EC2 instance in AWS, Terraform creates an entry in state that maps the metadata about the resource (such as instance-id) to key/value pairs in the entry. The tracking of resource metadata serves multiple functions:

  1. Idempotence: Each time a Terraform configuration is planned or applied, Terraform checks to see if there are any changes required to the actual environment to match the desired configuration. Only those resources that require changes will be updated, and all other resources will be left alone. If there are no changes to the configuration, then Terraform will not make any changes to the environment. State is what allows Terraform to map the resources defined in the configuration to the resources that exist in the real world.
  2. Dependencies: Imagine a scenario where you have removed a subnet and EC2 instance from a configuration. Terraform will attempt to destroy those resources the next time you apply the configuration. You know intuitively that the EC2 instance must be removed before the subnet, since the instance is dependent on the subnet. How can Terraform figure this out? When the resources were created, the EC2 instance referenced the subnet and so Terraform found the dependency when building its graph. With both resources removed from the configuration, Terraform cannot deduce the dependency by building a graph. The answer? State! Terraform maintains a list of dependencies in the state file so that it can properly deal with dependencies that no longer exist in the current configuration.
  3. Performance: The state is a representation of the current state of the world as Terraform understands it. When planning a change, Terraform needs to look at the resources and their attributes to etermine if changes are necessary. Do the EC2 instances need a new metadata tag? Terraform can check the tags attribute in state for the EC2 instance and make a quick decision. While Terraform could query resources directly for each planning run, the performance of planning would rapidly degrade as the infrastructure grows in scale. By default Terraform will refresh the state before each planning run, but to improve performance Terraform can be told to skip the refresh with the–refresh=false argument. The-target argument can be used to specify a particular resource to refresh, without triggering a full refresh of the state. The state can be periodically refreshed from the actual world when required in order to keep up with changes, while not requiring a full scan during each plan. It’s important to note that choosing not to refresh the state means that the reality of your infrastructure deployment may not match what is in the state file. This can lead to inconsistent results when you apply the plan, or an outright failure. The risk of not refreshing state should be balanced against any performance improvements.
  4. Collaboration: State keeps track of the version of an applied configuration, and it supports the locking of state during updates. Combined with the storage of state in a remote, shared location, teams are able to collaborate on deployments without overwriting each other’s work.

Providers

A provider is an executable plug-in that contains the code necessary to interact with the API of the service it was written for. Typically this includes a way to authenticate to a service, manage resources, and access data sources.

:!: Providers can be explicitly defined within a configuration, or implied by the presence of a resource or data source that uses the provider! The actual arguments in a provider block vary depending on the provider, but all providers support the meta-arguments of version and alias.

Example of an Azure provider block:

1 provider azurerm {
2     version = "=1.41.0"
3     tenant_id = var.tenant_id
4     subscription = var.subscription_id 
5 }
1 terraform {
2     required_providers {
3         azurerm = "=1.41.0"
4     }
5 }

:!: One of the more common arguments is ∼> which is meant to keep you on the same major version, while still allowing for minor version updates. For instance, let’s say there’s major change coming to the Azure provider in version 2.0. By setting the version to ∼>1.0, you would allow all version 1 updates that come down while still blocking the big 2.0 release.

Plugin Based Architecture

Using Multiple Providers

Even the most basic configurations will likely use multiple different providers. Let’s take the following configuration as an example:

1 provider "aws" {
2     region = "us-east-1"
3 }
4
5 resource "random_integer" "rand" {
6     min = 10000
7     max = 99999
8 }
9
10 resource "aws_s3_bucket" "bucket" {
11     name = "unique-name-${random_integer.rand.result}"
12     ...
13 }

In this configuration we have already used two separate providers to create a single S3 bucket. The Random provider gives us a random integer for naming the bucket and the AWS provider gives us the S3 bucket resource. When using a provider it can be explicitly defined in a provider block, or implied by the presence of a resource that uses the provider.