Terraform 核心概念

深入理解 Terraform 的核心概念,是掌握 IaC 的关键。

一、Providers(提供者)

1.1 Provider 是什么

Provider 是 Terraform 与云平台、SaaS 服务交互的插件。

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
  }
}

provider "aws" {
  region = "us-west-2"
}

provider "azurerm" {
  features {}
}

1.2 常用 Providers

Provider 用途 资源数量
AWS Amazon Web Services 1000+
Azure Microsoft Azure 800+
Google Google Cloud Platform 500+
Kubernetes K8s 集群管理 200+
Docker 容器管理 20+
GitHub 代码仓库管理 50+

1.3 Provider 配置

# AWS Provider 配置
provider "aws" {
  region     = var.aws_region
  access_key = var.aws_access_key
  secret_key = var.aws_secret_key
  
  # 默认标签
  default_tags {
    tags = {
      Environment = "Production"
      ManagedBy   = "Terraform"
    }
  }
}

# 多区域配置
provider "aws" {
  alias  = "us-east"
  region = "us-east-1"
}

provider "aws" {
  alias  = "us-west"
  region = "us-west-2"
}

二、Resources(资源)

2.1 资源定义

资源是 Terraform 管理的基础设施对象。

resource "aws_instance" "web_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "WebServer"
  }
}

resource "aws_s3_bucket" "data" {
  bucket = "my-app-data-${random_id.bucket_id.hex}"
  
  tags = {
    Name = "DataBucket"
  }
}

2.2 资源依赖

# 隐式依赖(通过引用)
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id  # 隐式依赖
  cidr_block = "10.0.1.0/24"
}

# 显式依赖
resource "aws_instance" "app" {
  ami           = "ami-xxx"
  instance_type = "t2.micro"
  
  depends_on = [
    aws_db_instance.database
  ]
}

2.3 资源生命周期

resource "aws_instance" "example" {
  ami           = "ami-xxx"
  instance_type = "t2.micro"
  
  lifecycle {
    create_before_destroy = true  # 先创建新资源
    prevent_destroy      = false  # 允许删除
    ignore_changes       = [       # 忽略这些字段的变化
      tags,
      user_data,
    ]
  }
}

三、Variables(变量)

3.1 输入变量

# variables.tf
variable "instance_type" {
  description = "EC2 实例类型"
  type        = string
  default     = "t2.micro"
}

variable "availability_zones" {
  description = "可用区列表"
  type        = list(string)
  default     = ["us-west-2a", "us-west-2b"]
}

variable "environment" {
  description = "环境名称"
  type        = string
  
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "环境必须是 dev、staging 或 prod。"
  }
}

3.2 使用变量

resource "aws_instance" "app" {
  ami           = "ami-xxx"
  instance_type = var.instance_type
  
  tags = {
    Environment = var.environment
  }
}

3.3 变量传递方式

# 1. 命令行
terraform apply -var="instance_type=t2.small"

# 2. 变量文件
terraform apply -var-file="prod.tfvars"

# 3. 环境变量
export TF_VAR_instance_type=t2.small
terraform apply

# 4. 自动加载的 .tfvars 文件
# terraform.tfvars 或 *.auto.tfvars

prod.tfvars 示例:

instance_type      = "t2.large"
availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]
environment        = "prod"

四、Outputs(输出)

4.1 定义输出

# outputs.tf
output "instance_public_ip" {
  description = "EC2 实例的公网 IP"
  value       = aws_instance.app.public_ip
}

output "database_endpoint" {
  description = "数据库连接端点"
  value       = aws_db_instance.main.endpoint
  sensitive   = true  # 标记为敏感信息
}

output "vpc_details" {
  description = "VPC 详细信息"
  value = {
    id         = aws_vpc.main.id
    cidr_block = aws_vpc.main.cidr_block
    region     = var.aws_region
  }
}

4.2 查看输出

# 查看所有输出
terraform output

# 查看特定输出
terraform output instance_public_ip

# JSON 格式输出
terraform output -json

4.3 输出用途

# 模块间传递数据
module "vpc" {
  source = "./modules/vpc"
}

module "app" {
  source = "./modules/app"
  vpc_id = module.vpc.vpc_id  # 使用其他模块的输出
}

五、Data Sources(数据源)

5.1 读取现有资源

# 查询最新的 Ubuntu AMI
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]  # Canonical
  
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
}

# 使用数据源
resource "aws_instance" "app" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"
}

5.2 常用数据源

# 获取当前账户信息
data "aws_caller_identity" "current" {}

output "account_id" {
  value = data.aws_caller_identity.current.account_id
}

# 获取可用区
data "aws_availability_zones" "available" {
  state = "available"
}

# 获取现有 VPC
data "aws_vpc" "existing" {
  filter {
    name   = "tag:Name"
    values = ["Production-VPC"]
  }
}

六、State(状态)

6.1 状态文件

Terraform 使用状态文件追踪资源的实际状态。

# 状态文件位置
./terraform.tfstate        # 本地状态
./terraform.tfstate.backup # 备份

6.2 远程状态

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-west-2"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

6.3 状态管理命令

# 查看状态
terraform state list
terraform state show aws_instance.app

# 移动资源
terraform state mv aws_instance.old aws_instance.new

# 删除资源(仅从状态中删除)
terraform state rm aws_instance.temp

# 导入现有资源
terraform import aws_instance.app i-1234567890abcdef0

七、Modules(模块)

7.1 模块结构

modules/
├── vpc/
│   ├── main.tf
│   ├── variables.tf
│   └── outputs.tf
└── app/
    ├── main.tf
    ├── variables.tf
    └── outputs.tf

7.2 使用模块

module "vpc" {
  source = "./modules/vpc"
  
  cidr_block = "10.0.0.0/16"
  environment = "production"
}

module "app" {
  source = "./modules/app"
  
  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnet_ids
}

7.3 公共模块

# 使用 Terraform Registry 的模块
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"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24"]
}

八、核心概念关系图

┌─────────────────────────────────────────────┐
│            Terraform 配置文件                │
├─────────────────────────────────────────────┤
│  Providers ←──→ Resources                   │
│     ↓              ↓                        │
│  Variables     Data Sources                 │
│     ↓              ↓                        │
│  Modules  ←────→ State                      │
│     ↓                                       │
│  Outputs                                    │
└─────────────────────────────────────────────┘

九、最佳实践

9.1 文件组织

project/
├── main.tf           # 主要资源定义
├── variables.tf      # 输入变量
├── outputs.tf        # 输出值
├── versions.tf       # Provider 版本约束
├── terraform.tfvars  # 变量值(不提交到 Git)
└── modules/          # 自定义模块

9.2 命名规范

# 使用下划线分隔,描述性命名
resource "aws_instance" "web_server" {}
variable "vpc_cidr_block" {}
output "instance_public_ip" {}

# 避免
resource "aws_instance" "ws" {}  # ❌ 太简短
variable "x" {}                  # ❌ 无意义

9.3 代码复用

# 使用 locals 减少重复
locals {
  common_tags = {
    Environment = var.environment
    ManagedBy   = "Terraform"
    Project     = "MyApp"
  }
}

resource "aws_instance" "app" {
  # ...
  tags = merge(
    local.common_tags,
    {
      Name = "AppServer"
    }
  )
}

小结

理解这些核心概念是使用 Terraform 的基础:

  • Providers: 连接云平台的桥梁
  • Resources: 需要管理的基础设施
  • Variables: 使配置灵活可复用
  • Outputs: 导出重要信息
  • Data Sources: 读取现有资源
  • State: 追踪资源实际状态
  • Modules: 组织和复用代码

下一章我们将学习 Terraform 的工作流程和常用命令。