Terra Notes
Terra Notes
5. Terraform Workflow
Terraform follows a three-step workflow:
provider "aws" {
region = "us-east-1"
}
Stored in terraform.tfstate.
Keeps track of resource metadata like IDs, dependencies, and attributes.
Helps Terraform understand what it needs to create, update, or destroy.
Performance: Terraform doesn’t query the cloud provider for every operation.
Tracking Resources: Keeps track of real-world resources and maps them to your config.
Dependency Resolution: Ensures dependent resources are applied in the right order.
Collaboration: Remote state allows teams to work together.
Type Description
Local State Stored in terraform.tfstate on your machine.
Remote State Stored in a backend (AWS S3, Azure Storage, etc.), allowing team collaboration.
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-lock"
}
}
Key Points:
Command Purpose
terraform state list Lists all resources in the state file.
terraform state show <resource> Shows details of a resource.
Removes a resource from the state file (without destroying
terraform state rm <resource>
it).
terraform state mv <source>
<destination>
Moves a resource within the state file.
Terraform detects "drift" (differences between the real infrastructure and the state file).
Run:
terraform plan
o If it shows changes without modifying your .tf files, it means drift has occurred.
If a resource exists in AWS but is not in the state file, you can import it:
This only updates the state file; it does not create or modify resources.
6.9 Best Practices for Managing State
✅Use Remote State: Store state in S3, Azure Blob, or Terraform Cloud.
✅Enable State Locking: Use DynamoDB (AWS) or equivalent to prevent corruption.
✅Secure the State File: It contains sensitive data (e.g., credentials, ARNs).
✅Never Manually Edit terraform.tfstate: Always use Terraform CLI commands.
✅Backup State Files: If using local state, store backups securely.
Final Thought
Mastering Terraform’s state management gives you a deep understanding of how Terraform
tracks infrastructure. Expect interview questions like:
variable "instance_type" {
description = "The type of AWS EC2 instance"
type = string
default = "t2.micro"
}
output "instance_ip" {
description = "The public IP address of the instance"
value = aws_instance.example.public_ip
}
locals {
instance_count = 3
env_name = "staging"
}
variable "env" {
type = string
default = "dev"
}
locals {
instance_type = var.env == "prod" ? "t3.large" : "t2.micro"
}
variable "servers" {
type = map(string)
default = { "web" = "t2.micro", "db" = "t3.medium" }
}
variable "names" {
default = ["alice", "bob", "charlie"]
}
output "name_map" {
value = { for name in var.names : name => upper(name) }
}
Final Thoughts
To ace any Terraform interview, practice:
Here's a deep dive into Terraform State Management, covering every aspect in a way that
prepares you for any interview question.
Without state, Terraform would have to query the provider (AWS, Azure, GCP, etc.) every time
to determine what exists, which is inefficient and prone to errors.
1. terraform.tfstate
o The main state file that stores resource details, mappings, and metadata.
o Stored in JSON format and is crucial for Terraform's operation.
o Sensitive data (like passwords or keys) can be exposed if not handled correctly.
2. terraform.tfstate.backup
o A backup of the previous terraform.tfstate, created before any change.
o Helps with recovery if the main state file becomes corrupted or lost.
o Located in the same directory as terraform.tfstate.
{
"version": 4,
"terraform_version": "1.5.0",
"resources": [
{
"mode": "managed",
"type": "aws_instance",
"name": "web",
"provider": "provider.aws",
"instances": [
{
"attributes": {
"id": "i-0abcd12345efgh678",
"ami": "ami-12345678",
"instance_type": "t2.micro"
}
}
]
}
]
}
It prevents collaboration.
It can be accidentally deleted.
It isn't secure.
To solve this, Terraform supports Remote State, storing state in cloud storage services like:
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-lock"
}
}
attribute {
name = "LockID"
type = "S"
}
}
Terraform will automatically use DynamoDB for locking if configured in backend "s3".
Command Description
terraform state list Lists all resources in the state.
terraform state show <resource> Displays details about a specific resource.
terraform state mv <source>
<destination>
Moves a resource within state (useful for renaming).
Removes a resource from state (but doesn't delete it in
terraform state rm <resource>
cloud).
terraform state pull Retrieves the latest state file and prints it as JSON.
terraform state push Uploads a new state file (use with caution).
variable "db_password" {
type = string
sensitive = true
}
Final Thoughts
Mastering Terraform State Management requires understanding:
By following best practices, you'll be prepared for real-world use cases and technical
interviews where deep Terraform knowledge is expected. 🚀
Alright, let’s go extremely in-depth on Terraform Providers and Modules to ensure you have
the expertise to answer any interview question on these topics.
We’ll cover:
Each provider:
✅Defines resources (e.g., aws_instance, azurerm_virtual_machine)
✅Defines data sources (e.g., aws_ami, azurerm_resource_group)
✅Manages API authentication and communication
Provider Lifecycle
Terraform manages providers in a structured way:
Compares current infrastructure state with the desired state in Terraform files.
AWS: Access Key/Secret Key, IAM Role, Environment Variables, Shared Credentials.
Azure: Service Principal, Managed Identity, Environment Variables.
GCP: JSON Key File, Default Application Credentials.
Best Practices:
go install github.com/hashicorp/terraform-plugin-sdk/v2
package main
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/plugin"
"github.com/myorg/terraform-provider-example/example"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: example.Provider,
})
}
Create()
Read()
Update()
Delete()
go build -o terraform-provider-example
terraform init
terraform apply
Module Structure
A Terraform module follows this standard structure:
my-module/
├── main.tf # Defines resources
├── variables.tf # Defines input variables
├── outputs.tf # Defines output values
├── README.md # Documentation
# main.tf
resource "aws_instance" "web" {
ami = var.ami
instance_type = var.instance_type
}
# variables.tf
variable "ami" {
type = string
}
variable "instance_type" {
type = string
default = "t2.micro"
}
# outputs.tf
output "instance_id" {
value = aws_instance.web.id
}
module "webserver" {
source = "./my-module"
ami = "ami-123456"
instance_type = "t3.micro"
}
infrastructure/
├── vpc/ (module)
├── ec2️/ (module)
├── main.tf (calls both)
module "vpc" {
source = "./vpc"
cidr = "10.0.0.0/16"
}
module "ec2" {
source = "./ec2"
instance_type = "t2.micro"
vpc_id = module.vpc.vpc_id
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = ">= 3.0.0, < 4.0.0"
}
Final Thoughts
By deeply understanding Terraform Providers & Modules, you’re ready to answer any
interview question! 🚀
depends_on = [aws_s3_bucket.app_bucket]
}
Here, Terraform ensures that the S3 bucket is created before launching the EC2 instance, even
though there is no direct reference in the instance configuration.
✅When dependencies are not obvious to Terraform (e.g., when using provisioner blocks).
✅When a resource depends on an implicit process, like an S3 bucket needing to exist before an
S3 bucket policy applies.
✅When modules interact but don’t reference each other directly.
-target lets you apply only specific resources instead of the entire infrastructure.
Usage:
Terraform's lifecycle rules help control how resources are updated, recreated, or ignored.
1️⃣ create_before_destroy
Ensures that Terraform creates a new resource first before destroying the old one.
Example:
lifecycle {
create_before_destroy = true
}
}
Why?
2️⃣ ignore_changes
Prevents Terraform from modifying certain attributes even if they change outside Terraform.
Example:
lifecycle {
ignore_changes = [ami]
}
}
This means that even if the AMI changes manually, Terraform won’t modify the instance.
Why?
✅Useful when external automation modifies certain properties (e.g., Kubernetes auto-scaling).
✅Prevents Terraform from overriding manual changes.
Dynamic Blocks
Terraform dynamic blocks allow you to generate multiple similar configuration blocks
dynamically.
dynamic "ingress" {
for_each = [22, 80, 443]
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
How It Works
1️⃣ for_each = [22, 80, 443] iterates over a list of port numbers.
2️⃣ ingress.value represents each item in the list.
3⃣ Terraform dynamically generates three ingress rules.
✅When defining repetitive nested blocks, such as IAM policies, security rules, etc.
✅When managing configurations dynamically using variables.
Data Sources (data blocks)
data blocks allow Terraform to fetch existing resources instead of creating new ones.
1️⃣ count
Used when you need a fixed number of identical resources.
Limitations
❌Indexing issues when an item is removed (Terraform will destroy & recreate).
2️⃣ for_each
Used when iterating over maps or sets.
🚀 Creates two S3 buckets: one for dev and one for prod.
3️⃣ provider
Used to assign different providers to different resources.
provider "aws" {
alias = "us_east"
region = "us-east-1"
}
provider "aws" {
alias = "us_west"
region = "us-west-2"
}
Summary Table
Feature Use Case Caution
for_each Dynamic resources with unique keys More complex than count
Would you like some real-world examples or mock interview questions to practice? 🚀
This is a common strategy where you maintain separate directories for each environment.
terraform-project/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── terraform.tfvars
│ ├── staging/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── terraform.tfvars
│ ├── prod/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── terraform.tfvars
│
├── modules/
│ ├── networking/
│ ├── compute/
│ ├── database/
Pros
Terraform workspaces provide a built-in way to manage multiple environments within the
same configuration. You use terraform workspace to switch between different logical
environments.
Key Commands
Initialize Terraform:
terraform init
Create a new workspace:
terraform workspace new dev
List available workspaces:
terraform workspace list
Switch between workspaces:
terraform workspace select prod
By default, Terraform starts with a default workspace. When you create new workspaces (dev,
staging, prod), Terraform automatically namespaces state files for isolation.
Pros
Cons
All environments share the same backend, which can introduce risks.
Workspaces work well for ephemeral environments, but not ideal for long-lived environments
like prod.
A more robust approach is using a separate Terraform backend (such as an S3 bucket with a
different state file for each environment).
Example backend.tf:
terraform {
backend "s3" {
bucket = "my-terraform-states"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
}
}
terraform {
backend "s3" {
bucket = "my-terraform-states"
key = "dev/terraform.tfstate"
region = "us-east-1"
encrypt = true
}
}
Pros
Cons
my-bucket-dev
Use workspaces for short-lived environments (e.g., feature branches, temporary testing).
Avoid using workspaces for production and staging, since they share the same backend.
Use Terraform backend configurations for persistent environments like prod.
Each environment should have an isolated Terraform state file. This can be achieved using:
instance_type = "t2.micro"
For prod:
instance_type = "t3.large"
Example module:
module "networking" {
source = "./modules/networking"
vpc_cidr = var.vpc_cidr
}
Use Terraform Cloud, GitHub Actions, or Jenkins to automatically apply changes in different
environments.
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
instance_type = "t2.micro"
Use it with:
export TF_VAR_instance_type="t2.micro"
terraform apply
3. Using .auto.tfvars
Terraform automatically loads .auto.tfvars files, removing the need to specify them manually.
Example dev.auto.tfvars:
instance_type = "t2.micro"
variable "instance_type" {
type = string
default = "t2.micro"
}
locals {
instance_type = terraform.workspace == "prod" ? "t3.large" : var.instance_type
}
Final Thoughts
Terraform workspaces and environment management are crucial for multi-environment
deployments. You should:
1. Understand different approaches (workspaces vs. directory structure vs. backend separation).
2. Use environment-specific variables effectively.
3. Adopt best practices like CI/CD, state isolation, and modular code.
With this knowledge, you should be able to ace any Terraform-related interview questions! 🚀
Terraform Cloud and Terraform Enterprise provide a managed service for Terraform, offering
features like remote state management, workspace organization, policy enforcement,
automation, and integrations with other systems. Let's go in-depth into all the components you
need to master for an interview.
Terraform Cloud acts as a remote backend, eliminating the need for self-managed state files.
Key Features:
State Locking: Ensures only one person modifies the state at a time.
State Versioning: Keeps historical versions of the state for rollback.
Secure Storage: Stores state data in Terraform Cloud, encrypted at rest.
State Sharing: Workspaces can share state using data sources.
1.2 Workspaces
Terraform Cloud uses workspaces to separate different infrastructure environments (e.g., dev,
staging, production).
Workspace Benefits
Workspace Components
2. Terraform Enterprise
Terraform Enterprise is the self-hosted version of Terraform Cloud, offering advanced security
and customization.
2.1 Cost Estimation
Before applying changes, Terraform Enterprise provides a cost estimate to help organizations
manage cloud spending.
How It Works:
Common Policies:
Use Cases:
Agent Setup:
1. How does Terraform Cloud handle remote state differently from self-managed backends?
2. What is the purpose of Terraform Cloud Agents, and how do they work?
3. How do Sentinel policies enforce security and compliance in Terraform Cloud?
4. How does the Terraform Cloud API enable automation, and what are its key endpoints?
5. Can you describe the process of cost estimation in Terraform Enterprise?
6. How does Terraform Cloud integrate with CI/CD tools?
7. How do you troubleshoot failed Terraform runs in Terraform Cloud?
Conclusion
By mastering Terraform Cloud & Enterprise, you can confidently handle interviews and real-
world Terraform automation tasks. This guide covered Remote State, Workspaces, Sentinel,
Enterprise Features, Terraform Agents, and the Terraform Cloud API in-depth.
Security and compliance in Terraform ensure that infrastructure is deployed securely while
following industry best practices and governance policies. Below is an in-depth breakdown of
each aspect.
Example:
organization "my-org" {
policy "deny_destroy" {
enforcement_level = "hard-mandatory"
}
}
RBAC in AWS
Use IAM roles to define least privilege:
resource "aws_iam_policy" "example" {
name = "TerraformAccess"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = ["ec2:Describe*", "s3:ListBucket"]
Resource = "*"
}]
})
}
Never give Terraform admin privileges.
RBAC in Kubernetes
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
Would you like me to generate mock interview questions for you to test your knowledge? 🚀
Debugging Approach:
TF_LOG Levels:
Level Description
TRACE Very detailed logs, including sensitive information.
DEBUG Includes internal function calls and detailed messages.
INFO General high-level logs (default level).
WARN Shows warnings without stopping execution.
ERROR Only logs errors that cause Terraform to stop.
Pro Tips
Remediation Strategies
Scenario Solution
Resource exists in the cloud but not in state terraform import
Resource exists in state but not in cloud terraform apply or terraform destroy
Attributes changed outside Terraform terraform apply (overwrites manual changes)
Final Notes
Always enable logging in CI/CD to capture TF_LOG=DEBUG output.
Regularly run drift detection to prevent surprises.
Know how to read Terraform crash logs—this is an advanced skill that interviewers love
to ask about!
When you run terraform apply, Terraform checks the dependency graph to determine
which resources can be created concurrently.
Resources without explicit dependencies on each other are deployed simultaneously.
You can control the level of parallelism using the -parallelism=N flag.
Suggested
Scenario Reason
Parallelism
Large deployments with independent
Increase (20+) Faster execution
resources
APIs with rate limits (e.g., AWS, Azure) Decrease (5-10) Prevent throttling
Avoid overloading Terraform
Limited compute resources Decrease (5-10)
process
1 (sequential
Debugging or diagnosing failures Helps isolate issues
execution)
Example Usage
lifecycle {
ignore_changes = [ tags, user_data ]
}
}
This prevents Terraform from tracking changes to tags and user_data, reducing
unnecessary state updates.
State locking: Prevents multiple users from applying changes at the same time.
Collaboration: Enables shared state access for teams.
Scalability: Offloads storage and versioning to a managed service.
Backend Features
AWS S3 + DynamoDB State storage + locking via DynamoDB
Terraform Cloud Built-in collaboration, workspaces, state locking
Google Cloud Storage (GCS) Native support in GCP
Azure Blob Storage Secure remote storage for Terraform state
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "state/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
Instead of managing everything in one Terraform file, use modules for reusable
components.
Example directory structure:
├── modules/
│ ├── networking/
│ ├── compute/
│ ├── database/
├── environments/
│ ├── dev/
│ ├── prod/
This makes maintenance easier and improves performance.
Workspaces allow multiple environments (e.g., dev, staging, prod) without duplicating
Terraform files.
Instead of applying all resources, target only the ones that changed:
Use logging tools like AWS CloudWatch or Terraform Cloud's built-in logs to track
performance issues.
Run terraform validate before apply to catch misconfigurations.
Summary Table
Optimization Area Key Actions
Parallelism Adjust -parallelism=N for speed and API limits
Ignore unnecessary attributes, use terraform state rm, modularize
State Size Optimization
infrastructure
Efficient terraform plan Use -target, -refresh=false, and output plan to a file
Store state in S3, GCS, Terraform Cloud for scalability and
Remote Backends
collaboration
Large-Scale Best
Use modules, workspaces, targeted apply, and state locking
Practices
Final Thoughts
Mastering performance optimization in Terraform is crucial for handling large-scale
infrastructure efficiently. By adjusting parallelism, optimizing state, using terraform plan smartly,
leveraging remote backends, and following best practices, you can ensure Terraform runs
efficiently—even at enterprise scale.
Would you like me to generate Terraform examples or practice interview questions based on
this? 🚀
Let's go deep into integrating Terraform with CI/CD pipelines, covering best practices, real-
world implementations, and advanced techniques.
Terraform with CI/CD Pipelines – Mastering the Integration
When integrating Terraform, your pipeline should run the following commands:
a) terraform fmt
b) terraform validate
c) terraform plan
d) terraform apply
c) Unit Testing
Example:
terraform plan -out=tfplan
terraform show -json tfplan | jq .
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-lock"
}
}
Example:
variable "active_environment" {
default = "blue"
}
on:
push:
branches:
- main
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
stages:
- validate
- plan
- apply
terraform_init:
stage: validate
script:
- terraform init
- terraform validate
only:
- main
terraform_plan:
stage: plan
script:
- terraform plan -out=tfplan
only:
- main
terraform_apply:
stage: apply
script:
- terraform apply -auto-approve tfplan
when: manual
only:
- main
Final Notes
This should give you expert-level knowledge of Terraform CI/CD, making you confident for any
interview or real-world implementation. Want me to dive even deeper into any specific part? 🚀
Here's a detailed breakdown of Infrastructure Testing and Validation with Terraform, covering
validation, unit testing, testing frameworks, and policy as code in depth.
1. Terraform Validation
Before applying Terraform configurations, you can validate their syntax and logical structure
using terraform validate. This is a static check that ensures:
Usage
terraform validate
Limitations:
terraform plan shows what changes Terraform will make before applying them. We can capture
and analyze this output.
Infracost is useful for financial validation, ensuring that infrastructure meets budget
constraints.
Prevent merging a PR if the new infrastructure costs increase by more than 10%.
3. Testing Frameworks
Automated infrastructure testing is critical. Here are three major Terraform testing
frameworks:
(a) Terratest
Terratest is a Go-based framework that deploys infrastructure, runs assertions, and then
destroys it.
Features:
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
// Validate outputs
bucketName := terraform.Output(t, terraformOptions, "bucket_name")
assert.Contains(t, bucketName, "my-test-bucket")
}
🚀 Key Aspects:
Limitations:
(b) Kitchen-Terraform
Kitchen-Terraform is based on Test Kitchen and supports Ruby-based infrastructure testing.
Workflow:
🚀 Key Aspects:
Limitations:
(c) Checkov
Checkov is a static code analysis tool that scans Terraform for security and compliance issues.
Usage
checkov -d .
Example Output
FAILED Check: Ensure S3 bucket is encrypted
- File: main.tf, Line: 12
- Expected: server_side_encryption_configuration is enabled
Custom Policy Example
metadata:
id: "CUSTOM_001"
name: "Ensure all S3 buckets have encryption enabled"
category: "security"
definition:
cond_type: "attribute"
resource_types: ["aws_s3_bucket"]
attribute: "server_side_encryption_configuration"
operator: "exists"
Workflow
deny[msg] {
input.resource_type == "aws_s3_bucket"
not input.server_side_encryption_configuration
msg := "S3 bucket must have encryption enabled"
}
Downsides:
Conclusion
Best Tools for Different Use Cases
Would you like to dive deeper into writing Rego policies or specific CI/CD integrations? 🚀
Here’s a deep dive into customizing Terraform, including writing custom providers, developing
and sharing modules, using external data sources, and integrating Terraform with Python and
Bash.
1. Provider Schema: Defines the provider configuration (e.g., API keys, authentication).
2. Resource Schema: Defines the structure of a resource.
3. CRUD Operations: Implement Create, Read, Update, and Delete functions.
4. Data Sources: Allow Terraform to fetch information from an external API.
You'll need:
Go installed (go version to check)
Terraform Plugin SDK (go get github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema)
package main
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/plugin"
"example.com/terraform-provider-example/example"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: example.Provider,
})
}
Inside example/provider.go:
package example
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
Inside example/resource_example.go:
package example
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
},
}
}
Place it in your Terraform plugins directory and define your Terraform config to use the
provider.
Create a main.tf:
variable "instance_name" {}
Create a variables.tf:
variable "instance_name" {
description = "The name of the EC2 instance"
type = string
}
Create an outputs.tf:
output "instance_id" {
value = aws_instance.example.id
}
module "ec2_instance" {
source = "github.com/username/terraform-aws-my-module"
instance_name = "MyInstance"
}
output "external_data" {
value = data.external.example.result
}
#!/usr/bin/env python3
import json
Key Points:
import subprocess
# Initialize Terraform
subprocess.run(["terraform", "init"])
Executing:
chmod +x deploy.sh
./deploy.sh
Final Thoughts
Writing custom providers requires Go knowledge but is powerful.
Modules make Terraform reusable and shareable.
External provider allows data injection from any external system.
Python/Bash integration automates Terraform workflows.
Would you like me to dive even deeper into any specific area?
Here's a detailed breakdown of these topics to ensure you have a deep understanding and can
confidently answer interview questions.
Why Multi-Cloud?
Resilience & Redundancy: Avoid vendor lock-in and ensure high availability.
Regulatory Compliance: Some regions require data to be stored in specific clouds.
Cost Optimization: Utilize pricing differences between providers.
Best-of-Breed Services: AWS Lambda, Azure AD, Google’s AI/ML services.
Unified Configuration: Write a single Terraform codebase to manage AWS, Azure, and GCP.
State Management: Terraform’s remote state storage (S3, Azure Blob, Google Cloud Storage).
Provider Abstraction: Define multiple providers (aws, azurerm, google).
Modules & Workspaces: Isolate cloud-specific configurations while maintaining consistency.
Azure Functions
Event-Driven Architectures
Networking Components