Terraform Master Documentation
Terraform is a product by Hashicorp that uses Infrastructure as Code (IaC) to provision cloud infrastructure. With the right approach and resources, learning Terraform can be an exciting and rewarding experience, regardless of your background or familiarity with related concepts. In this getting started Terraform tutorial, we will cover all the basics (and more) of the Terraform workflow and show how to use Terraform step-by-step, enabling you to manage cloud infrastructure with IaC.
Definition:
Terraform is an IaC tool that allows users to provision and manage infrastructure resources across various cloud platforms and on-premises environments. It uses declarative configuration files, written in HashiCorp Configuration Language (HCL) or JSON, to define and automate the lifecycle of resources, ensuring predictability and consistency. Terraform’s extensible plugin-based architecture supports a wide range of providers, enabling seamless integration and management of diverse infrastructure environments.
Purpose:
Manage infrastructure with code to enable reproducibility and automation.
Features:
Infrastructure as Code: Write infrastructure in a declarative configuration language.
Execution Plans: Preview changes before applying them.
Resource Graph: Creates a dependency graph to determine resource creation order.
Change Automation: Applies complex changes with minimal human interaction.
Benefits:
Consistency: Ensures the same infrastructure is provisioned every time.
Version Control: Infrastructure configurations can be stored in version control systems.
Scalability: Easily scale infrastructure up or down.
Collaboration: Teams can collaborate on infrastructure as code.
Automation: Reduces manual provisioning errors and effort.
Integration:
Terraform integrates with numerous providers and services including:
Cloud Providers: AWS, Azure, Google Cloud, Oracle Cloud.
Configuration Management Tools: Chef, Puppet, Ansible.
Version Control Systems: GitHub, GitLab.
CI/CD Tools: Jenkins, CircleCI, GitLab CI.
Configuration Files:
Terraform configuration files are the cornerstone of defining and managing infrastructure as code. These files are written in HashiCorp Configuration Language (HCL) or optionally JSON, and they describe the desired state of your infrastructure.
File Extensions: .tf for HCL files, .tf.json for JSON files.
Key Elements of Configuration Files
Providers
Resources
Variables
Outputs
Modules
Data Sources
Locals
Provisioners
Lets deep dive into each of them.
Providers
Definition: Providers are plugins that interact with various APIs and services. Each provider requires configuration to establish connections and define settings.
provider "aws" { region = "us-west-2" }Example: Configuring AWS as a provider.
provider "aws" { region = "us-west-2" access_key = "your_access_key" secret_key = "your_secret_key" }Resources
Definition: Resources define the components of your infrastructure, such as virtual machines, storage accounts, and networking components
resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" }Example: Creating an AWS EC2 instance.
resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" tags = { Name = "example-instance" } }Variables
Definition: Variables allow parameterization of Terraform configurations to make them flexible and reusable.
Types: String, Number, Boolean, List, Map, Object, Tuple
variable "instance_type" { type = string default = "t2.micro" }Example: Defining and using variables.
variable "region" { type = string default = "us-west-2" } provider "aws" { region = var.region }Outputs
Definition: Outputs export values from your Terraform configuration. These can be used for referencing in other configurations or for display purposes.
output "instance_id" { value = aws_instance.example.id }Example: Defining an output value.
output "instance_id" { value = aws_instance.example.id } output "instance_public_ip" { value = aws_instance.example.public_ip }Modules
Definition: Modules encapsulate multiple resources into reusable and manageable pieces. They allow you to create complex configurations by combining smaller components.
module "vpc" { source = "./modules/vpc" cidr = "10.0.0.0/16" }Example: Using a module for VPC creation.
module "vpc" { source = "./modules/vpc" cidr = "10.0.0.0/16" } module "web_server" { source = "./modules/web_server" instance_type = var.instance_type vpc_id = module.vpc.vpc_id }Data Sources
Definition: Data sources allow Terraform to use information defined outside of Terraform, such as values from other resources or services.
data "aws_ami" "example" { most_recent = true filter { name = "name" values = ["amzn-ami-hvm-*-x86_64-gp2"] } owners = ["self"] }Example: Using a data source to get the latest AMI.
data "aws_ami" "example" { most_recent = true filter { name = "name" values = ["amzn-ami-hvm-*-x86_64-gp2"] } owners = ["amazon"] } resource "aws_instance" "example" { ami = data.aws_ami.example.id instance_type = "t2.micro" }Locals
Definition: Local values assign names to expressions, allowing you to use them multiple times in your configuration without repeating the expression.
locals { instance_type = "t2.micro" }Example: Defining local values.
locals { instance_type = "t2.micro" ami_id = "ami-0c55b159cbfafe1f0" } resource "aws_instance" "example" { ami = local.ami_id instance_type = local.instance_type }Provisioners
Definition: Provisioners allow you to execute scripts or commands on a local machine or on a remote resource after it's created or destroyed.
Types: local-exec, remote-exec.
resource "aws_instance" "example" { provisioner "local-exec" { command = "echo ${self.public_ip} >> ip_addresses.txt" } }Example: Using a provisioner to run a local script.
resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" provisioner "local-exec" { command = "echo ${self.public_ip} >> ip_addresses.txt" } }Best Practices for Configuration Files
Organize Files: Use a logical file structure. Separate providers, resources, variables, outputs, and modules into different files.
DRY Principle: Avoid repetition. Use variables, locals, and modules to keep configurations DRY (Don't Repeat Yourself).
Use Version Control: Always version control your Terraform configurations to track changes and enable collaboration.
Document Configurations: Clearly document what each file, module, and variable does.
Use Remote State: For team collaboration and consistency, store Terraform state in a remote backend.
Data Types:
Terraform supports various data types to define and manage infrastructure more effectively. Understanding these data types is essential for writing robust and flexible Terraform configurations.
String
Definition: Represents textual data.
Usage: Commonly used for names, IDs, paths, etc.
variable "example_string" { type = string default = "Hello, Terraform!" }Number
Definition: Represents numeric values, either integers or floating-point.
Usage: Used for quantities, counts, sizes, etc.
variable "example_number" { type = number default = 42 }Boolean
Definition: Represents true or false values.
Usage: Used for enabling/disabling features, toggles, etc.
variable "example_boolean" { type = bool default = true }List
Definition: An ordered sequence of values, all of the same data type.
Usage: Used for multiple values of the same type, such as IP addresses, instance IDs, etc.
variable "example_list" { type = list(string) default = ["value1", "value2", "value3"] }Map
Definition: A collection of key-value pairs, where keys are strings.
Usage: Used for associative arrays, such as configurations, tags, etc.
variable "example_map" { type = map(string) default = { key1 = "value1" key2 = "value2" } }Set
Definition: An unordered collection of unique values, all of the same data type.
Usage: Used for collections where order does not matter, but uniqueness does, such as security group rules.
variable "example_set" { type = set(string) default = ["value1", "value2", "value3"] }Object
Definition: A collection of named attributes that each have their own type.
Usage: Used for complex data structures with named attributes, such as resource configurations.
variable "example_object" { type = object({ id = string count = number active = bool }) default = { id = "example" count = 10 active = true } }Tuple
Definition: An ordered sequence of values, each of which can have a different type.
Usage: Used for fixed-length sequences where each element has a specific type.
variable "example_tuple" { type = tuple([string, number, bool]) default = ["example", 42, true] }Terraform configurations often use complex structures involving multiple data types. Here's an example that combines several types:
variable "app_config" { type = object({ name = string version = string instances = number zones = list(string) tags = map(string) }) default = { name = "my-app" version = "1.0" instances = 3 zones = ["us-west-2a", "us-west-2b"] tags = { Name = "my-app" Version = "1.0" } } } resource "aws_instance" "example" { count = var.app_config.instances ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" availability_zone = element(var.app_config.zones, count.index) tags = var.app_config.tags }
State File
The Terraform state file is a fundamental component of how Terraform operates. It tracks the current state of your infrastructure, mapping Terraform configurations to real-world resources.
Definition:
The state file is a JSON file that stores information about the infrastructure resources managed by Terraform.
Purpose:
It keeps track of resource metadata, helps with mapping resources to configuration files, and enables efficient updates by storing the current state of your infrastructure.
Features and Benefits
- Resource Mapping
Feature: Maps Terraform resource names to actual resource IDs in the infrastructure.
Benefit: Ensures Terraform knows which resources it is managing, facilitating operations like apply and destroy.
- Plan and Apply Efficiency
Feature: Stores the state of resources to efficiently create plans and apply changes.
Benefit: Increases speed and accuracy by comparing the current state with the desired state.
- Dependency Management
Feature: Tracks dependencies between resources.
Benefit: Ensures resources are created or destroyed in the correct order.
- Drift Detection
Feature: Detects changes outside of Terraform.
Benefit: Alerts users to manual changes or configuration drift.
- Collaboration
Feature: When stored remotely, state files can be shared among team members.
Benefit: Facilitates collaboration and consistency across teams.
- Best Practices
Use Remote Backends
Store state files remotely to facilitate team collaboration and state locking.
Enable State Locking
Prevents concurrent operations that could corrupt the state file.
Encrypt State Files
Protect sensitive information by encrypting state files.
Version Control State Management Code
Use version control for Terraform configurations, but do not store state files in version control.
Regular Backups
Keep regular backups of state files to prevent data loss.
Use Workspaces for Multiple Environments
Use Terraform workspaces to manage different environments (e.g., dev, staging, production) within a single configuration.
Remote Backend
Remote backends allow Terraform to store the state file in a remote location, providing features such as collaboration, locking, and state management. Some commonly used remote backends include AWS S3, Azure Blob Storage, Google Cloud Storage, and Terraform Cloud.
Benefits of Remote Backends
Collaboration
Teams can work together on the same Terraform configuration and state file.
State Locking
Prevents simultaneous operations that can lead to state corruption.
Ensures only one user can modify the state at a time.
Persistence and Availability
State files are stored in a reliable and highly available storage service.
Security
State files can be encrypted and access-controlled.
Centralized Management
Easier to manage and track state files from a central location.
Configuring Remote Backends
AWS S3 Example
Create an S3 Bucket
Ensure the bucket is configured for versioning and server-side encryption.
Configure Backend in Terraform
Add backend configuration to the Terraform configuration file.
terraform { backend "s3" { bucket = "my-terraform-state-bucket" key = "path/to/my/statefile" region = "us-west-2" dynamodb_table = "my-lock-table" encrypt = true } }Initialize Terraform
Run terraform init to initialize the backend.
Detailed Configuration of Remote Backends
AWS S3 with DynamoDB for State Locking
Create an S3 Bucket and DynamoDB Table
Ensure the S3 bucket has versioning and server-side encryption enabled.
Create a DynamoDB table with a primary key named LockID for state locking.
Configure Backend
Add the backend configuration to your Terraform configuration file.
terraform { backend "s3" { bucket = "my-terraform-state-bucket" key = "path/to/my/statefile" region = "us-west-2" dynamodb_table = "my-lock-table" encrypt = true } }IAM Policies
Ensure the IAM role or user Terraform uses has the appropriate permissions for S3 and DynamoDB.
S3 Policy:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::my-terraform-state-bucket", "arn:aws:s3:::my-terraform-state-bucket/*" ] } ] }DynamoDB Policy:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:PutItem", "dynamodb:GetItem", "dynamodb:DeleteItem", "dynamodb:Scan" ], "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/my-lock-table" } ] }Initialize Terraform
Run terraform init to initialize the backend.
Advanced State Management
State Versioning
Enable versioning in the remote storage backend to track state file changes over time.
State Environments
Use Terraform workspaces to manage different environments within the same configuration.
State File Splitting
Split state files by using multiple Terraform configurations or workspaces to manage large infrastructures.
State Management Commands
terraform state list: List resources in the state.
terraform state show <resource>: Show detailed state for a resource.
terraform state mv <source> <destination>: Move resources in the state.
terraform state rm <resource>: Remove resources from the state.
terraform state pull: Pull the current state.
terraform state push: Push a state file to a remote backend.
Example of Managing State
Listing Resources
terraform state listShowing Resource Details
terraform state show aws_instance.exampleMoving Resources
terraform state mv aws_instance.exampleaws_instance.new_exampleRemoving Resources
terraform state rm aws_instance.exampleBy understanding and implementing these best practices and features of Terraform state files and remote backends, you can efficiently manage your infrastructure as code, enhance collaboration, and maintain the integrity and security of your state files.
- Modules
Definition: Modules encapsulate multiple resources into reusable and manageable pieces. They allow you to create complex configurations by combining smaller components.
Usuage:
module "vpc" { source = "./modules/vpc" cidr = "10.0.0.0/16" }Example: Using a module for VPC creation.
module "web_server" { source = "./modules/web_server" instance_type = var.instance_type vpc_id = module.vpc.vpc_id }
