7天搞定AWS基础设施测试:基于Terratest的实战指南
引言:你还在手动验证AWS资源吗?
当你使用Terraform部署了包含2个EC2实例、1个ALB和完整VPC网络的基础设施后,如何确保:
- 安全组确实只开放了80和22端口?
- ALB能正确转发流量到两个可用区的实例?
- S3桶命名符合公司规范且未公开访问?
手动登录AWS控制台检查这些配置通常需要30分钟/次,而使用Terratest可将其压缩至5分钟的自动化测试流程。本文将以aws-devops-zero-to-hero项目的day-24基础设施为案例,带你构建完整的基础设施测试体系。
读完本文你将掌握:
- 用Terratest编写可复用的AWS资源测试套件
- 实现VPC/EC2/ALB/S3的关键属性验证
- 集成测试到CI/CD流水线的最佳实践
- 测试优化技巧:并行执行/超时控制/成本控制
一、基础设施测试现状与痛点
1.1 传统验证方式的三大痛点
| 验证方式 | 平均耗时 | 覆盖率 | 可持续性 |
|---|---|---|---|
| 控制台手动检查 | 30-60分钟 | ≤40% | 低(人员流动影响大) |
| AWS CLI脚本 | 15-20分钟 | 60-70% | 中(维护成本高) |
| Terratest自动化测试 | 5-8分钟 | ≥95% | 高(代码化维护) |
1.2 基础设施即代码的测试盲区
二、Terratest快速入门
2.1 核心组件与工作原理
2.2 环境准备
# 安装Go (Terratest基于Go语言)
sudo apt update && sudo apt install golang -y
# 验证安装
go version # 需≥1.16版本
# 创建测试目录
mkdir -p test && cd test
# 初始化Go模块
go mod init github.com/aw/aws-devops-zero-to-hero/test
go get github.com/gruntwork-io/terratest/modules/terraform
go get github.com/aws/aws-sdk-go/aws
三、实战:测试day-24基础设施
3.1 测试目标分析
day-24/main.tf包含的核心资源:
- 1个VPC (10.0.0.0/16 CIDR)
- 2个公有子网 (10.0.0.0/24, 10.0.1.0/24)
- 2个EC2实例 (t2.micro, Amazon Linux 2)
- 1个应用负载均衡器(ALB)
- 1个S3桶 (abhisheksterraform2023project)
3.2 完整测试代码 (test/terraform_test.go)
package test
import (
"testing"
"time"
"github.com/gruntwork-io/terratest/modules/aws"
"github.com/gruntwork-io/terratest/modules/http-helper"
"github.com/gruntwork-io/terratest/modules/terraform"
)
func TestTerraformAwsInfrastructure(t *testing.T) {
t.Parallel() // 支持并行测试
// 配置Terraform选项
terraformOptions := &terraform.Options{
TerraformDir: "../day-24", // day-24目录的相对路径
}
// 测试结束后自动清理资源
defer terraform.Destroy(t, terraformOptions)
// 部署基础设施
terraform.InitAndApply(t, terraformOptions)
// ==============================================
// 1. 验证VPC和子网配置
// ==============================================
vpcId := terraform.Output(t, terraformOptions, "vpc_id")
aws.AssertVpcExists(t, vpcId)
// 验证子网数量
subnetIds := aws.GetSubnetIdsForVpc(t, vpcId)
if len(subnetIds) != 2 {
t.Errorf("预期2个子网,实际发现%d个", len(subnetIds))
}
// ==============================================
// 2. 验证EC2实例状态
// ==============================================
instanceIds := []string{
terraform.Output(t, terraformOptions, "webserver1_id"),
terraform.Output(t, terraformOptions, "webserver2_id"),
}
for _, instanceId := range instanceIds {
aws.AssertInstanceState(t, instanceId, "running")
aws.AssertInstanceType(t, instanceId, "t2.micro")
}
// ==============================================
// 3. 验证ALB可用性
// ==============================================
albDns := terraform.Output(t, terraformOptions, "loadbalancerdns")
url := fmt.Sprintf("http://%s", albDns)
// 验证HTTP响应 (重试3次,间隔5秒)
http_helper.HttpGetWithRetry(t, url, nil, 200, "Hello World", 3, 5*time.Second)
// ==============================================
// 4. 验证S3桶配置
// ==============================================
bucketName := "abhisheksterraform2023project"
aws.AssertS3BucketExists(t, bucketName)
// 验证桶私有性
isPublic := aws.IsPublicS3Bucket(t, bucketName)
if isPublic {
t.Error("S3桶意外设置为公开访问")
}
}
3.3 关键测试点解析
3.3.1 VPC与网络层测试矩阵
| 测试项 | 预期结果 | 测试方法 |
|---|---|---|
| VPC CIDR | 10.0.0.0/16 | aws.GetVpcCidrBlock() |
| 子网可用性 | 2个可用区 | len(subnetIds) == 2 |
| 公网IP分配 | 自动分配 | aws.SubnetHasMapPublicIpOnLaunch() |
| 路由表关联 | 所有子网关联IGW | aws.AssertRouteTableAssociatedWithSubnet() |
3.3.2 安全组规则验证代码
// 验证安全组入站规则
sgId := terraform.Output(t, terraformOptions, "web_sg_id")
ingressRules := aws.GetSecurityGroupIngressRules(t, sgId)
expectedPorts := map[int]bool{80: true, 22: true}
for _, rule := range ingressRules {
if rule.FromPort != rule.ToPort {
t.Errorf("端口范围不合法: %d-%d", rule.FromPort, rule.ToPort)
}
if !expectedPorts[rule.FromPort] {
t.Errorf("发现未授权端口: %d", rule.FromPort)
}
delete(expectedPorts, rule.FromPort)
}
if len(expectedPorts) > 0 {
t.Errorf("缺少预期端口规则: %v", expectedPorts)
}
四、集成CI/CD流水线
4.1 GitHub Actions配置 (.github/workflows/terratest.yml)
name: Infrastructure Tests
on:
push:
branches: [ main ]
paths:
- 'day-24/**'
- 'test/**'
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Run Terratest
run: |
cd test
go mod download
go test -v -timeout 30m # 增加超时时间应对AWS资源创建延迟
4.2 测试优化策略
五、进阶技巧与最佳实践
5.1 测试模块化设计
// 将通用测试逻辑抽象为函数
func TestVpcConfiguration(t *testing.T, vpcId string) {
// VPC测试通用代码
}
func TestEc2Instances(t *testing.T, instanceIds []string) {
// EC2测试通用代码
}
5.2 成本控制措施
- 使用测试专用AWS账户
- 设置资源标签
Environment=Test便于识别 - 实施自动清理机制:
// 即使测试失败也确保清理 defer func() { if r := recover(); r != nil { terraform.Destroy(t, terraformOptions) panic(r) } }()
5.3 常见问题排查
| 错误类型 | 可能原因 | 解决方案 |
|---|---|---|
| 超时错误 | AWS资源创建延迟 | 增加重试次数和超时时间 |
| 权限不足 | IAM角色权限不够 | 附加AmazonEC2FullAccess策略 |
| 资源冲突 | 测试环境未清理干净 | 使用随机后缀生成唯一资源名称 |
六、总结与下一步
通过本文你已掌握:
- 使用Terratest编写AWS基础设施测试的完整流程
- 针对VPC/EC2/ALB/S3等核心资源的验证方法
- 集成GitHub Actions实现持续测试
下一步行动:
- 为day-21的Docker应用添加容器化测试
- 实现多环境测试矩阵 (dev/test/prod)
- 探索高级测试:混沌工程与故障注入
点赞+收藏+关注,下期分享《Terraform模块化设计最佳实践》
附录:测试资源清单
| 工具 | 版本要求 | 用途 |
|---|---|---|
| Go | ≥1.16 | 测试代码运行环境 |
| Terraform | ≥1.0 | 基础设施部署 |
| Terratest | ≥0.40 | 基础设施测试库 |
| AWS CLI | ≥2.0 | AWS资源交互 |
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



