1. 概述
在我们之前的文章《Terraform 基础概念与使用》中,我们介绍了 Terraform 的基本用法。本文将进一步探讨使用 Terraform 时的一些最佳实践,帮助你在实际项目中更好地组织代码、管理状态和协作开发。
2. 资源文件组织结构
刚开始使用 Terraform 时,我们可能会把所有资源定义、变量和输出都放在一个文件中。这种做法虽然简单,但随着项目规模增长,代码将变得难以维护和复用。
✅ 推荐做法:利用 Terraform 在模块内自动读取所有 .tf
文件的特性,按功能将内容分文件管理。虽然资源声明顺序对 Terraform 无影响,但良好的组织结构有助于理解和协作。
常见的文件结构如下:
variables.tf
:定义模块输入变量,含默认值(如适用)main.tf
:核心资源定义,建议保持简洁,遵循单一职责原则modules/
:存放子模块(如有)outputs.tf
:定义输出变量providers.tf
:仅用于顶层模块,声明所用的 Provider 及其版本
⚠️ 注意:当 main.tf
文件变得臃肿时,应考虑将其拆分为多个子模块,比如将 EC2 实例与其绑定的 EBS 卷封装为一个模块。
3. 模块使用规范
模块是 Terraform 提供的复用机制,但如何设计模块结构是关键。我们可以借鉴软件工程中 S.O.L.I.D 原则中的 单一职责原则(Single Responsibility Principle)。
✅ 建议:每个模块只关注一个基础设施方面,比如创建 VPC、部署虚拟机等。
以下是一个典型项目结构示例:
$ tree .
├── main.tf
├── modules
│ ├── ingress
│ │ └── www.petshop.com.br
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── SvcFeedback
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── outputs.tf
├── terraform.tfvars
└── variables.tf
每个模块包含:
variables.tf
:输入变量main.tf
:资源定义outputs.tf
:输出变量
这种结构有助于模块使用者快速理解接口(即变量与输出),而无需关心具体实现。
4. Provider 配置管理
Terraform 中的 Provider 是与云平台交互的关键组件,通常需要配置访问密钥、区域等敏感信息。
❌ 不推荐做法:将敏感信息硬编码在代码中。
4.1 使用变量配置 Provider
通过定义变量来传递敏感信息:
variable "aws_region" {
type = string
}
variable "aws_access_key" {
type = string
}
variable "aws_secret_key" {
type = string
}
然后在 provider
声明中使用:
provider "aws" {
region = var.aws_region
access_key = var.aws_access_key
secret_key = var.aws_secret_key
}
变量值可以通过 .tfvars
文件或环境变量传入:
# aws.tfvars
aws_access_key = "xxxxx"
aws_secret_key = "yyyyy"
aws_region = "us-east-1"
运行命令时也可以混合使用环境变量和命令行参数:
$ export TF_VAR_aws_region="us-east-1"
$ terraform plan -var="access_key=xxxx" -var-file=./aws.tfvars
Terraform 默认会读取 terraform.tfvars
和所有以 .auto.tfvars
结尾的文件。
4.2 利用 Provider 的默认配置机制
某些 Provider 支持从本地配置文件读取凭证,比如 Kubernetes Provider 可以直接使用 kubectl
的上下文配置。
✅ 优势:省去手动配置,提高安全性。
5. State 管理
Terraform 的 State 文件记录了当前基础设施的状态,包含敏感信息,必须妥善管理。
✅ 推荐做法:
- 将
.tfstate
文件加入.gitignore
,避免提交到版本控制系统 - 尽早使用远程后端(Remote Backend)代替默认的本地存储
- 启用 State 锁定机制,避免并发冲突
5.1 远程 Backend 配置示例
以 PostgreSQL 为例:
terraform {
backend "pg" {}
}
远程后端通常需要额外配置,建议通过环境变量或 .auto.tfvars
文件传入。
✅ 优势:
- 支持多用户协作
- 提供 State 锁定功能,防止并发操作冲突
5.2 推荐使用自动化工具运行 Terraform
建议将 Terraform 部署过程集成到 CI/CD 流程中,例如 Jenkins、GitLab CI 等。
中小型团队也可以考虑使用 Terraform Cloud 的免费版本进行统一管理。
6. Workspaces 使用建议
Workspaces 允许我们在同一套代码下维护多个 State,适用于管理多个环境(如 DEV/QA/PRD)。
✅ 推荐做法:以环境名称命名 Workspaces,例如 DEV
, QA
, PRD
,便于识别。
如果多个团队协作开发,也可以加入团队名称,例如 DEV-SQUAD1
, DEV-SUPPORT
。
⚠️ 注意:不同 Workspace 的变量配置可能不同,建议通过 .tfvars
文件控制。
7. 自动化测试实践
随着基础设施代码化(IaC)的推进,测试变得越来越重要,尤其是在模块开发中。
✅ 建议测试内容:
- 可访问性:资源是否成功创建?是否可达?
- 安全性:是否有不必要的端口开放?是否禁用了默认账户?
- 正确性:模块是否正确使用输入参数?是否对缺失参数做出反馈?
Terraform 的测试生态仍在演进中,目前可以使用如下方式:
- 使用测试框架:FitNesse、Spock、Protractor 等
- 使用 Shell 脚本编写集成测试
- 集成到 CI/CD 流程中自动运行
⚠️ 提示:建议优先编写集成测试,而不是单元测试,因为基础设施本身是集成性很强的系统。
8. 总结
本文介绍了 Terraform 使用中的一些最佳实践,包括资源文件组织、模块设计、Provider 配置、State 管理、Workspaces 使用及测试策略。
由于基础设施即代码(IaC)仍处于快速发展阶段,这些实践只是一个起点。随着社区的不断演进,我们也将看到更多新工具和新模式的出现。
如需参考完整示例代码,请查看 GitHub 项目:Terraform Best Practices 示例代码。