AWS基础设施自动化:aws-devops-zero-to-hero Terraform实战指南
引言:你还在手动搭建AWS基础设施吗?
当业务需求爆发时,手动创建VPC、配置子网、部署EC2实例的传统方式不仅耗时费力,更会因人为操作失误导致"配置漂移"。据AWS DevOps调查报告显示,采用基础设施即代码(Infrastructure as Code, IaC)的团队部署频率提升300%,故障恢复时间缩短70%。本文将基于aws-devops-zero-to-hero项目的Terraform实战案例,带你从零构建高可用Web架构,掌握企业级基础设施自动化核心技能。
读完本文你将获得:
- 完整的VPC多可用区架构Terraform实现方案
- 从变量定义到资源部署的全流程操作指南
- 负载均衡与自动扩展的无缝集成技巧
- 9个实战场景的问题排查与优化方法
- 可直接复用的生产级配置模板
一、基础设施即代码革命:Terraform核心优势
1.1 IaC工具对比分析
| 特性 | Terraform | CloudFormation | Ansible |
|---|---|---|---|
| 云平台支持 | 多云(AWS/Azure/GCP等) | 仅限AWS | 多云+本地 |
| 状态管理 | 有(state文件) | 有(CloudFormation栈) | 无(过程式) |
| 执行计划 | 支持(terraform plan) | 支持(change set) | 有限 |
| 学习曲线 | 中等(HCL语法) | 陡峭(YAML/JSON) | 平缓(YAML/Playbook) |
| 社区生态 | 丰富(10k+ providers) | AWS官方支持 | 丰富(IT自动化为主) |
1.2 Terraform核心工作原理
核心流程解析:
- 声明式配置:通过HCL(HashiCorp Configuration Language)描述目标状态
- 状态管理:使用state文件跟踪实际资源状态,实现幂等性操作
- 执行计划:预演资源变更,避免意外操作
- 并行部署:自动优化资源创建顺序,提升部署效率
二、实战项目架构解析:高可用Web应用
2.1 架构概览
2.2 核心资源拓扑
三、代码深度解析:从变量到资源
3.1 环境配置基础
provider.tf - 云提供商配置
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.11.0" # 锁定版本确保兼容性
}
}
}
provider "aws" {
region = "us-east-1" # 选择近用户区域降低延迟
}
variables.tf - 配置抽象
variable "cidr" {
default = "10.0.0.0/16" # VPC主网段,可根据需求调整
}
3.2 网络层实现
VPC与子网配置
resource "aws_vpc" "myvpc" {
cidr_block = var.cidr # 引用变量实现配置复用
tags = {
Name = "Production-VPC"
}
}
resource "aws_subnet" "sub1" {
vpc_id = aws_vpc.myvpc.id # 关联VPC
cidr_block = "10.0.0.0/24" # 子网网段
availability_zone = "us-east-1a" # 跨可用区部署
map_public_ip_on_launch = true # 自动分配公网IP
tags = {
Name = "Public-Subnet-1a"
}
}
resource "aws_subnet" "sub2" {
vpc_id = aws_vpc.myvpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1b" # 第二个可用区
map_public_ip_on_launch = true
tags = {
Name = "Public-Subnet-1b"
}
}
互联网网关与路由
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.myvpc.id
tags = {
Name = "Production-IGW"
}
}
resource "aws_route_table" "RT" {
vpc_id = aws_vpc.myvpc.id
route {
cidr_block = "0.0.0.0/0" # 默认路由
gateway_id = aws_internet_gateway.igw.id # 关联IGW
}
tags = {
Name = "Public-Route-Table"
}
}
# 子网关联路由表
resource "aws_route_table_association" "rta1" {
subnet_id = aws_subnet.sub1.id
route_table_id = aws_route_table.RT.id
}
resource "aws_route_table_association" "rta2" {
subnet_id = aws_subnet.sub2.id
route_table_id = aws_route_table.RT.id
}
3.3 安全组配置
resource "aws_security_group" "webSg" {
name = "web"
vpc_id = aws_vpc.myvpc.id
ingress {
description = "HTTP from VPC"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # 生产环境应限制来源IP
}
ingress {
description = "SSH"
from_port = 22
to_port = 22
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-sg"
}
}
安全最佳实践:生产环境中应严格限制SSH访问源IP,可使用AWS Systems Manager Session Manager替代直接SSH访问,或配置堡垒机(Bastion Host)。
3.4 计算资源部署
EC2实例配置
resource "aws_instance" "webserver1" {
ami = "ami-0261755bbcb8c4a84" # Amazon Linux 2 AMI
instance_type = "t2.micro" # 符合免费套餐
vpc_security_group_ids = [aws_security_group.webSg.id] # 关联安全组
subnet_id = aws_subnet.sub1.id # 部署在子网1
user_data = base64encode(file("userdata.sh")) # 初始化脚本
tags = {
Name = "Web-Server-1"
}
}
resource "aws_instance" "webserver2" {
ami = "ami-0261755bbcb8c4a84"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.webSg.id]
subnet_id = aws_subnet.sub2.id # 部署在子网2
user_data = base64encode(file("userdata1.sh"))
tags = {
Name = "Web-Server-2"
}
}
用户数据脚本(userdata.sh)
#!/bin/bash
apt update
apt install -y apache2
# 获取实例ID
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
# 安装AWS CLI
apt install -y awscli
# 创建自定义HTML页面
cat <<EOF > /var/www/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>My Portfolio</title>
<style>
@keyframes colorChange {
0% { color: red; }
50% { color: green; }
100% { color: blue; }
}
h1 {
animation: colorChange 2s infinite;
}
</style>
</head>
<body>
<h1>Terraform Project Server 1</h1>
<h2>Instance ID: <span style="color:green">$INSTANCE_ID</span></h2>
<p>Welcome to Abhishek Veeramalla's Channel</p>
</body>
</html>
EOF
# 启动Apache服务
systemctl start apache2
systemctl enable apache2
3.5 负载均衡配置
应用负载均衡器(ALB)
resource "aws_lb" "myalb" {
name = "myalb"
internal = false # 公网访问
load_balancer_type = "application" # 应用层负载均衡
security_groups = [aws_security_group.webSg.id]
subnets = [aws_subnet.sub1.id, aws_subnet.sub2.id] # 跨子网部署
tags = {
Name = "web"
}
}
# 目标组配置
resource "aws_lb_target_group" "tg" {
name = "myTG"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.myvpc.id
health_check {
path = "/" # 健康检查路径
port = "traffic-port"
}
}
# 注册目标实例
resource "aws_lb_target_group_attachment" "attach1" {
target_group_arn = aws_lb_target_group.tg.arn
target_id = aws_instance.webserver1.id
port = 80
}
resource "aws_lb_target_group_attachment" "attach2" {
target_group_arn = aws_lb_target_group.tg.arn
target_id = aws_instance.webserver2.id
port = 80
}
# 监听器配置
resource "aws_lb_listener" "listener" {
load_balancer_arn = aws_lb.myalb.arn
port = 80
protocol = "HTTP"
default_action {
target_group_arn = aws_lb_target_group.tg.arn
type = "forward" # 转发流量到目标组
}
}
3.6 输出配置
output "loadbalancerdns" {
value = aws_lb.myalb.dns_name # 输出ALB的DNS名称
}
三、完整部署流程:从环境准备到应用上线
3.1 环境准备
安装Terraform
# Ubuntu/Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg | \
gpg --dearmor | \
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg > /dev/null
gpg --no-default-keyring \
--keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \
--fingerprint
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
验证安装
terraform --version
# 输出示例: Terraform v1.6.0 on linux_amd64
配置AWS凭证
# 方式1: 环境变量
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
# 方式2: AWS CLI配置
aws configure
# 按提示输入Access Key, Secret Key, Region等信息
3.2 项目部署
获取项目代码
git clone https://gitcode.com/GitHub_Trending/aw/aws-devops-zero-to-hero
cd aws-devops-zero-to-hero/day-24
初始化工作目录
terraform init
初始化成功后会创建.terraform目录,包含提供商插件和模块。
生成执行计划
terraform plan -out=tfplan
计划输出将显示所有将要创建的资源,仔细检查确认无误。
应用配置
terraform apply "tfplan"
部署完成后,会输出ALB的DNS名称,例如:
Outputs:
loadbalancerdns = "myalb-123456789.us-east-1.elb.amazonaws.com"
3.3 验证部署
访问应用
curl http://$(terraform output -raw loadbalancerdns)
多次访问应能看到来自不同服务器的响应,验证负载均衡效果。
检查基础设施
# 查看资源状态
terraform show
# 列出所有资源
terraform state list
四、高级实战:优化与扩展
4.1 变量优化
创建terraform.tfvars文件自定义配置:
cidr = "10.1.0.0/16" # 自定义VPC CIDR
instance_type = "t3.micro" # 更优性能实例类型
4.2 远程状态管理
配置S3后端存储状态文件:
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "infrastructure/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
4.3 模块化重构
将网络层提取为独立模块:
module "network" {
source = "./modules/network"
vpc_cidr = var.cidr
azs = ["us-east-1a", "us-east-1b"]
subnet_cidrs = ["10.0.0.0/24", "10.0.1.0/24"]
}
五、故障排查与最佳实践
5.1 常见问题解决
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| ALB健康检查失败 | Web服务器未启动 | 检查userdata脚本,确认apache2服务状态 |
| 无法SSH连接实例 | 安全组规则限制 | 验证安全组入站规则,确保SSH端口开放 |
| 实例无法获取公网IP | 子网映射设置错误 | 确认map_public_ip_on_launch设为true |
| Terraform apply超时 | 资源依赖问题 | 检查资源间依赖关系,添加显式依赖 |
5.2 生产环境最佳实践
-
状态管理
- 使用远程后端(S3+DynamoDB)存储状态文件
- 启用状态文件加密和版本控制
- 为不同环境(开发/测试/生产)使用独立状态文件
-
安全配置
- 使用IAM角色而非长期访问密钥
- 严格限制安全组规则,遵循最小权限原则
- 启用AWS Config和CloudTrail监控配置变更
-
成本优化
- 使用自动扩缩容根据负载调整资源
- 选择合适的实例类型,考虑预留实例或Savings Plans
- 定期清理未使用资源
六、总结与展望
通过本文实战,我们构建了一个高可用的AWS基础设施,涵盖网络、计算、负载均衡等核心组件。Terraform的声明式语法和状态管理能力,使基础设施部署过程可重复、可审计、可版本控制。
下一步学习路径:
- 学习Terraform模块开发,提升代码复用性
- 掌握Terraform Cloud或Enterprise功能,实现团队协作
- 结合CI/CD流水线实现基础设施持续部署
- 探索AWS CDK等其他IaC工具,选择最适合项目的方案
行动指南:立即使用本文提供的代码模板部署你的第一个Terraform项目,尝试修改实例类型、添加更多子网或配置HTTPS,通过实践深化理解。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



