Terraform: Up & Running 代码示例教程
概述
《Terraform: Up & Running》是学习基础设施即代码(Infrastructure as Code, IaC)的权威指南,本书通过实践案例深入讲解Terraform的核心概念和最佳实践。本教程将基于官方代码仓库,带你系统学习Terraform从入门到精通的完整知识体系。
环境准备
安装Terraform
# 在Linux系统上安装Terraform
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install terraform
# 验证安装
terraform version
配置AWS凭证
# 配置AWS访问密钥
aws configure
# 或者设置环境变量
export AWS_ACCESS_KEY_ID="your_access_key"
export AWS_SECRET_ACCESS_KEY="your_secret_key"
export AWS_DEFAULT_REGION="us-east-2"
基础语法入门
第一个Terraform配置
让我们从最简单的示例开始,创建单个EC2实例:
# code/terraform/01-why-terraform/web-server/main.tf
terraform {
required_version = ">= 1.0.0, < 2.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
provider "aws" {
region = "us-east-2"
}
resource "aws_instance" "app" {
instance_type = "t2.micro"
availability_zone = "us-east-2a"
ami = "ami-0fb653ca2d3203ac1"
user_data = <<-EOF
#!/bin/bash
sudo service apache2 start
EOF
}
执行流程
变量和输出
定义变量
# code/terraform/02-intro-to-terraform-syntax/webserver-cluster/variables.tf
variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
default = 8080
}
variable "alb_name" {
description = "The name of the ALB"
type = string
default = "terraform-asg-example"
}
使用变量
resource "aws_security_group" "instance" {
name = var.instance_security_group_name
ingress {
from_port = var.server_port
to_port = var.server_port
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
定义输出
# code/terraform/02-intro-to-terraform-syntax/webserver-cluster/outputs.tf
output "alb_dns_name" {
value = aws_lb.example.dns_name
description = "The domain name of the load balancer"
}
output "asg_name" {
value = aws_autoscaling_group.example.name
description = "The name of the Auto Scaling Group"
}
模块化设计
模块结构
模块调用示例
# code/terraform/04-terraform-module/module-example/stage/services/webserver-cluster/main.tf
module "webserver_cluster" {
source = "../../../../modules/services/webserver-cluster"
cluster_name = "webservers-stage"
db_remote_state_bucket = "(YOUR_BUCKET_NAME)"
db_remote_state_key = "stage/data-stores/mysql/terraform.tfstate"
instance_type = "t2.micro"
min_size = 2
max_size = 2
}
状态管理
远程状态配置
terraform {
backend "s3" {
bucket = "(YOUR_BUCKET_NAME)"
key = "global/s3/terraform.tfstate"
region = "us-east-2"
dynamodb_table = "(YOUR_TABLE_NAME)"
encrypt = true
}
}
状态文件结构
| 组件 | 描述 | 示例路径 |
|---|---|---|
| 全局资源 | 跨环境共享的资源 | global/s3/terraform.tfstate |
| 环境资源 | 特定环境的资源 | stage/services/webserver-cluster/terraform.tfstate |
| 数据存储 | 数据库等数据资源 | stage/data-stores/mysql/terraform.tfstate |
循环和条件语句
count 参数循环
# 创建多个IAM用户
resource "aws_iam_user" "example" {
count = 3
name = "neo.${count.index}"
}
for_each 循环
# 使用for_each创建唯一名称的用户
resource "aws_iam_user" "example" {
for_each = toset(["neo", "trinity", "morpheus"])
name = each.value
}
条件表达式
# 根据环境变量决定是否创建资源
resource "aws_instance" "example" {
count = var.create_instance ? 1 : 0
instance_type = "t2.micro"
ami = "ami-0fb653ca2d3203ac1"
}
测试策略
单元测试示例
// code/terraform/09-testing-terraform-code/test/alb_example_test.go
func TestAlbExample(t *testing.T) {
t.Parallel()
opts := &terraform.Options{
TerraformDir: "../examples/alb",
Vars: map[string]interface{}{
"alb_name": fmt.Sprintf("test-%s", random.UniqueId()),
},
}
defer terraform.Destroy(t, opts)
terraform.InitAndApply(t, opts)
albDnsName := terraform.OutputRequired(t, opts, "alb_dns_name")
url := fmt.Sprintf("http://%s", albDnsName)
// 测试ALB默认动作返回404
expectedStatus := 404
expectedBody := "404: page not found"
http_helper.HttpGetWithRetry(
t,
url,
nil,
expectedStatus,
expectedBody,
10,
10*time.Second,
)
}
测试类型对比
| 测试类型 | 描述 | 适用场景 | 工具 |
|---|---|---|---|
| 语法检查 | 验证Terraform配置语法 | 开发阶段 | terraform validate |
| 计划测试 | 检查执行计划是否符合预期 | 代码审查 | terraform plan |
| 单元测试 | 测试单个模块的功能 | 模块开发 | terratest |
| 集成测试 | 测试多个模块的协作 | 系统测试 | terratest |
| 合规测试 | 检查安全性和合规性 | 安全审计 | OPA |
生产级最佳实践
目录结构设计
infrastructure/
├── modules/
│ ├── networking/
│ │ └── alb/
│ ├── data-stores/
│ │ └── mysql/
│ └── services/
│ └── webserver-cluster/
├── live/
│ ├── prod/
│ │ ├── data-stores/
│ │ └── services/
│ └── stage/
│ ├── data-stores/
│ └── services/
└── examples/
├── alb/
├── asg/
└── mysql/
安全最佳实践
-
密钥管理
# 使用AWS Secrets Manager管理数据库密码 data "aws_secretsmanager_secret_version" "db_password" { secret_id = "mysql-master-password-stage" } -
最小权限原则
# 为EC2实例分配最小必要权限的IAM角色 resource "aws_iam_role" "example" { name = "example" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } } ] }) }
团队协作
工作空间管理
# 使用工作空间管理多环境
locals {
environment = terraform.workspace
}
resource "aws_instance" "example" {
instance_type = local.environment == "prod" ? "m5.large" : "t2.micro"
ami = "ami-0fb653ca2d3203ac1"
tags = {
Environment = local.environment
}
}
CI/CD集成
# GitHub Actions工作流示例
name: Terraform CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
- name: Terraform Format
run: terraform fmt -check
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan
run: terraform plan
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
故障排除和调试
常见问题解决
| 问题类型 | 症状 | 解决方案 |
|---|---|---|
| 状态文件冲突 | Error acquiring state lock | 检查并释放状态锁 |
| 资源依赖问题 | Circular dependency detected | 使用depends_on显式声明依赖 |
| 权限不足 | AccessDeniedException | 检查IAM策略和权限 |
| 网络问题 | Timeout waiting for LB | 检查安全组和网络ACL |
调试技巧
# 启用详细日志
export TF_LOG=DEBUG
export TF_LOG_PATH=terraform.log
# 检查执行计划详情
terraform plan -detailed-exitcode
# 导入现有资源
terraform import aws_instance.example i-1234567890abcdef0
总结
通过《Terraform: Up & Running》的代码示例,我们系统学习了:
- 基础语法 - 资源、变量、输出的定义和使用
- 模块化设计 - 如何创建和调用可重用模块
- 状态管理 - 本地和远程状态的最佳实践
- 测试策略 - 单元测试和集成测试的实施
- 生产部署 - 多环境管理和CI/CD集成
- 团队协作 - 工作空间和版本控制策略
Terraform作为基础设施即代码的标准工具,通过声明式配置和强大的生态系统,为现代云原生应用提供了可靠的基础设施管理方案。掌握这些核心概念和实践,将帮助你在实际项目中构建可维护、可扩展的基础设施代码库。
记住,良好的Terraform实践不仅仅是编写配置,更重要的是建立可重复、可测试、可协作的工作流程。从简单的单实例部署开始,逐步扩展到复杂的多模块架构,让基础设施代码成为你技术栈中的强大资产。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



