Terraform — Operations¶
Scope
State management, workspace patterns, CI/CD integration, drift detection, and operational best practices.
State Management¶
Backend Configuration¶
| Backend | State Locking | Encryption | Team Use | Cost |
|---|---|---|---|---|
| S3 + DynamoDB | Yes | SSE-S3/KMS | Multi-user | Low |
| GCS | Yes (native) | Yes | Multi-user | Low |
| Azure Blob | Yes (lease) | Yes | Multi-user | Low |
| Terraform Cloud | Yes | Yes | Enterprise | Free-$$ |
| Consul | Yes | Optional | Self-hosted | Free |
| Local | No | No | Single user | Free |
# Production S3 backend
terraform {
backend "s3" {
bucket = "company-terraform-state"
key = "prod/network/terraform.tfstate"
region = "us-east-1"
encrypt = true
kms_key_id = "alias/terraform-state"
dynamodb_table = "terraform-lock"
}
}
State Operations¶
# Import existing resource
terraform import aws_instance.web i-1234567890abcdef0
# Move resource in state
terraform state mv aws_instance.old aws_instance.new
# Remove from state without destroying
terraform state rm aws_instance.decommissioned
# List all resources
terraform state list
# Show specific resource
terraform state show aws_instance.web
Workspace Patterns¶
Environment Isolation¶
# Per-environment workspaces
terraform workspace new staging
terraform workspace new production
terraform workspace select production
# Use workspace in configs
locals {
env = terraform.workspace
instance_type = {
staging = "t3.small"
production = "t3.xlarge"
}
}
Workspace vs Directory
For significantly different environments, use separate directories with shared modules instead of workspaces. Workspaces share the same backend config and variable structure.
CI/CD Integration¶
GitHub Actions Pattern¶
- name: Terraform Plan
run: |
terraform init -backend-config=backend.hcl
terraform plan -out=tfplan -input=false
terraform show -json tfplan > plan.json
- name: Terraform Apply
if: github.ref == 'refs/heads/main'
run: terraform apply -auto-approve tfplan
Drift Detection¶
# Detect drift without applying
terraform plan -detailed-exitcode
# Exit code: 0 = no changes, 1 = error, 2 = changes detected
Performance Optimization¶
| Strategy | Impact | When to Use |
|---|---|---|
parallelism flag |
Faster apply | Large infra (default: 10) |
-refresh=false |
Skip state refresh | When you know state is current |
-target flag |
Apply specific resources | Emergency fixes (avoid in CI) |
| Module splitting | Reduce blast radius | 50+ resources per state |
| Provider caching | Faster init | CI/CD pipelines |
Common Issues¶
| Issue | Root Cause | Resolution |
|---|---|---|
| State lock stuck | Crashed apply | terraform force-unlock <ID> |
| Provider version conflict | Loose constraints | Pin provider versions exactly |
| Cycle detected | Circular dependencies | Use depends_on or restructure |
| State drift | Manual changes | terraform refresh then fix |
| Slow plan | Large state file | Split into smaller states |