What Terraform Does
- Declarative Config: Define desired state, Terraform figures out how to get there
- Execution Plans: Preview exactly what will change before applying
- Resource Graph: Automatic dependency resolution and parallel creation
- State Management: Track real-world resources in state files (local or remote)
- Modules: Reusable infrastructure components for DRY configuration
- Multi-Cloud: Manage AWS, Azure, GCP, Kubernetes, DigitalOcean, and more from one tool
- Import: Bring existing resources under Terraform management
- Workspaces: Manage multiple environments (dev/staging/prod) from one codebase
Architecture
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ .tf files │────▶│ Terraform │────▶│ Cloud APIs │
│ (HCL config)│ │ Core │ │ AWS │
└──────────────┘ │ (Go) │ │ Azure │
└──────┬───────┘ │ GCP │
│ │ K8s │
┌──────┴───────┐ │ 3000+ more │
│ State File │ └──────────────┘
│ (JSON) │
└──────────────┘Basic Example
main.tf (AWS EC2 Instance)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "web-server"
Env = "production"
}
}
resource "aws_security_group" "web" {
name = "web-sg"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
output "instance_ip" {
value = aws_instance.web.public_ip
}Workflow
# Initialize (download providers)
terraform init
# Preview changes
terraform plan
# Apply changes
terraform apply
# Get outputs
terraform output instance_ip
# Destroy everything
terraform destroyVariables & Modules
Variables
# variables.tf
variable "environment" {
type = string
default = "dev"
}
variable "instance_count" {
type = number
default = 1
}
variable "tags" {
type = map(string)
default = {
Owner = "devops"
}
}
# Using variables
resource "aws_instance" "web" {
count = var.instance_count
ami = "ami-..."
instance_type = var.environment == "prod" ? "t3.large" : "t3.micro"
tags = merge(var.tags, {
Environment = var.environment
})
}Modules
# Use a module
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-west-2a", "us-west-2b", "us-west-2c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = false
}State Management
Local State (Default)
terraform.tfstate # Current state
terraform.tfstate.backup # Previous stateRemote State (Production)
# backend.tf
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-west-2"
dynamodb_table = "terraform-locks" # State locking
encrypt = true
}
}Benefits of remote state:
- Team collaboration (shared state)
- State locking (prevent concurrent modifications)
- Encrypted storage
- Versioning and backup
Multi-Cloud Example
# AWS + Cloudflare + Kubernetes
provider "aws" { region = "us-west-2" }
provider "cloudflare" { api_token = var.cf_token }
provider "kubernetes" {
config_path = "~/.kube/config"
}
# Create AWS EC2 instance
resource "aws_instance" "web" { ... }
# Create Cloudflare DNS record pointing to EC2
resource "cloudflare_record" "web" {
zone_id = var.cf_zone_id
name = "www"
value = aws_instance.web.public_ip
type = "A"
}
# Deploy to Kubernetes
resource "kubernetes_deployment" "app" {
metadata { name = "my-app" }
spec {
replicas = 3
template {
spec {
container {
image = "myapp:latest"
name = "app"
}
}
}
}
}Terraform vs Alternatives
| Feature | Terraform | OpenTofu | Pulumi | CloudFormation |
|---|---|---|---|---|
| Open Source | BSL | MPL-2.0 | Apache-2.0 | No |
| Language | HCL | HCL | Python/TS/Go/C# | YAML/JSON |
| Multi-cloud | Yes | Yes | Yes | AWS only |
| Providers | 3000+ | Same as TF | 100+ | AWS services |
| State backend | Multiple | Multiple | Cloud (free) | AWS managed |
| Community | Very large | Growing | Large | AWS focused |
OpenTofu — The Open Source Fork
Note: In August 2023, HashiCorp changed Terraform's license from MPL-2.0 to BSL. The Linux Foundation and community created OpenTofu as an open-source fork. OpenTofu is drop-in compatible with Terraform 1.5.x and maintains MPL-2.0 licensing.
# Use OpenTofu instead (drop-in replacement)
brew install opentofu
tofu init
tofu plan
tofu apply常见问题
Q: Terraform 和 Ansible 有什么区别? A: Terraform 主要用于基础设施供应(创建云资源如 VM、网络、数据库)。Ansible 主要用于配置管理(在已有机器上安装软件和配置)。两者经常配合:Terraform 创建服务器,Ansible 配置服务器。
Q: BSL 许可证对使用有影响吗? A: 对绝大多数用户没影响。BSL 限制是不能将 Terraform 作为商业产品竞品提供(如创建自己的 HashiCorp Cloud 竞品)。个人、企业内部使用完全不受限。担心许可证问题可以用 OpenTofu。
Q: State 文件丢失怎么办? A: State 文件非常重要,丢失意味着 Terraform 不知道哪些资源属于它管理。务必使用远程 state 后端(S3、Azure Blob、GCS)并启用版本控制。定期备份 state 文件。
来源与致谢
- GitHub: hashicorp/terraform — 48.1K+ ⭐ | BSL
- 官网: terraform.io
- OpenTofu: opentofu.org