Terraform for beginners
Publié le
Do not index
Do not index
Primary Keyword
Lié à Analyse sémantique (Articles liés) 1
Lié à Analyse sémantique (Articles liés)
Statut rédaction
Terminé
Lié à Analyse sémantique (Articles liés) 2
IntroductionUnderstanding Infrastructure As Code (IaC)IaC with TerraformTerraform FundamentalsTerraform StateTerraform ModulesBuilt-in Functions and Dynamic BlocksTerraform CLITerraform Cloud and EnterpriseConclusion
Introduction
The DevOps movement includes a series of IT engineering tactics aimed at shortening the amount of time it takes to make changes to software design and deployment. One of these tactics is to leverage technology to write a plan that contains deployment specifications ready to be orchestrated in the cloud or on-premises. Terraform is a tool that allows you to build and manage infrastructure safely and efficiently. This includes low-level components such as compute instances, storage, and networking, as well as high-level components such as DNS entries, SaaS features, etc. Terraform can manage both existing service providers and custom in-house solutions.
In this course, you will learn about how to use Terraform to define and to manage your Cloud or on-premise infrastructure
Understanding Infrastructure As Code (IaC)
Infrastructure as code is a concept that allows you to:
- Write down what you want to deploy such as virtual machines, disks, virtual networks, etc... as human readable code without having to use the provider Web GUI
- Enable DevOps since your infrastructure will be described in a code that can be tracked inside a version control repository. This enables more visibility and collaboration across teams
IaC with Terraform
- Terraform is an IaC tool
- Why choosing Terraform as IaC tool ?
- Terraform interacts and takes care of communications with control layer APIs with ease
- Terraform supports a vast array of private and public Cloud vendors and so much more (on-premise infrastructures, etc...)
- Terraform tracks the state of each deployed resource
- What is the Terraform workflow?
- Write: starting by writting the code that describes the infrastructure inside a version control repository (best practice) or locally
- Plan: preview the changes that the writtten code would bring into the real infrastructure
- Apply: after one last plan/review, you are ready to provision the real infrastructure
- Initializing the Terraform working directory
Before you start coding your infrastructure, you need to understand how to initialize Terraform inside your working directory
You have to enter the following command to get started:
terraform init
This command will:
- Terraform key concepts : Plan, Apply and Destroy
- Plan:
- Reads the code and shows a "plan" of what will be deployed with with code without actually deploying any resource
- Allows the user to review the action plan before executing anything
- Requires authetication credentials, if required
- Apply:
- Deploys the infrastructure resources according to the descriptions in the code
- Updates the deployment state mechanism file aka state file or tfstate
- Destroy:
- Looks at the recorded state file created during the deployment and destroys all of the resources created with the code
- Updates the deployment state file by removing all of the destroyed resources
- Non-reversible command
- Resource addressing in Terraform: Understanding Terraform Code
- Understanding the provider configuration
- Understanding a resource block definition
- Understanding a data source block definition
- Terraform configuration files uses .tf extension
The provider block lets you define your provider configurations
A resource block defines a resource that will be created from scratch and will be managed by Terraform code
Resource address is: aws_instance.web
A data source block give the possibility to get informations of resources that already exists in the infrastructure (eg: getting the public IP address of an existing VM, etc..)
Data source address is: data.aws_instance.my-vm
Terraform Fundamentals
- Installing Terraform
- Method 1: Using the Terraform binary
- Download zipped binary from Hashicorp website: https://www.terraform.io/downloads.html
- Unzip Terraform binary
- Move it to a directory that is included in your $PATH environment variable
- Method 2: Using the Terraform repository (Linux only)
- Set up Hashicorp Terraform repository on Linux
- For YUM https://www.terraform.io/docs/cli/install/yum.html
- For APT https://www.terraform.io/docs/cli/install/apt.html
- Install the "terraform" through the package manager
- For YUM:
yum install terraform
- For APT:
apt install terraform
- Terraform providers
- Providers are Terraform's way of abstracting integrations with API control layer of the infrastructure vendors.
- Terraform, by default, looks for Providers in the Terraform providers registry https://registry.terraform.io/browse/providers
- Providers are plugins. They are released on a separate rhythm from Terraform itself, and each provider has its own series of version numbers.
- You can write your own Terraform provider as well.
- Terraform finds and installs providers when initializing working directory via
terraform init
command. - As a best practice Providers should be pegged down to a specific version, so that any changes across provider version doesn't break your Terraform code.
Provider definition example in a file
provider.tf
. You can choose any other filename.provider "aws" {
region = "eu-west-1"
version = "3.69.0"
}
By executing the command
terraform init
,Terraform will download the required files for this provider from the default Terraform registry.You can find all of the available providers list on the Terraform registry here: https://registry.terraform.io/browse/providers
- Terraform state: the concept
- A way for Terraform to keep tabs on what has been deployed
- Stored in a flat json file, usually having the name
terraform.tfstate
- Critical to Terraform's functionality so never lose it
- Terraform variables
- Declaring a variable
All of the variable config arguments are optional so you can also define your variable simply with:
variable "my-var" {}
...and you will provide the value for your variable in the command line or in another file that we will discuss later
Use the
var.
object suffixed by your variable namevar.my-var
terraform.tfvars
file to explicitly set variables valuesSimply create a file with
tfvars
extension in the same directory as your Terraform codemy-var = "eu-west-1"
my-other-var = "foobar"
my-super-var = "makeitclear"
These values will overwrite the default value (if there is any) of each variable from their declaration block
string
: a sequence of Unicode characters representing some text, like"hello"
.number
: a numeric value. Thenumber
type can represent both whole numbers like15
and fractional values like6.283185
.bool
: a boolean value, eithertrue
orfalse
.bool
values can be used in conditional logic.list
(ortuple
): a sequence of values, like["us-west-1a", "us-west-1c"]
. Elements in a list or tuple are identified by consecutive whole numbers, starting with zero.map
(orobject
): a group of values identified by named labels, like{name = "Mabel", age = 52}
.
- Validate the value that will be passed to your variable to prevent invalid inputs
Here is a validation example that will force the user to put a string that must contain more than 4 characters, otherwise Terraform won't deploy the code and display an error message.
variable "my-var" {
description = "My Test Variable"
type = string
default = "Hello"
validation {
condition = length (var.my-var) > 4
error_message = "The string must be more than 4 characters"
}
}
variable "my-var" {
description = "My Test Variable"
type = string
default = "Hello"
sensitive = true
}
- Terraform outputs
- Returns informations about your resources to be displayed on and to be accessible form the command line
- Can expose informations for other Terraform configurations to use.
- Similar to return values in programming languages.
- Declaring output:
- You can also mark an output as sensitive like variables and Terraform will not display it on the shell output
The
value
argument is usually a reference to a resource property that you have deployedoutput "container_registry_secret_key" {
description = "The secret key that can be used to access the container registry"
value = google_service_account_key.artifact-sa-key.private_key
sensitive = true
}
- Terraform provisioners
- Terraforms way of bootstrapping custom scripts, commands or actions
- Can be run locally on the same system where Terraform commands are being issued from
- Can be run remotely on resources spun up through the Terraform deployment
- Within Terraform code, each individual resource can have its own "provisioner" defining the connection method (if required such as SSH or WinRM) and the actions/commands or script to execute.
- There are 2 types of provisioners:
- "Creation-time" provisioner which you can set to run when a resource is being created
- "Destroy-time" provisioner which you can set to run when a resource is being destroyed.
- DISCLAIMER: Hashicorp recommends using Provisioners as a last resort and to try using inherent mechanisms within your infrastructure deployment to carry out custom tasks where possible.
- When should you use provisioners?
- When you want to invoke actions not covered by Terraforms declarative model.
Keep in mind that If the command within a provisioner returns non-zero return code, it's considered failed and the underlying resource is tainted. A resource that is tainted will be re-created (destroyed, then created) by Terraform during the next deployment/apply
Provisioner usage example:
resource "null_resource" "dummy_resource" {
provisioner "local-exec" {
command = "echo 'created your resource'> status.txt"
#creation time
}
provisioner "local-exec" {
when = destroy
command = "echo 'destroyed your resource'> status.txt"
#destroy time
}
}
Terraform State
- Terraform state description
- It maps real-world resources to Terraform configuration.
- Contains output values.
- By default, state is stored locally in a file called
terraform. tfstate
. - Prior to any modification operation, Terraform refreshes the state file.
- Resource dependency metadata is also tracked via the state file.
- Helps boost deployment performance by caching resource attributes for subsequent use.
- Terraform state command
- Utility for manipulating and reading the Terraform State file.
- Scenario:
- Listing out tracked resources and their details via state and list subcommands
- Command:
terraform state list
to list all of the tracked resources in the state - Command:
terraform state show <resource-reference>
to get all of the provided resource informations in the state file - Manually remove a resource from Terraform State file so that it's not managed by Terraform. For advanced users only
- Advanced state management (eg: importing an existing resource in the state file)
- Local and Remote state storage
- Local state storage
- Saves Terraform state locally on your system in a file called
terraform.tfstate
- Terraform's default behavior.
- For personal projects.
- Remote state storage
- Saves state to a remote data source. Examples of storage: AWS S3, Google Storage
- Allows sharing state file between distributed teams.
When a state file is being in use for Plan, Apply or Destroy, Terraform puts a lock in it so other team members cannot access to it in order to avoid parallel execution
Terraform Modules
- What is a Terraform module ?
- A folder for multiple resources that are used together for code reusability.
- Every Terraform configuration has at least one module, called the root module, which consists of code files in your main working directory.
- Accessing and using Terraform modules
- Modules can be downloaded or referenced from:
- Terraform Public Registry
- A Private Registry
- Your Local system (since it is a directory)
- Modules are referenced using a module block.
- Modules can optionally take input and provide outputs to be used into your main code.
- Interacting with Terraform modules inputs and outputs
- Module inputs
- Module inputs are arbitrarily named parameters that you pass inside the module block.
- Module inputs can be used as variables inside the module code.
- Module outputs
- The outputs declared inside Terraform module code can be fed back into the root module or your main code
- Accessing the module output follows this pattern:
module.<name-of-module>.<name-of-output>
Example:
#In your module
output "instance_ip" {
value = aws_instance.private_ip
}
##################################################
#In your main terraform code (root module)
module "my-vpc-module" {
source = "./modules/vpc"
server-region = "us-east"
}
resource "dummy_resource" "my-root-resource" {
#...other parameters
vpc_ip = module.my-vpc-module.instance_ip
}
Built-in Functions and Dynamic Blocks
- Terraform built-in functions
- Terraform comes pre-packaged with functions to help you transform and combine values.
- User-defined functions are not allowed - only built-in ones.
- General syntax:
function_name(arg1, arg2, ...)
Usage example:
variable "project-name" {
type = string
default = "prod"
}
resource "aws_vpc" "my-vpc" {
cidr_block = "10.0.0.0/16"
tags {
Name = join("-",["terraform", var.project-name])
# The argument "Name" will have "terraform-prod" as value after using the join() function
}
}
Open a terminal, then type
terraform console
and test your function there- Terraform Type Constraints (Collections & Structural)
- Primitive types:
number
,string
,bool
,any
variable "example-var" {
type = bool
value = false
}
list(<TYPE>)
Constructors for these collections are:
variable "list-of-string" {
type = list(string)
default = ["alpha","beta","banana split","cupcake"]
}
tuple([<TYPE>, ...])
variable "tuple" {
type = tuple([string,number,bool])
default = ["alpha",15,false]
}
set(<TYPE>)
variable "set-of-number" {
type = set(number)
default = [10,77,48,50]
}
#A set is a list type that cannot contains duplicate element values
map(<TYPE>)
variable "map-of-string" {
type = map(string)
default = {
"primo" = "alpha"
"secondo" = "beta"
}
}
object({<ATTR NAME> = <TYPE>, ... })
variable "complex-object" {
type = object({
name = string
age = number
qualified = bool
misc = map(string)
})
default = {
name = "John"
age = 29
qualified = true
misc = {
"opinion" = "agree"
}
}
}
- Terraform dynamic blocks
- Dynamically constructs repeatable nested configuration blocks inside Terraform resources
- Supported within the following block types:
- resource
- data
- provider
- provisioner
- Used to make the code cleaner
Example:
#Without dynamic block
resource "aws_security_group" "my-sg" {
name = "prod-instance-sg"
vpc_id = aws_vpc.my-vpc.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cird_blocks = ["1.2.3.3/32"]
}
ingress {
#more rules
}
ingress {
#another rules
}
....
}
#Using dynamic block
resource "aws_security_group" "my-sg" {
name = "prod-instance-sg"
vpc_id = aws_vpc.my-vpc.id
dynamic "ingress" {
for_each = var.ingress-rules-map #Complex variable to iterate over
content {
from_port = ingress.value["from_port"] # The nested "content" block
to_port = ingress.value["to_port"] # defines the body of
protocol = ingress.value["protocol"] # each generated block
cird_blocks = ingress.value["cird_blocks"] # using the variable you provided
}
}
}
#The ingress-rules-map complex variable definition
variable "ingress-rules-map" {
default = {
rule_1 = {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["1.2.3.4/32"]
}
rule_2 = {
from_port = "any"
to_port = 443
protocol = "tcp"
cidr_blocks = ["1.2.3.4/32"]
}
#You can add more as you need
}
}
for
loop and outputs a nested block for each element in your variable.NOTES:
Terraform CLI
- Terraform format
- Formats Terraform code for readability
- Helps in keeping code consistent
- Safe to run at any time
- Scenario:
- Before pushing your code to version control
- After upgrading Terraform or its modules
- Any time you've made changes to code
- Syntax:
terraform fmt
#no other options required
- Terraform taint
- Taints a resource, forcing it to be destroyed and recreated upon the next Apply
- Modifies the state file, which causes the recreation workflow
- Tainting a resource may cause other dependant resources to be modified upon the next Apply
- Scenario:
- To cause provisioners to run.
- To replace misbehaving resources forcefully
- Syntax:
terraform taint RESOURCE_ADDRESS
#example
terraform taint aws_security_group.my-sg
- Terraform import
- Maps existing resources to Terraform using an "ID".
- The "ID" is dependent on the underlying vendor For example to import an AWS EC2 instance you'll need to provide its instance ID. Another example, to import a Helm chart release, you'll need to provide the release name suffixed by the namespace of the release
- Importing the same resource to multiple Terraform resources can cause unknown behavior and is NOT recommended.
- Scenario:
- When you need to work with existing resources.
- Not allowed to create new resources.
- Syntax:
terraform import RESOURCE_ADDRESS ID
#example
terraform import helm_release default/prod-release
- Terraform CLI configuration block
- A special configuration block for controlling Terraform's own behavior from the code.
- This block only allows constant values, named resources and variables are not allowed in it.
- Scenario:
- Configuring the backend for storing state files
- Specifying a required Terraform version
- Specifying a required Terraform Provider version and its requirements
- Enable and test Terraform experimental features
- Passing metadata to providers
- Usage example:
terraform {
required_version = ">=0.13.0" # Requires Terraform 0.13.0 or higher version
required_providers { # ˥
aws = ">=3.0.0" # Requires a provider "aws" with version 3.0.0 or higher
} # ˩
backend "remote" { # ˥
organization = "my-organization" #
workspaces { # Setup the backend for the state file
prefix = "infrastructure-" #
} #
} # ˩
}
- Terraform workspaces CLI
- The Terraform Workspaces are alternate state files within the same working directory.
- Terraform starts with a single workspace that is always called
default
. It cannot be deleted. - Scenario:
- Test changes using a parallel, distinct copy of infrastructure.
- Create similar infrastructure across different environments (production, staging, testing, etc...)
- It can be modeled against branches in version control such as Git.
- Terraform workspace subcommand examples
terraform workspace new <WORKSPACE_NAME>
#create a new terraform workpace with new empty statefile
terraform workspace select <WORKSPACE_NAME>
#select/use the given workspace
$(terraform.workspace}
variable.
It can be useful for resources naming purpose or for conditional resources creation, for example.- Debugging Terraform
TF_LOG
is an environment variable for enabling verbose logging in Terraform. By default, it will send logs tostderr
(standard error output) on your screen.TF_LOG
can be set to the following levels (values):TRACE
,DEBUG
,INFO
,WARN
,ERROR
TRACE
is the most verbose level of logging and the most reliable one.- To persist logged output, use the
TF_LOG_PATH
environment variable with a file path as value. - Usage example:
Setting logging environment variables for Terraform on Linux:
export TF_LOG=TRACE
export TF_LOG_PATH=./terraform.log
TF_LOG
set to TRACE
Terraform Cloud and Enterprise
- Sentinel (Embedded Policy-As-Code Framework) and its benefits
- Enforces policies on your code.
- Has its own policy language - Sentinel language.
- Designed to be approachable by non programmers (much more human-readable).
- Benefits:
- Sandboxing - Guardrails for automation and to protect against accidental deployments
- Codification - Easier understanding, better collaboration
- Integrated Version Control
- Testing and Automation
- Use case examples:
- For enforcing CIS standards across AWS accounts
- Checking to make sure only t3.micro instance types are used
- Ensuring Security Groups do not allow traffic on port 22
- Hashicorp Vault
- Secrets management software
- Dynamically provisions credentials and rotates them
- Encrypts sensitive data in transit and at rest and provides fine-grained access to secrets using Access Control List
- How does Vault work with Terraform?
- Developers don't need to manage long-lived credentials
- Inject secrets into your Terraform deployment at runtime
- Fine-grained ACLs for access to temporary credentials
- Terraform Registry
- A repository of publicly available Terraform providers and modules
- You can publish and share your own providers and modules
- You can collaborate with other contributors to make changes to providers and modules
- Can be directly referenced in your Terraform code
- URL: https://registry.terraform.io/
- Terraform Cloud Workspaces
- Workspace directories that is hosted in Terraform Cloud
- Stores old versions of state files by default
- Maintains a record of all execution activity
- All Terraform commands are executed on "managed" Terraform Cloud VMs by default
- Differentiating between Terraform Open Source Software Workspaces and Terraform Cloud Workspaces
Components | OSS Workspace | Cloud Workspace |
Terraform configuration | On disk | In linked version control repository or periodically Uploaded via CLI/API |
Variable values | As .tfvars files or
As CLI arguments or
In shell environment | In Terraform Cloud workspace as variables |
State | On disk or
In a remote backend | In Terraform Cloud workspace |
Credentials and Secrets | In shell environment or
Entered at prompts | In Terraform Cloud workspace as sensitive variables |
- Benefits of Terraform Cloud (Summary)
- Remote Terraform execution
- Version control integration (Github, Bitbucket etc)
- Private Terraform Module registry
- Workspace based organization model that enables cross-organization states sharing
- Cost estimation for AWS, GCP and Azure infrastructures
- Sentinel integration features for policies enforcement
Conclusion
- Infrastructure as Code allows you to deploy IT infrastructures simply by writing code
- Terraform is a Cloud agnostic Infrastructure as Code tool that uses HCL as configuration language
- The core Terraform workflow is: Write, Plan and Apply
- Terraform is able to interact with Cloud vendors API by using "providers”
- Terraform efficiently manages Cloud resources by referring to the state file
- Terraform uses the concept of workspace to manage states and replicas of the defined infrastructure
- Terraform Cloud offers even more features like policy enforcement, advanced secret management, remote execution, remote state management and more.