terraform-infrastructure-as-code
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTerraform Infrastructure as Code - Comprehensive Guide
Terraform基础设施即代码 - 全面指南
Table of Contents
目录
Introduction to Terraform
Terraform简介
Terraform is an open-source Infrastructure as Code (IaC) tool created by HashiCorp that enables you to define and provision infrastructure using a declarative configuration language called HashiCorp Configuration Language (HCL). Terraform manages external resources such as public cloud infrastructure, private cloud infrastructure, network appliances, and software as a service.
Terraform是HashiCorp开发的开源基础设施即代码(IaC)工具,允许你使用名为HashiCorp配置语言(HCL)的声明式配置语言来定义和置备基础设施。Terraform可以管理外部资源,如公有云基础设施、私有云基础设施、网络设备以及软件即服务。
Key Benefits
核心优势
- Declarative Configuration: Define what your infrastructure should look like, not how to create it
- Cloud-Agnostic: Works with multiple cloud providers and services
- Version Control: Infrastructure code can be versioned and reviewed
- Plan Before Apply: Preview changes before applying them
- Resource Graph: Automatically manages dependencies between resources
- State Management: Tracks the current state of your infrastructure
- 声明式配置:定义基础设施的目标状态,而非创建步骤
- 跨云兼容:支持多个云提供商和服务
- 版本控制:基础设施代码可进行版本控制和评审
- 先规划后应用:在应用变更前预览效果
- 资源图:自动管理资源之间的依赖关系
- 状态管理:跟踪基础设施的当前状态
Terraform Workflow
Terraform工作流
bash
undefinedbash
undefinedInitialize Terraform working directory
初始化Terraform工作目录
terraform init
terraform init
Initialize and upgrade provider versions
初始化并升级提供商版本
terraform init -upgrade
terraform init -upgrade
Initialize with backend configuration
使用后端配置初始化
terraform init -backend-config="bucket=my-state-bucket"
terraform init -backend-config="bucket=my-state-bucket"
Generate a plan
生成执行计划
terraform plan
terraform plan
Save plan to file for later apply
将计划保存到文件以便后续应用
terraform plan -out=tfplan
terraform plan -out=tfplan
Plan with specific variable values
使用特定变量值生成计划
terraform plan -var="region=us-west-2" -var="instance_type=t2.micro"
terraform plan -var="region=us-west-2" -var="instance_type=t2.micro"
Apply with interactive approval
交互式确认后应用变更
terraform apply
terraform apply
Auto-approve without confirmation
自动批准无需确认
terraform apply -auto-approve
terraform apply -auto-approve
Apply a saved plan file
应用保存的计划文件
terraform apply tfplan
terraform apply tfplan
Destroy with confirmation prompt
带确认提示销毁资源
terraform destroy
terraform destroy
Auto-approve destruction
自动批准销毁
terraform destroy -auto-approve
undefinedterraform destroy -auto-approve
undefinedCore Concepts
核心概念
1. Resources
1. 资源
Resources are the most fundamental elements in Terraform. They represent infrastructure objects like virtual machines, networks, databases, or DNS records.
hcl
undefined资源是Terraform中最基础的元素,代表虚拟机、网络、数据库或DNS记录等基础设施对象。
hcl
undefinedBasic resource declaration
基础资源声明
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "WebServer"
Environment = "production"
}
}
undefinedresource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "WebServer"
Environment = "production"
}
}
undefined2. Providers
2. 提供商
Providers are plugins that allow Terraform to interact with cloud platforms, SaaS providers, and other APIs.
hcl
undefined提供商是允许Terraform与云平台、SaaS提供商及其他API交互的插件。
hcl
undefinedAWS provider configuration
AWS提供商配置
provider "aws" {
region = "us-west-2"
default_tags {
tags = {
ManagedBy = "Terraform"
Project = "MyApp"
}
}
}
undefinedprovider "aws" {
region = "us-west-2"
default_tags {
tags = {
ManagedBy = "Terraform"
Project = "MyApp"
}
}
}
undefined3. State
3. 状态
Terraform stores information about your infrastructure in a state file. This state is used to map real-world resources to your configuration and track metadata.
Terraform将基础设施的信息存储在状态文件中,该状态用于将现实世界的资源映射到你的配置并跟踪元数据。
4. Configuration Language (HCL)
4. 配置语言(HCL)
HCL is designed to be both human-readable and machine-friendly, making it ideal for infrastructure configuration.
HCL设计为兼具人类可读性和机器友好性,非常适合基础设施配置。
Resources
资源
Resources are the building blocks of Terraform configurations. Each resource block describes one or more infrastructure objects.
资源是Terraform配置的构建块,每个资源块描述一个或多个基础设施对象。
Basic Resource Syntax
基础资源语法
hcl
resource "resource_type" "resource_name" {
argument1 = "value1"
argument2 = "value2"
nested_block {
nested_argument = "nested_value"
}
}hcl
resource "resource_type" "resource_name" {
argument1 = "value1"
argument2 = "value2"
nested_block {
nested_argument = "nested_value"
}
}Resource Examples
资源示例
AWS EC2 Instance
AWS EC2实例
hcl
resource "aws_instance" "app_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
key_name = "my-keypair"
vpc_security_group_ids = [aws_security_group.app.id]
subnet_id = aws_subnet.public.id
user_data = <<-EOF
#!/bin/bash
echo "Hello, World!" > index.html
nohup busybox httpd -f -p 8080 &
EOF
tags = {
Name = "AppServer"
Environment = "production"
ManagedBy = "Terraform"
}
}hcl
resource "aws_instance" "app_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
key_name = "my-keypair"
vpc_security_group_ids = [aws_security_group.app.id]
subnet_id = aws_subnet.public.id
user_data = <<-EOF
#!/bin/bash
echo "Hello, World!" > index.html
nohup busybox httpd -f -p 8080 &
EOF
tags = {
Name = "AppServer"
Environment = "production"
ManagedBy = "Terraform"
}
}AWS VPC
AWS VPC
hcl
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "main-vpc"
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-2a"
map_public_ip_on_launch = true
tags = {
Name = "public-subnet"
}
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-west-2a"
tags = {
Name = "private-subnet"
}
}hcl
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "main-vpc"
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-2a"
map_public_ip_on_launch = true
tags = {
Name = "public-subnet"
}
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-west-2a"
tags = {
Name = "private-subnet"
}
}AWS S3 Bucket
AWS S3存储桶
hcl
resource "aws_s3_bucket" "data" {
bucket = "my-app-data-bucket-12345"
tags = {
Name = "Data Bucket"
Environment = "production"
}
}
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}hcl
resource "aws_s3_bucket" "data" {
bucket = "my-app-data-bucket-12345"
tags = {
Name = "Data Bucket"
Environment = "production"
}
}
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}AWS Security Group
AWS安全组
hcl
resource "aws_security_group" "web" {
name = "web-sg"
description = "Security group for web servers"
vpc_id = aws_vpc.main.id
ingress {
description = "HTTP from anywhere"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTPS from anywhere"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "web-security-group"
}
}hcl
resource "aws_security_group" "web" {
name = "web-sg"
description = "Security group for web servers"
vpc_id = aws_vpc.main.id
ingress {
description = "HTTP from anywhere"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTPS from anywhere"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "web-security-group"
}
}Resource Lifecycle
资源生命周期
hcl
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
lifecycle {
create_before_destroy = true
prevent_destroy = true
ignore_changes = [tags]
}
}Lifecycle options:
- : Create new resource before destroying the old one
create_before_destroy - : Prevent accidental destruction of resources
prevent_destroy - : Ignore changes to specified attributes
ignore_changes - : Force replacement when specific resources change
replace_triggered_by
hcl
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
lifecycle {
replace_triggered_by = [
aws_iam_policy.example.id
]
}
}hcl
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
lifecycle {
create_before_destroy = true
prevent_destroy = true
ignore_changes = [tags]
}
}生命周期选项:
- : 创建新资源后再销毁旧资源
create_before_destroy - : 防止意外销毁资源
prevent_destroy - : 忽略指定属性的变更
ignore_changes - : 当特定资源变更时强制替换当前资源
replace_triggered_by
hcl
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
lifecycle {
replace_triggered_by = [
aws_iam_policy.example.id
]
}
}Data Sources
数据源
Data sources allow Terraform to use information defined outside of Terraform, or defined by another separate Terraform configuration.
数据源允许Terraform使用Terraform外部定义的信息,或由其他独立Terraform配置定义的信息。
Data Source Syntax
数据源语法
hcl
data "resource_type" "name" {
# Query parameters
}hcl
data "resource_type" "name" {
# 查询参数
}Data Source Examples
数据源示例
hcl
undefinedhcl
undefinedQuery existing AWS resources
查询现有AWS资源
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
}
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
}
Use data source in resource
在资源中使用数据源
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
}
Query availability zones
查询可用区
data "aws_availability_zones" "available" {
state = "available"
}
data "aws_availability_zones" "available" {
state = "available"
}
Query VPC
查询VPC
data "aws_vpc" "default" {
default = true
}
data "aws_vpc" "default" {
default = true
}
Query remote state
查询远程状态
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "terraform-state"
key = "network/terraform.tfstate"
region = "us-west-2"
}
}
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "terraform-state"
key = "network/terraform.tfstate"
region = "us-west-2"
}
}
Use remote state outputs
使用远程状态输出
resource "aws_instance" "app" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
subnet_id = data.terraform_remote_state.network.outputs.subnet_id
availability_zone = data.aws_availability_zones.available.names[0]
}
undefinedresource "aws_instance" "app" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
subnet_id = data.terraform_remote_state.network.outputs.subnet_id
availability_zone = data.aws_availability_zones.available.names[0]
}
undefinedCommon Data Sources
常见数据源
hcl
undefinedhcl
undefinedAWS Account ID
AWS账户ID
data "aws_caller_identity" "current" {}
output "account_id" {
value = data.aws_caller_identity.current.account_id
}
data "aws_caller_identity" "current" {}
output "account_id" {
value = data.aws_caller_identity.current.account_id
}
AWS Region
AWS区域
data "aws_region" "current" {}
output "region" {
value = data.aws_region.current.name
}
data "aws_region" "current" {}
output "region" {
value = data.aws_region.current.name
}
Route53 Zone
Route53区域
data "aws_route53_zone" "primary" {
name = "example.com"
}
data "aws_route53_zone" "primary" {
name = "example.com"
}
IAM Policy Document
IAM策略文档
data "aws_iam_policy_document" "assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}}
}
undefineddata "aws_iam_policy_document" "assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}}
}
undefinedVariables and Outputs
变量与输出
Input Variables
输入变量
Variables allow you to parameterize your configurations for reusability.
hcl
undefined变量允许你将配置参数化以实现复用。
hcl
undefinedSimple variable
简单变量
variable "region" {
type = string
default = "us-west-2"
description = "AWS region for resources"
}
variable "region" {
type = string
default = "us-west-2"
description = "AWS资源所在区域"
}
Variable with validation
带验证的变量
variable "instance_type" {
type = string
default = "t2.micro"
validation {
condition = contains(["t2.micro", "t2.small", "t2.medium"], var.instance_type)
error_message = "Instance type must be t2.micro, t2.small, or t2.medium."
}
}
variable "instance_type" {
type = string
default = "t2.micro"
validation {
condition = contains(["t2.micro", "t2.small", "t2.medium"], var.instance_type)
error_message = "实例类型必须是t2.micro、t2.small或t2.medium。"
}
}
Complex type variable
复杂类型变量
variable "vpc_config" {
type = object({
cidr_block = string
azs = list(string)
private_subnets = list(string)
public_subnets = list(string)
})
default = {
cidr_block = "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"]
}
}
undefinedvariable "vpc_config" {
type = object({
cidr_block = string
azs = list(string)
private_subnets = list(string)
public_subnets = list(string)
})
default = {
cidr_block = "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"]
}
}
undefinedVariable Types
变量类型
hcl
undefinedhcl
undefinedString variable
字符串变量
variable "environment" {
type = string
default = "development"
}
variable "environment" {
type = string
default = "development"
}
Number variable
数字变量
variable "instance_count" {
type = number
default = 3
}
variable "instance_count" {
type = number
default = 3
}
Boolean variable
布尔变量
variable "enable_monitoring" {
type = bool
default = true
}
variable "enable_monitoring" {
type = bool
default = true
}
List variable
列表变量
variable "availability_zones" {
type = list(string)
default = ["us-west-2a", "us-west-2b", "us-west-2c"]
}
variable "availability_zones" {
type = list(string)
default = ["us-west-2a", "us-west-2b", "us-west-2c"]
}
Map variable
映射变量
variable "ami_ids" {
type = map(string)
default = {
us-west-2 = "ami-0c55b159cbfafe1f0"
us-east-1 = "ami-0b69ea66ff7391e80"
}
}
variable "ami_ids" {
type = map(string)
default = {
us-west-2 = "ami-0c55b159cbfafe1f0"
us-east-1 = "ami-0b69ea66ff7391e80"
}
}
Object variable
对象变量
variable "database_config" {
type = object({
engine = string
engine_version = string
instance_class = string
allocated_storage = number
})
default = {
engine = "postgres"
engine_version = "13.7"
instance_class = "db.t3.micro"
allocated_storage = 20
}
}
undefinedvariable "database_config" {
type = object({
engine = string
engine_version = string
instance_class = string
allocated_storage = number
})
default = {
engine = "postgres"
engine_version = "13.7"
instance_class = "db.t3.micro"
allocated_storage = 20
}
}
undefinedSetting Variables
设置变量
bash
undefinedbash
undefinedCommand line
命令行设置
terraform apply -var="region=us-east-1" -var="instance_count=5"
terraform apply -var="region=us-east-1" -var="instance_count=5"
Variable files
变量文件
terraform apply -var-file="production.tfvars"
terraform apply -var-file="production.tfvars"
Environment variables
环境变量
export TF_VAR_region=us-east-1
terraform apply
**terraform.tfvars:**
```hcl
region = "us-west-2"
instance_count = 3
environment = "production"export TF_VAR_region=us-east-1
terraform apply
**terraform.tfvars:**
```hcl
region = "us-west-2"
instance_count = 3
environment = "production"Output Values
输出值
Outputs make information about your infrastructure available for other configurations or display to users.
hcl
undefined输出值可将基础设施信息提供给其他配置或展示给用户。
hcl
undefinedSimple output
简单输出
output "instance_ip" {
value = aws_instance.web.public_ip
description = "The public IP of the web server"
}
output "instance_ip" {
value = aws_instance.web.public_ip
description = "Web服务器的公网IP"
}
Output with sensitive data
敏感数据输出
output "database_password" {
value = aws_db_instance.main.password
sensitive = true
}
output "database_password" {
value = aws_db_instance.main.password
sensitive = true
}
Complex output
复杂输出
output "instance_details" {
value = {
id = aws_instance.web.id
public_ip = aws_instance.web.public_ip
private_ip = aws_instance.web.private_ip
arn = aws_instance.web.arn
}
description = "Complete instance information"
}
output "instance_details" {
value = {
id = aws_instance.web.id
public_ip = aws_instance.web.public_ip
private_ip = aws_instance.web.private_ip
arn = aws_instance.web.arn
}
description = "完整的实例信息"
}
Output with depends_on
带依赖的输出
output "vpc_ready" {
value = "VPC and subnets are ready"
depends_on = [
aws_vpc.main,
aws_subnet.private,
aws_subnet.public
]
}
undefinedoutput "vpc_ready" {
value = "VPC和子网已就绪"
depends_on = [
aws_vpc.main,
aws_subnet.private,
aws_subnet.public
]
}
undefinedUsing Outputs
使用输出
bash
undefinedbash
undefinedShow all outputs
显示所有输出
terraform output
terraform output
Get specific output value
获取特定输出值
terraform output instance_ip
terraform output instance_ip
Output in JSON format
以JSON格式输出
terraform output -json
terraform output -json
Use output in scripts
在脚本中使用输出
INSTANCE_IP=$(terraform output -raw instance_ip)
echo "Server IP: $INSTANCE_IP"
undefinedINSTANCE_IP=$(terraform output -raw instance_ip)
echo "服务器IP: $INSTANCE_IP"
undefinedLocal Values
本地值
Local values assign a name to an expression for reuse within a module.
hcl
locals {
common_tags = {
ManagedBy = "Terraform"
Environment = var.environment
Project = "MyApp"
}
name_prefix = "${var.project_name}-${var.environment}"
availability_zones = slice(data.aws_availability_zones.available.names, 0, 3)
}
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
tags = merge(
local.common_tags,
{
Name = "${local.name_prefix}-web-server"
}
)
}本地值为表达式分配名称,以便在模块内复用。
hcl
locals {
common_tags = {
ManagedBy = "Terraform"
Environment = var.environment
Project = "MyApp"
}
name_prefix = "${var.project_name}-${var.environment}"
availability_zones = slice(data.aws_availability_zones.available.names, 0, 3)
}
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
tags = merge(
local.common_tags,
{
Name = "${local.name_prefix}-web-server"
}
)
}Modules
模块
Modules are containers for multiple resources that are used together. They enable you to create reusable components.
模块是用于组合多个资源的容器,可帮助你创建可复用的组件。
Module Structure
模块结构
modules/
└── vpc/
├── main.tf
├── variables.tf
├── outputs.tf
└── README.mdmodules/
└── vpc/
├── main.tf
├── variables.tf
├── outputs.tf
└── README.mdCreating a Module
创建模块
modules/vpc/main.tf:
hcl
resource "aws_vpc" "main" {
cidr_block = var.cidr_block
enable_dns_hostnames = var.enable_dns_hostnames
enable_dns_support = var.enable_dns_support
tags = merge(
var.tags,
{
Name = var.name
}
)
}
resource "aws_subnet" "public" {
count = length(var.public_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.public_subnet_cidrs[count.index]
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = merge(
var.tags,
{
Name = "${var.name}-public-${count.index + 1}"
Type = "public"
}
)
}
resource "aws_subnet" "private" {
count = length(var.private_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnet_cidrs[count.index]
availability_zone = var.availability_zones[count.index]
tags = merge(
var.tags,
{
Name = "${var.name}-private-${count.index + 1}"
Type = "private"
}
)
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = merge(
var.tags,
{
Name = "${var.name}-igw"
}
)
}modules/vpc/variables.tf:
hcl
variable "name" {
description = "Name prefix for VPC resources"
type = string
}
variable "cidr_block" {
description = "CIDR block for VPC"
type = string
}
variable "public_subnet_cidrs" {
description = "CIDR blocks for public subnets"
type = list(string)
}
variable "private_subnet_cidrs" {
description = "CIDR blocks for private subnets"
type = list(string)
}
variable "availability_zones" {
description = "Availability zones for subnets"
type = list(string)
}
variable "enable_dns_hostnames" {
description = "Enable DNS hostnames in VPC"
type = bool
default = true
}
variable "enable_dns_support" {
description = "Enable DNS support in VPC"
type = bool
default = true
}
variable "tags" {
description = "Tags to apply to resources"
type = map(string)
default = {}
}modules/vpc/outputs.tf:
hcl
output "vpc_id" {
description = "ID of the VPC"
value = aws_vpc.main.id
}
output "vpc_cidr" {
description = "CIDR block of the VPC"
value = aws_vpc.main.cidr_block
}
output "public_subnet_ids" {
description = "IDs of public subnets"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "IDs of private subnets"
value = aws_subnet.private[*].id
}
output "internet_gateway_id" {
description = "ID of the internet gateway"
value = aws_internet_gateway.main.id
}modules/vpc/main.tf:
hcl
resource "aws_vpc" "main" {
cidr_block = var.cidr_block
enable_dns_hostnames = var.enable_dns_hostnames
enable_dns_support = var.enable_dns_support
tags = merge(
var.tags,
{
Name = var.name
}
)
}
resource "aws_subnet" "public" {
count = length(var.public_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.public_subnet_cidrs[count.index]
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = merge(
var.tags,
{
Name = "${var.name}-public-${count.index + 1}"
Type = "public"
}
)
}
resource "aws_subnet" "private" {
count = length(var.private_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnet_cidrs[count.index]
availability_zone = var.availability_zones[count.index]
tags = merge(
var.tags,
{
Name = "${var.name}-private-${count.index + 1}"
Type = "private"
}
)
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = merge(
var.tags,
{
Name = "${var.name}-igw"
}
)
}modules/vpc/variables.tf:
hcl
variable "name" {
description = "VPC资源的名称前缀"
type = string
}
variable "cidr_block" {
description = "VPC的CIDR块"
type = string
}
variable "public_subnet_cidrs" {
description = "公有子网的CIDR块"
type = list(string)
}
variable "private_subnet_cidrs" {
description = "私有子网的CIDR块"
type = list(string)
}
variable "availability_zones" {
description = "子网所在的可用区"
type = list(string)
}
variable "enable_dns_hostnames" {
description = "在VPC中启用DNS主机名"
type = bool
default = true
}
variable "enable_dns_support" {
description = "在VPC中启用DNS支持"
type = bool
default = true
}
variable "tags" {
description = "应用于资源的标签"
type = map(string)
default = {}
}modules/vpc/outputs.tf:
hcl
output "vpc_id" {
description = "VPC的ID"
value = aws_vpc.main.id
}
output "vpc_cidr" {
description = "VPC的CIDR块"
value = aws_vpc.main.cidr_block
}
output "public_subnet_ids" {
description = "公有子网的ID"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "私有子网的ID"
value = aws_subnet.private[*].id
}
output "internet_gateway_id" {
description = "互联网网关的ID"
value = aws_internet_gateway.main.id
}Using Modules
使用模块
hcl
undefinedhcl
undefinedUsing a module from local path
使用本地路径的模块
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
region = var.region
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
region = var.region
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
Using a module from Terraform Registry
使用Terraform Registry中的模块
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "3.15.0"
bucket = "my-application-bucket"
acl = "private"
versioning = {
enabled = true
}
}
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "3.15.0"
bucket = "my-application-bucket"
acl = "private"
versioning = {
enabled = true
}
}
Using module outputs
使用模块输出
resource "aws_instance" "app" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = module.vpc.private_subnet_ids[0]
tags = {
Name = "App Server"
}
}
resource "aws_instance" "app" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = module.vpc.private_subnet_ids[0]
tags = {
Name = "App Server"
}
}
Module with count
带count的模块
module "web_servers" {
count = 3
source = "./modules/web-server"
name = "web-${count.index}"
subnet = module.vpc.public_subnet_ids[count.index]
}
module "web_servers" {
count = 3
source = "./modules/web-server"
name = "web-${count.index}"
subnet = module.vpc.public_subnet_ids[count.index]
}
Module with for_each
带for_each的模块
module "environments" {
for_each = toset(["dev", "staging", "prod"])
source = "./modules/environment"
env_name = each.key
vpc_cidr = "10.${index(["dev", "staging", "prod"], each.key)}.0.0/16"
}
undefinedmodule "environments" {
for_each = toset(["dev", "staging", "prod"])
source = "./modules/environment"
env_name = each.key
vpc_cidr = "10.${index(["dev", "staging", "prod"], each.key)}.0.0/16"
}
undefinedModule Sources
模块源
hcl
undefinedhcl
undefinedLocal path
本地路径
module "vpc" {
source = "./modules/vpc"
}
module "vpc" {
source = "./modules/vpc"
}
Terraform Registry
Terraform Registry
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.1.0"
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.1.0"
}
GitHub
GitHub
module "vpc" {
source = "github.com/terraform-aws-modules/terraform-aws-vpc"
}
module "vpc" {
source = "github.com/terraform-aws-modules/terraform-aws-vpc"
}
GitHub with specific branch
指定分支的GitHub
module "vpc" {
source = "github.com/terraform-aws-modules/terraform-aws-vpc?ref=v5.1.0"
}
module "vpc" {
source = "github.com/terraform-aws-modules/terraform-aws-vpc?ref=v5.1.0"
}
Git
Git
module "vpc" {
source = "git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git"
}
module "vpc" {
source = "git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git"
}
S3 bucket
S3存储桶
module "vpc" {
source = "s3::https://s3.amazonaws.com/my-bucket/vpc-module.zip"
}
undefinedmodule "vpc" {
source = "s3::https://s3.amazonaws.com/my-bucket/vpc-module.zip"
}
undefinedModule Versioning
模块版本控制
hcl
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0" # Any version 5.x
}
module "s3" {
source = "terraform-aws-modules/s3-bucket/aws"
version = ">= 3.0, < 4.0" # Between 3.0 and 4.0
}hcl
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0" # 任何5.x版本
}
module "s3" {
source = "terraform-aws-modules/s3-bucket/aws"
version = ">= 3.0, < 4.0" # 3.0到4.0之间的版本
}State Management
状态管理
Terraform state is a critical component that maps your configuration to real-world resources.
Terraform状态是将配置映射到现实世界资源的关键组件。
Local State
本地状态
By default, Terraform stores state locally in a file named .
terraform.tfstatehcl
terraform {
backend "local" {
path = "terraform.tfstate"
}
}默认情况下,Terraform将状态本地存储在名为的文件中。
terraform.tfstatehcl
terraform {
backend "local" {
path = "terraform.tfstate"
}
}Remote State
远程状态
Remote state enables team collaboration and provides better security and reliability.
远程状态支持团队协作,并提供更好的安全性和可靠性。
S3 Backend
S3后端
hcl
undefinedhcl
undefinedS3 backend configuration
S3后端配置
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "production/terraform.tfstate"
region = "us-west-2"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
**Setup DynamoDB for state locking:**
```hcl
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
tags = {
Name = "Terraform State Lock Table"
}
}terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "production/terraform.tfstate"
region = "us-west-2"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
**设置DynamoDB用于状态锁定:**
```hcl
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
tags = {
Name = "Terraform状态锁定表"
}
}Azure Backend
Azure后端
hcl
terraform {
backend "azurerm" {
resource_group_name = "terraform-rg"
storage_account_name = "tfstate"
container_name = "tfstate"
key = "prod.terraform.tfstate"
}
}hcl
terraform {
backend "azurerm" {
resource_group_name = "terraform-rg"
storage_account_name = "tfstate"
container_name = "tfstate"
key = "prod.terraform.tfstate"
}
}Terraform Cloud Backend
Terraform Cloud后端
hcl
terraform {
cloud {
organization = "my-organization"
workspaces {
name = "production"
}
}
}hcl
terraform {
cloud {
organization = "my-organization"
workspaces {
name = "production"
}
}
}Consul Backend
Consul后端
hcl
terraform {
backend "consul" {
address = "consul.example.com:8500"
scheme = "https"
path = "terraform/production"
}
}hcl
terraform {
backend "consul" {
address = "consul.example.com:8500"
scheme = "https"
path = "terraform/production"
}
}State Commands
状态命令
bash
undefinedbash
undefinedList all resources in state
列出状态中的所有资源
terraform state list
terraform state list
Show specific resource details
显示特定资源的详细信息
terraform state show aws_instance.example
terraform state show aws_instance.example
Remove resource from state (doesn't destroy)
从状态中移除资源(不销毁)
terraform state rm aws_instance.example
terraform state rm aws_instance.example
Move resource to new address
将资源移动到新地址
terraform state mv aws_instance.example aws_instance.web_server
terraform state mv aws_instance.example aws_instance.web_server
Show current state
显示当前状态
terraform show
terraform show
Show specific plan file
显示特定计划文件
terraform show tfplan
terraform show tfplan
Output state in JSON format
以JSON格式输出状态
terraform show -json > state.json
terraform show -json > state.json
Pull remote state
拉取远程状态
terraform state pull > terraform.tfstate
terraform state pull > terraform.tfstate
Push local state to remote
将本地状态推送到远程
terraform state push terraform.tfstate
undefinedterraform state push terraform.tfstate
undefinedState Locking
状态锁定
State locking prevents concurrent operations that could corrupt your state.
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "terraform.tfstate"
region = "us-west-2"
dynamodb_table = "terraform-state-lock"
encrypt = true
}
}状态锁定可防止并发操作导致状态损坏。
hcl
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "terraform.tfstate"
region = "us-west-2"
dynamodb_table = "terraform-state-lock"
encrypt = true
}
}Importing Existing Resources
导入现有资源
bash
undefinedbash
undefinedImport AWS instance
导入AWS实例
terraform import aws_instance.example i-0abc123def456
terraform import aws_instance.example i-0abc123def456
Import with module
导入模块中的资源
terraform import module.network.aws_vpc.main vpc-0123456789abcdef
**Configuration needed before import:**
```hcl
resource "aws_instance" "example" {
# Configuration will be populated after import
# Define the basic structure matching the resource
}terraform import module.network.aws_vpc.main vpc-0123456789abcdef
**导入前需要的配置:**
```hcl
resource "aws_instance" "example" {
# 导入后会填充配置
# 定义与资源匹配的基本结构
}State Migration
状态迁移
bash
undefinedbash
undefinedInitialize with backend
使用后端初始化
terraform init
terraform init
Migrate from local to remote
从本地迁移到远程
terraform init -migrate-state
terraform init -migrate-state
Backend configuration from CLI
从命令行指定后端配置
terraform init -backend-config="bucket=my-other-bucket"
-backend-config="key=my-state"
-backend-config="key=my-state"
undefinedterraform init -backend-config="bucket=my-other-bucket"
-backend-config="key=my-state"
-backend-config="key=my-state"
undefinedWorkspaces
工作区
Workspaces allow you to manage multiple instances of a single configuration.
工作区允许你管理单个配置的多个实例。
Workspace Commands
工作区命令
bash
undefinedbash
undefinedList workspaces
列出工作区
terraform workspace list
terraform workspace list
Create new workspace
创建新工作区
terraform workspace new production
terraform workspace new production
Switch to workspace
切换工作区
terraform workspace select staging
terraform workspace select staging
Show current workspace
显示当前工作区
terraform workspace show
terraform workspace show
Delete workspace
删除工作区
terraform workspace delete development
undefinedterraform workspace delete development
undefinedWorkspace Workflow
工作区工作流
bash
undefinedbash
undefinedExample workflow:
示例工作流:
terraform workspace new development
terraform apply # Creates resources in development workspace
terraform workspace new staging
terraform apply # Creates separate resources in staging workspace
terraform workspace new production
terraform apply # Creates separate resources in production workspace
undefinedterraform workspace new development
terraform apply # 在development工作区创建资源
terraform workspace new staging
terraform apply # 在staging工作区创建独立资源
terraform workspace new production
terraform apply # 在production工作区创建独立资源
undefinedUsing Workspace in Configuration
在配置中使用工作区
hcl
locals {
environment = terraform.workspace
}
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = terraform.workspace == "production" ? "t3.large" : "t3.micro"
tags = {
Name = "web-${terraform.workspace}"
Environment = terraform.workspace
}
}hcl
locals {
environment = terraform.workspace
}
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = terraform.workspace == "production" ? "t3.large" : "t3.micro"
tags = {
Name = "web-${terraform.workspace}"
Environment = terraform.workspace
}
}Workspace-specific variables
工作区特定变量
variable "instance_counts" {
type = map(number)
default = {
development = 1
staging = 2
production = 5
}
}
resource "aws_instance" "app" {
count = var.instance_counts[terraform.workspace]
ami = var.ami_id
instance_type = "t3.micro"
tags = {
Name = "app-${terraform.workspace}-${count.index + 1}"
}
}
undefinedvariable "instance_counts" {
type = map(number)
default = {
development = 1
staging = 2
production = 5
}
}
resource "aws_instance" "app" {
count = var.instance_counts[terraform.workspace]
ami = var.ami_id
instance_type = "t3.micro"
tags = {
Name = "app-${terraform.workspace}-${count.index + 1}"
}
}
undefinedWorkspace State Isolation
工作区状态隔离
Each workspace has its own state file:
terraform.tfstate.d/development/terraform.tfstateterraform.tfstate.d/staging/terraform.tfstateterraform.tfstate.d/production/terraform.tfstate
每个工作区都有自己的状态文件:
terraform.tfstate.d/development/terraform.tfstateterraform.tfstate.d/staging/terraform.tfstateterraform.tfstate.d/production/terraform.tfstate
Provider Configuration
提供商配置
Providers are plugins that enable Terraform to interact with cloud platforms and other services.
提供商是使Terraform能够与云平台和其他服务交互的插件。
Single Provider
单个提供商
hcl
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
default_tags {
tags = {
ManagedBy = "Terraform"
Project = "MyApp"
}
}
}hcl
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
default_tags {
tags = {
ManagedBy = "Terraform"
Project = "MyApp"
}
}
}Multiple Provider Instances (Aliases)
多个提供商实例(别名)
hcl
provider "aws" {
alias = "east"
region = "us-east-1"
}
provider "aws" {
alias = "west"
region = "us-west-2"
}
resource "aws_instance" "east_server" {
provider = aws.east
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
resource "aws_instance" "west_server" {
provider = aws.west
ami = "ami-0123456789abcdef"
instance_type = "t2.micro"
}hcl
provider "aws" {
alias = "east"
region = "us-east-1"
}
provider "aws" {
alias = "west"
region = "us-west-2"
}
resource "aws_instance" "east_server" {
provider = aws.east
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
resource "aws_instance" "west_server" {
provider = aws.west
ami = "ami-0123456789abcdef"
instance_type = "t2.micro"
}Multi-Cloud Setup
多云设置
hcl
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 4.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
provider "google" {
project = var.gcp_project_id
region = "us-central1"
}hcl
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 4.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
provider "google" {
project = var.gcp_project_id
region = "us-central1"
}AWS resources
AWS资源
resource "aws_s3_bucket" "data" {
bucket = "my-data-bucket"
}
resource "aws_s3_bucket" "data" {
bucket = "my-data-bucket"
}
Azure resources
Azure资源
resource "azurerm_storage_account" "data" {
name = "mydatastorageacct"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
account_tier = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_storage_account" "data" {
name = "mydatastorageacct"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
account_tier = "Standard"
account_replication_type = "LRS"
}
GCP resources
GCP资源
resource "google_storage_bucket" "data" {
name = "my-data-bucket-gcp"
location = "US"
}
undefinedresource "google_storage_bucket" "data" {
name = "my-data-bucket-gcp"
location = "US"
}
undefinedProvider Configuration in Modules
模块中的提供商配置
hcl
undefinedhcl
undefinedRoot module
根模块
provider "aws" {
region = "us-west-2"
}
provider "aws" {
alias = "dr"
region = "us-east-1"
}
module "app" {
source = "./modules/app"
providers = {
aws = aws
aws.dr = aws.dr
}
}
**Module configuration:**
```hclprovider "aws" {
region = "us-west-2"
}
provider "aws" {
alias = "dr"
region = "us-east-1"
}
module "app" {
source = "./modules/app"
providers = {
aws = aws
aws.dr = aws.dr
}
}
**模块配置:**
```hclmodules/app/main.tf
modules/app/main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
configuration_aliases = [aws.dr]
}
}
}
resource "aws_instance" "primary" {
provider = aws
...
}
resource "aws_instance" "dr" {
provider = aws.dr
...
}
undefinedterraform {
required_providers {
aws = {
source = "hashicorp/aws"
configuration_aliases = [aws.dr]
}
}
}
resource "aws_instance" "primary" {
provider = aws
...
}
resource "aws_instance" "dr" {
provider = aws.dr
...
}
undefinedAdvanced Features
高级功能
Dynamic Blocks
动态块
Dynamic blocks allow you to dynamically construct repeatable nested blocks.
hcl
variable "ingress_rules" {
type = list(object({
description = string
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
default = [
{
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
},
{
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
]
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Security group for web servers"
vpc_id = aws_vpc.main.id
dynamic "ingress" {
for_each = var.ingress_rules
content {
description = ingress.value.description
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}动态块允许你动态构建可重复的嵌套块。
hcl
variable "ingress_rules" {
type = list(object({
description = string
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
default = [
{
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
},
{
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
]
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Web服务器安全组"
vpc_id = aws_vpc.main.id
dynamic "ingress" {
for_each = var.ingress_rules
content {
description = ingress.value.description
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}For_Each Meta-Argument
For_Each元参数
hcl
resource "aws_s3_bucket" "buckets" {
for_each = toset(["logs", "data", "backups"])
bucket = "my-app-${each.key}"
tags = {
Purpose = each.key
}
}hcl
resource "aws_s3_bucket" "buckets" {
for_each = toset(["logs", "data", "backups"])
bucket = "my-app-${each.key}"
tags = {
Purpose = each.key
}
}With map
配合映射使用
variable "instances" {
type = map(object({
ami = string
instance_type = string
}))
default = {
web = {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
}
app = {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.small"
}
}
}
resource "aws_instance" "servers" {
for_each = var.instances
ami = each.value.ami
instance_type = each.value.instance_type
tags = {
Name = each.key
}
}
undefinedvariable "instances" {
type = map(object({
ami = string
instance_type = string
}))
default = {
web = {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
}
app = {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.small"
}
}
}
resource "aws_instance" "servers" {
for_each = var.instances
ami = each.value.ami
instance_type = each.value.instance_type
tags = {
Name = each.key
}
}
undefinedCount Meta-Argument
Count元参数
hcl
resource "aws_instance" "servers" {
count = 3
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "server-${count.index}"
}
}hcl
resource "aws_instance" "servers" {
count = 3
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "server-${count.index}"
}
}Conditional resource creation
条件式资源创建
variable "create_db" {
type = bool
default = true
}
resource "aws_db_instance" "database" {
count = var.create_db ? 1 : 0
engine = "postgres"
instance_class = "db.t3.micro"
allocated_storage = 20
}
undefinedvariable "create_db" {
type = bool
default = true
}
resource "aws_db_instance" "database" {
count = var.create_db ? 1 : 0
engine = "postgres"
instance_class = "db.t3.micro"
allocated_storage = 20
}
undefinedConditional Expressions
条件表达式
hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.environment == "production" ? "t3.large" : "t3.micro"
tags = {
Name = var.environment == "production" ? "prod-web" : "dev-web"
}
}
locals {
instance_count = var.environment == "production" ? 5 : var.environment == "staging" ? 2 : 1
}hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.environment == "production" ? "t3.large" : "t3.micro"
tags = {
Name = var.environment == "production" ? "prod-web" : "dev-web"
}
}
locals {
instance_count = var.environment == "production" ? 5 : var.environment == "staging" ? 2 : 1
}Functions
函数
hcl
locals {
# String functions
name_upper = upper(var.name)
name_lower = lower(var.name)
name_title = title(var.name)
# Collection functions
subnet_count = length(var.subnet_cidrs)
first_az = element(var.availability_zones, 0)
all_azs = join(",", var.availability_zones)
# Numeric functions
min_instances = min(var.instance_count, 10)
max_instances = max(var.instance_count, 1)
# Type conversion
instance_count_string = tostring(var.instance_count)
az_set = toset(var.availability_zones)
# Map functions
merged_tags = merge(var.common_tags, var.specific_tags)
# File functions
user_data = file("${path.module}/scripts/init.sh")
config = templatefile("${path.module}/templates/config.tpl", {
environment = var.environment
region = var.region
})
# Encoding functions
encoded = base64encode("secret data")
decoded = base64decode(var.encoded_data)
# Date/Time functions
timestamp = timestamp()
# IP Network functions
cidr_subnets = cidrsubnets("10.0.0.0/16", 8, 8, 8, 8)
}hcl
locals {
# 字符串函数
name_upper = upper(var.name)
name_lower = lower(var.name)
name_title = title(var.name)
# 集合函数
subnet_count = length(var.subnet_cidrs)
first_az = element(var.availability_zones, 0)
all_azs = join(",", var.availability_zones)
# 数值函数
min_instances = min(var.instance_count, 10)
max_instances = max(var.instance_count, 1)
# 类型转换
instance_count_string = tostring(var.instance_count)
az_set = toset(var.availability_zones)
# 映射函数
merged_tags = merge(var.common_tags, var.specific_tags)
# 文件函数
user_data = file("${path.module}/scripts/init.sh")
config = templatefile("${path.module}/templates/config.tpl", {
environment = var.environment
region = var.region
})
# 编码函数
encoded = base64encode("secret data")
decoded = base64decode(var.encoded_data)
# 日期/时间函数
timestamp = timestamp()
# IP网络函数
cidr_subnets = cidrsubnets("10.0.0.0/16", 8, 8, 8, 8)
}Terraform Functions in Practice
Terraform函数实践
hcl
undefinedhcl
undefinedCreating multiple subnets across availability zones
在可用区中创建多个子网
locals {
subnet_cidrs = cidrsubnets(var.vpc_cidr, 8, 8, 8, 8)
}
data "aws_availability_zones" "available" {
state = "available"
}
resource "aws_subnet" "public" {
count = 3
vpc_id = aws_vpc.main.id
cidr_block = local.subnet_cidrs[count.index]
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "public-${count.index + 1}"
}
}
undefinedlocals {
subnet_cidrs = cidrsubnets(var.vpc_cidr, 8, 8, 8, 8)
}
data "aws_availability_zones" "available" {
state = "available"
}
resource "aws_subnet" "public" {
count = 3
vpc_id = aws_vpc.main.id
cidr_block = local.subnet_cidrs[count.index]
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "public-${count.index + 1}"
}
}
undefinedDependencies
依赖关系
Implicit Dependencies
隐式依赖
Terraform automatically infers dependencies from resource references.
hcl
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id # Implicit dependency
cidr_block = "10.0.1.0/24"
}
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t2.micro"
subnet_id = aws_subnet.public.id # Implicit dependency
}Terraform会自动从资源引用中推断依赖关系。
hcl
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" "web" {
ami = var.ami_id
instance_type = "t2.micro"
subnet_id = aws_subnet.public.id # 隐式依赖
}Explicit Dependencies
显式依赖
Use when dependencies cannot be inferred automatically.
depends_onhcl
resource "aws_instance" "app" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
depends_on = [aws_db_instance.database]
}
resource "aws_db_instance" "database" {
engine = "postgres"
instance_class = "db.t3.micro"
allocated_storage = 20
}当依赖关系无法自动推断时,使用。
depends_onhcl
resource "aws_instance" "app" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
depends_on = [aws_db_instance.database]
}
resource "aws_db_instance" "database" {
engine = "postgres"
instance_class = "db.t3.micro"
allocated_storage = 20
}Module Dependencies
模块依赖
hcl
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
}
module "app" {
source = "./modules/app"
vpc_id = module.vpc.vpc_id
subnet_id = module.vpc.private_subnet_ids[0]
depends_on = [module.vpc]
}hcl
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
}
module "app" {
source = "./modules/app"
vpc_id = module.vpc.vpc_id
subnet_id = module.vpc.private_subnet_ids[0]
depends_on = [module.vpc]
}Provisioners
置备器
Provisioners are used to execute scripts on a local or remote machine as part of resource creation or destruction.
置备器用于在资源创建或销毁时在本地或远程机器上执行脚本。
Local-Exec Provisioner
Local-Exec置备器
hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t2.micro"
provisioner "local-exec" {
command = "echo ${self.private_ip} >> private_ips.txt"
}
provisioner "local-exec" {
when = destroy
command = "echo 'Instance ${self.id} destroyed' >> destroy_log.txt"
}
}hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t2.micro"
provisioner "local-exec" {
command = "echo ${self.private_ip} >> private_ips.txt"
}
provisioner "local-exec" {
when = destroy
command = "echo 'Instance ${self.id} destroyed' >> destroy_log.txt"
}
}Remote-Exec Provisioner
Remote-Exec置备器
hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t2.micro"
key_name = var.key_name
connection {
type = "ssh"
user = "ubuntu"
private_key = file(var.private_key_path)
host = self.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx",
"sudo systemctl start nginx",
"sudo systemctl enable nginx"
]
}
}hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t2.micro"
key_name = var.key_name
connection {
type = "ssh"
user = "ubuntu"
private_key = file(var.private_key_path)
host = self.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx",
"sudo systemctl start nginx",
"sudo systemctl enable nginx"
]
}
}File Provisioner
File置备器
hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t2.micro"
key_name = var.key_name
connection {
type = "ssh"
user = "ubuntu"
private_key = file(var.private_key_path)
host = self.public_ip
}
provisioner "file" {
source = "scripts/init.sh"
destination = "/tmp/init.sh"
}
provisioner "remote-exec" {
inline = [
"chmod +x /tmp/init.sh",
"sudo /tmp/init.sh"
]
}
}hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t2.micro"
key_name = var.key_name
connection {
type = "ssh"
user = "ubuntu"
private_key = file(var.private_key_path)
host = self.public_ip
}
provisioner "file" {
source = "scripts/init.sh"
destination = "/tmp/init.sh"
}
provisioner "remote-exec" {
inline = [
"chmod +x /tmp/init.sh",
"sudo /tmp/init.sh"
]
}
}Provisioner Failure Behavior
置备器失败行为
hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t2.micro"
provisioner "local-exec" {
command = "./configure.sh"
on_failure = continue # or fail (default)
}
}hcl
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t2.micro"
provisioner "local-exec" {
command = "./configure.sh"
on_failure = continue # 或fail(默认)
}
}Best Practices
最佳实践
1. State Management
1. 状态管理
- Always use remote state for team collaboration
- Enable state locking to prevent concurrent modifications
- Enable encryption for sensitive data
- Regular state backups for disaster recovery
- 始终使用远程状态以支持团队协作
- 启用状态锁定防止并发修改
- 启用加密保护敏感数据
- 定期备份状态用于灾难恢复
2. Code Organization
2. 代码组织
project/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
├── modules/
│ ├── vpc/
│ ├── compute/
│ └── database/
└── global/
└── s3/project/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
├── modules/
│ ├── vpc/
│ ├── compute/
│ └── database/
└── global/
└── s3/3. Variable Management
3. 变量管理
hcl
undefinedhcl
undefinedUse meaningful descriptions
使用有意义的描述
variable "instance_type" {
description = "EC2 instance type for web servers"
type = string
default = "t3.micro"
}
variable "instance_type" {
description = "Web服务器使用的EC2实例类型"
type = string
default = "t3.micro"
}
Use validation
使用验证
variable "environment" {
description = "Deployment environment"
type = string
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "Environment must be dev, staging, or production."
}
}
undefinedvariable "environment" {
description = "部署环境"
type = string
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "环境必须是dev、staging或production。"
}
}
undefined4. Naming Conventions
4. 命名约定
hcl
undefinedhcl
undefinedResource naming
资源命名
resource "aws_instance" "web_server" { # Use descriptive names
tags = {
Name = "${var.project}-${var.environment}-web-${count.index + 1}"
}
}
resource "aws_instance" "web_server" { # 使用描述性名称
tags = {
Name = "${var.project}-${var.environment}-web-${count.index + 1}"
}
}
Module naming
模块命名
module "vpc_production" {
source = "./modules/vpc"
}
undefinedmodule "vpc_production" {
source = "./modules/vpc"
}
undefined5. DRY Principle
5. DRY原则
hcl
undefinedhcl
undefinedUse locals for repeated values
使用本地值存储重复值
locals {
common_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "Terraform"
CostCenter = var.cost_center
}
}
resource "aws_instance" "web" {
tags = merge(
local.common_tags,
{
Name = "web-server"
Role = "webserver"
}
)
}
undefinedlocals {
common_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "Terraform"
CostCenter = var.cost_center
}
}
resource "aws_instance" "web" {
tags = merge(
local.common_tags,
{
Name = "web-server"
Role = "webserver"
}
)
}
undefined6. Security Best Practices
6. 安全最佳实践
hcl
undefinedhcl
undefinedNever hardcode credentials
永远不要硬编码凭证
BAD
错误示例
provider "aws" {
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
provider "aws" {
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
GOOD - Use environment variables or IAM roles
正确示例 - 使用环境变量或IAM角色
provider "aws" {
Credentials from environment or IAM role
}
provider "aws" {
从环境变量或IAM角色获取凭证
}
Use sensitive flag for outputs
对输出使用敏感标记
output "database_password" {
value = aws_db_instance.main.password
sensitive = true
}
output "database_password" {
value = aws_db_instance.main.password
sensitive = true
}
Encrypt sensitive data
加密敏感数据
resource "aws_s3_bucket" "data" {
bucket = "my-data-bucket"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
undefinedresource "aws_s3_bucket" "data" {
bucket = "my-data-bucket"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
undefined7. Testing
7. 测试
bash
undefinedbash
undefinedValidate syntax
验证语法
terraform validate
terraform validate
Format code
格式化代码
terraform fmt -recursive
terraform fmt -recursive
Plan before apply
先规划后应用
terraform plan -out=tfplan
terraform plan -out=tfplan
Review plan
评审计划
terraform show tfplan
undefinedterraform show tfplan
undefined8. Version Control
8. 版本控制
.gitignore:
undefined.gitignore:
undefinedLocal .terraform directories
本地.terraform目录
*/.terraform/
*/.terraform/
.tfstate files
.tfstate文件
*.tfstate
.tfstate.
*.tfstate
.tfstate.
Crash log files
崩溃日志文件
crash.log
crash.*.log
crash.log
crash.*.log
Exclude variable files that may contain sensitive data
排除可能包含敏感数据的变量文件
*.tfvars
*.tfvars.json
*.tfvars
*.tfvars.json
Ignore override files
忽略覆盖文件
override.tf
override.tf.json
*_override.tf
*_override.tf.json
override.tf
override.tf.json
*_override.tf
*_override.tf.json
CLI configuration files
CLI配置文件
.terraformrc
terraform.rc
.terraformrc
terraform.rc
Plan files
计划文件
*.tfplan
undefined*.tfplan
undefined9. Module Best Practices
9. 模块最佳实践
hcl
undefinedhcl
undefinedModule versioning
模块版本控制
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0" # Pin to major version
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0" # 固定主版本
}
Module documentation
模块文档
Always include README.md with:
始终包含README.md,内容包括:
- Description
- 描述
- Requirements
- 要求
- Providers
- 提供商
- Inputs
- 输入
- Outputs
- 输出
- Example usage
- 使用示例
undefinedundefined10. Resource Tagging
10. 资源标记
hcl
undefinedhcl
undefinedConsistent tagging strategy
一致的标记策略
locals {
required_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "Terraform"
Owner = var.owner_email
CostCenter = var.cost_center
Compliance = var.compliance_level
}
}
locals {
required_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "Terraform"
Owner = var.owner_email
CostCenter = var.cost_center
Compliance = var.compliance_level
}
}
Use default tags at provider level
在提供商级别使用默认标记
provider "aws" {
region = var.region
default_tags {
tags = local.required_tags
}
}
undefinedprovider "aws" {
region = var.region
default_tags {
tags = local.required_tags
}
}
undefinedCI/CD Integration
CI/CD集成
GitHub Actions
GitHub Actions
.github/workflows/terraform.yml:
yaml
name: Terraform
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
TF_VERSION: 1.5.0
jobs:
terraform:
name: Terraform
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Terraform Format
run: terraform fmt -check -recursive
- name: Terraform Init
run: terraform init
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan
run: terraform plan -no-color
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -auto-approve
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}.github/workflows/terraform.yml:
yaml
name: Terraform
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
TF_VERSION: 1.5.0
jobs:
terraform:
name: Terraform
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Terraform Format
run: terraform fmt -check -recursive
- name: Terraform Init
run: terraform init
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan
run: terraform plan -no-color
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -auto-approve
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}GitLab CI
GitLab CI
.gitlab-ci.yml:
yaml
image:
name: hashicorp/terraform:1.5.0
entrypoint: [""]
stages:
- validate
- plan
- apply
before_script:
- terraform init
validate:
stage: validate
script:
- terraform validate
- terraform fmt -check -recursive
plan:
stage: plan
script:
- terraform plan -out=tfplan
artifacts:
paths:
- tfplan
expire_in: 1 week
apply:
stage: apply
script:
- terraform apply -auto-approve tfplan
dependencies:
- plan
only:
- main
when: manual.gitlab-ci.yml:
yaml
image:
name: hashicorp/terraform:1.5.0
entrypoint: [""]
stages:
- validate
- plan
- apply
before_script:
- terraform init
validate:
stage: validate
script:
- terraform validate
- terraform fmt -check -recursive
plan:
stage: plan
script:
- terraform plan -out=tfplan
artifacts:
paths:
- tfplan
expire_in: 1 week
apply:
stage: apply
script:
- terraform apply -auto-approve tfplan
dependencies:
- plan
only:
- main
when: manualJenkins Pipeline
Jenkins Pipeline
Jenkinsfile:
groovy
pipeline {
agent any
environment {
TF_VERSION = '1.5.0'
AWS_CREDENTIALS = credentials('aws-credentials')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Terraform Init') {
steps {
sh 'terraform init'
}
}
stage('Terraform Validate') {
steps {
sh 'terraform validate'
sh 'terraform fmt -check -recursive'
}
}
stage('Terraform Plan') {
steps {
sh 'terraform plan -out=tfplan'
}
}
stage('Terraform Apply') {
when {
branch 'main'
}
steps {
input message: 'Apply Terraform changes?', ok: 'Apply'
sh 'terraform apply -auto-approve tfplan'
}
}
}
post {
always {
cleanWs()
}
}
}Jenkinsfile:
groovy
pipeline {
agent any
environment {
TF_VERSION = '1.5.0'
AWS_CREDENTIALS = credentials('aws-credentials')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Terraform Init') {
steps {
sh 'terraform init'
}
}
stage('Terraform Validate') {
steps {
sh 'terraform validate'
sh 'terraform fmt -check -recursive'
}
}
stage('Terraform Plan') {
steps {
sh 'terraform plan -out=tfplan'
}
}
stage('Terraform Apply') {
when {
branch 'main'
}
steps {
input message: 'Apply Terraform changes?', ok: 'Apply'
sh 'terraform apply -auto-approve tfplan'
}
}
}
post {
always {
cleanWs()
}
}
}Azure DevOps
Azure DevOps
azure-pipelines.yml:
yaml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
- name: terraformVersion
value: '1.5.0'
stages:
- stage: Validate
jobs:
- job: ValidateTerraform
steps:
- task: TerraformInstaller@0
inputs:
terraformVersion: $(terraformVersion)
- task: TerraformTaskV2@2
displayName: 'Terraform Init'
inputs:
provider: 'aws'
command: 'init'
backendServiceAWS: 'AWS-Connection'
- task: TerraformTaskV2@2
displayName: 'Terraform Validate'
inputs:
provider: 'aws'
command: 'validate'
- script: terraform fmt -check -recursive
displayName: 'Terraform Format Check'
- stage: Plan
dependsOn: Validate
jobs:
- job: PlanTerraform
steps:
- task: TerraformTaskV2@2
displayName: 'Terraform Plan'
inputs:
provider: 'aws'
command: 'plan'
commandOptions: '-out=tfplan'
- stage: Apply
dependsOn: Plan
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: ApplyTerraform
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- task: TerraformTaskV2@2
displayName: 'Terraform Apply'
inputs:
provider: 'aws'
command: 'apply'
commandOptions: '-auto-approve tfplan'azure-pipelines.yml:
yaml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
- name: terraformVersion
value: '1.5.0'
stages:
- stage: Validate
jobs:
- job: ValidateTerraform
steps:
- task: TerraformInstaller@0
inputs:
terraformVersion: $(terraformVersion)
- task: TerraformTaskV2@2
displayName: 'Terraform Init'
inputs:
provider: 'aws'
command: 'init'
backendServiceAWS: 'AWS-Connection'
- task: TerraformTaskV2@2
displayName: 'Terraform Validate'
inputs:
provider: 'aws'
command: 'validate'
- script: terraform fmt -check -recursive
displayName: 'Terraform Format Check'
- stage: Plan
dependsOn: Validate
jobs:
- job: PlanTerraform
steps:
- task: TerraformTaskV2@2
displayName: 'Terraform Plan'
inputs:
provider: 'aws'
command: 'plan'
commandOptions: '-out=tfplan'
- stage: Apply
dependsOn: Plan
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: ApplyTerraform
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- task: TerraformTaskV2@2
displayName: 'Terraform Apply'
inputs:
provider: 'aws'
command: 'apply'
commandOptions: '-auto-approve tfplan'Pre-commit Hooks
Pre-commit Hooks
.pre-commit-config.yaml:
yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.81.0
hooks:
- id: terraform_fmt
- id: terraform_validate
- id: terraform_docs
- id: terraform_tflint
- id: terraform_tfsec
- id: terraform_checkov.pre-commit-config.yaml:
yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.81.0
hooks:
- id: terraform_fmt
- id: terraform_validate
- id: terraform_docs
- id: terraform_tflint
- id: terraform_tfsec
- id: terraform_checkovAutomated Testing
自动化测试
test/terraform_test.go:
go
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
func TestTerraformVPC(t *testing.T) {
terraformOptions := &terraform.Options{
TerraformDir: "../examples/vpc",
Vars: map[string]interface{}{
"cidr_block": "10.0.0.0/16",
"region": "us-west-2",
},
}
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
vpcId := terraform.Output(t, terraformOptions, "vpc_id")
assert.NotEmpty(t, vpcId)
}test/terraform_test.go:
go
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
func TestTerraformVPC(t *testing.T) {
terraformOptions := &terraform.Options{
TerraformDir: "../examples/vpc",
Vars: map[string]interface{}{
"cidr_block": "10.0.0.0/16",
"region": "us-west-2",
},
}
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
vpcId := terraform.Output(t, terraformOptions, "vpc_id")
assert.NotEmpty(t, vpcId)
}Additional Commands and Tools
其他命令和工具
Terraform Console
Terraform控制台
bash
undefinedbash
undefinedStart console
启动控制台
terraform console
terraform console
Example session:
示例会话:
aws_instance.example.public_ip "54.183.22.100" var.region "us-west-2" length(aws_instance.example.tags) 3
undefinedaws_instance.example.public_ip "54.183.22.100" var.region "us-west-2" length(aws_instance.example.tags) 3
undefinedTerraform Graph
Terraform图
bash
undefinedbash
undefinedGenerate graph in DOT format
生成DOT格式的图
terraform graph > graph.dot
terraform graph > graph.dot
Convert to image with Graphviz
使用Graphviz转换为图片
terraform graph | dot -Tpng > graph.png
terraform graph | dot -Tpng > graph.png
Generate graph for specific plan
为特定计划生成图
terraform graph -type=plan > plan-graph.dot
undefinedterraform graph -type=plan > plan-graph.dot
undefinedTerraform Taint
Terraform标记为脏
bash
undefinedbash
undefinedTaint a resource (mark for recreation)
将资源标记为脏(标记为需要重新创建)
terraform taint aws_instance.example
terraform taint aws_instance.example
Untaint a resource
取消标记
terraform untaint aws_instance.example
undefinedterraform untaint aws_instance.example
undefinedTerraform Providers
Terraform提供商
bash
undefinedbash
undefinedList required providers
列出所需提供商
terraform providers
terraform providers
Show provider schemas
显示提供商架构
terraform providers schema -json > schemas.json
terraform providers schema -json > schemas.json
Lock provider versions
锁定提供商版本
terraform providers lock
undefinedterraform providers lock
undefinedConclusion
总结
This comprehensive guide covers the essential aspects of Terraform Infrastructure as Code, from basic concepts to advanced patterns and CI/CD integration. By following these practices and patterns, you can build maintainable, scalable, and secure infrastructure deployments across any cloud provider.
Key takeaways:
- Use modules for reusable components
- Implement remote state with locking for team collaboration
- Leverage workspaces for environment isolation
- Follow security best practices and never hardcode credentials
- Integrate Terraform into CI/CD pipelines for automated deployments
- Use validation, formatting, and testing tools
- Maintain clear documentation and consistent naming conventions
- Implement proper tagging strategies for resource management
Terraform enables infrastructure teams to adopt DevOps practices, improve collaboration, reduce manual errors, and accelerate deployment cycles while maintaining full control and visibility over infrastructure changes.
本全面指南涵盖了Terraform基础设施即代码的基本概念到高级模式和CI/CD集成等关键方面。通过遵循这些实践和模式,你可以在任何云提供商上构建可维护、可扩展且安全的基础设施部署。
核心要点:
- 使用模块创建可复用组件
- 实现带锁定的远程状态以支持团队协作
- 利用工作区实现环境隔离
- 遵循安全最佳实践,永远不要硬编码凭证
- 将Terraform集成到CI/CD管道以实现自动化部署
- 使用验证、格式化和测试工具
- 保持清晰的文档和一致的命名约定
- 实施适当的标记策略以进行资源管理
Terraform使基础设施团队能够采用DevOps实践,改善协作,减少手动错误,加速部署周期,同时保持对基础设施变更的完全控制和可见性。