Terraform 与 Ansible 深度解析:基础设施即代码、状态管理、配置自动化与生产实践
摘要:基础设施即代码并不只是把命令写进脚本,而是用版本化、可评审、可重复的声明描述基础设施。Terraform 擅长创建和管理云资源生命周期,Ansible 擅长配置操作系统、服务和应用。本文分析二者的职责边界、工作流程、状态、安全、模块化、漂移、流水线和生产治理。

一、为什么需要基础设施即代码
人工在控制台创建虚拟机、网络、负载均衡和账号,初期很快,但随着环境增多会产生配置不一致、操作不可追溯、灾难后难以重建、知识依赖个人等问题。
基础设施即代码(IaC)把资源和配置写成代码,纳入版本控制和评审,通过流水线执行。目标包括:
- 同一套定义能够重复创建开发、测试和生产环境;
- 变更在执行前可以评审和预览;
- 资源依赖由工具计算,降低手工顺序错误;
- 配置和变更历史可以审计;
- 灾难恢复时能够重建基础设施;
- 通过模块和策略形成组织级标准。
IaC 不会自动消除风险,它只是把风险从临时人工操作转移到代码、状态、凭据和流水线治理上。
二、Terraform 与 Ansible 的职责边界
Terraform 是声明式资源编排工具,通过 Provider 调用云平台、OpenStack、Kubernetes、DNS、SaaS 等 API。它根据配置和 State 计算资源应创建、修改或销毁。
Ansible 是远程系统配置与自动化工具。控制节点读取 Inventory 和 Playbook,通过 SSH、WinRM 或 API 管理目标主机,常用于安装软件、修改配置、启动服务和部署应用。
推荐边界是:
- Terraform 创建 VPC、子网、虚拟机、负载均衡、数据库、DNS 和安全策略等资源。
- Ansible 配置操作系统、用户、软件包、中间件、应用和运行参数。
- 镜像构建工具制作基础镜像,减少新主机启动后的可变配置。
- Kubernetes 资源使用 Helm、Kustomize 或 GitOps 管理,避免职责过度重叠。
边界并非绝对,但同一资源最好只有一个权威管理者,否则 Terraform、Ansible、控制台和其他系统可能互相覆盖。
三、Terraform 工作原理
Terraform 官方工作流可概括为 Write、Plan、Apply。
1. Write
使用 HCL 定义 Provider、Resource、Data Source、Variable、Local、Output 和 Module。代码描述期望状态,而非逐步执行命令。
terraform {
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
}
}
}
resource "openstack_compute_instance_v2" "web" {
name = "web-01"
image_name = "ubuntu"
flavor_name = "m1.small"
network {
name = "app-network"
}
}
2. Plan
Terraform 读取配置、State 和远端资源,构建依赖图并生成执行计划。计划中的 create、update、replace 和 destroy 应由人或策略检查。
3. Apply
审批后,Terraform 按依赖关系执行变更。无依赖资源可以并行处理。执行结束后,实际资源标识和属性写入 State。
计划不是永久有效的承诺。如果计划和 Apply 之间远端资源或 State 发生变化,应重新生成并审查最终计划。
四、Terraform State 为什么重要
State 保存 Terraform 配置中的资源与真实平台对象之间的映射,例如 openstack_compute_instance_v2.web 对应哪个实例 ID。Terraform 还利用 State 保存依赖元数据、输出值和部分属性。
State 可能包含敏感数据。生产环境应使用支持以下能力的远端 Backend:
- 加密存储和传输;
- 严格访问控制;
- 版本与恢复;
- State Locking,避免多人同时 Apply;
- 审计日志;
- 可靠备份。
不要把 terraform.tfstate 提交到普通 Git 仓库,也不要手工编辑 JSON。资源改名、拆分模块或导入已有资源时,应使用 moved、import 和 terraform state 等受控方式。
五、依赖图与生命周期
Terraform 能从资源引用推断隐式依赖。例如子网引用网络 ID,实例引用子网 ID,工具会自动按顺序执行。只有无法从属性关系推断时才使用 depends_on。
生命周期参数可以控制替换顺序和保护策略:
create_before_destroy:先创建新资源再删除旧资源,但需要平台容量和名称允许。prevent_destroy:防止误删关键资源,但不是完整权限控制。ignore_changes:忽略特定属性变化,过度使用会掩盖真实漂移。
任何触发 Replace 的变更都要确认数据、IP、连接和停机影响。
六、模块化设计
Module 是可复用的基础设施组件,例如标准 VPC、Kubernetes 节点组、OpenStack 三层网络或应用负载均衡。
好的模块应该:
- 有明确职责和稳定输入输出;
- 提供合理默认值,但暴露真正需要变化的参数;
- 固定 Provider 和模块版本范围;
- 包含示例、说明、测试和升级记录;
- 不把所有资源塞进一个“万能模块”;
- 避免输出不必要的敏感信息。
根模块通常负责组合环境,子模块负责可复用能力。开发、测试和生产环境可以共享模块,但应使用独立 State 和凭据。
七、Ansible 核心模型
Ansible 官方入门模型由 Control Node、Inventory 和 Managed Nodes 构成。Playbook 是 YAML 自动化蓝图,包含 Play、Task 和 Module。
Inventory
Inventory 描述目标主机、分组和变量,可以是静态 INI/YAML,也可以从云平台、OpenStack 或 CMDB 动态获取。
all:
children:
web:
hosts:
web-01:
ansible_host: 192.0.2.10
Playbook
- name: Configure web servers
hosts: web
become: true
tasks:
- name: Install nginx
ansible.builtin.package:
name: nginx
state: present
- name: Start nginx
ansible.builtin.service:
name: nginx
state: started
enabled: true
Role 与 Collection
Role 用固定目录组织 Tasks、Handlers、Templates、Defaults 和 Variables。Collection 用于分发模块、插件和角色。生产环境应固定依赖版本并审查第三方内容来源。
八、幂等性与可重复执行
幂等表示重复执行后系统保持同一目标状态。使用 package、user、template、service 等声明式模块通常比 shell 和 command 更容易保持幂等。
但 Ansible 并不会保证所有任务天然幂等。自定义脚本、数据库迁移、API 调用和无条件重启都可能每次产生变化。应正确设置 changed_when、failed_when、检查模式和 Handler。
Handler 只在被通知时执行,适合配置变化后重启服务。批量更新时可以使用 serial、健康检查和负载均衡摘除,避免同时中断所有节点。
九、Terraform 与 Ansible 如何衔接
典型流程如下:
- Terraform 创建网络、实例、磁盘、安全组和 DNS。
- Terraform 输出实例 IP、角色、环境和连接信息。
- 流水线将输出转换为动态 Inventory,或由 Ansible 直接查询云 API。
- Ansible 等待 SSH/WinRM 可用,配置主机和应用。
- 测试阶段验证端口、健康检查和业务请求。
- 成功后登记 CMDB、发布记录和监控标签。
不要通过大量 local-exec 或 remote-exec 把完整 Ansible 流程塞进 Terraform。Provisioner 难以重试、审计和单独复用,应该作为最后手段。
十、漂移与现有资源接管
漂移是实际资源与代码期望不一致。它可能来自控制台手工修改、自动扩缩容、其他工具或平台默认值变化。
治理方法包括:
- 定期运行只读 Plan 检测漂移;
- 限制生产控制台修改权限;
- 紧急修改后及时回写代码;
- 对平台自动管理的属性谨慎使用
ignore_changes; - 使用 Import Block 或导入命令逐步接管已有资源;
- 接管前确认不会触发意外替换或删除。
IaC 的权威来源应明确。代码、State、真实环境和 CMDB 之间出现差异时,团队必须有统一处理流程。
十一、CI/CD 流水线设计
一个相对完整的 Terraform 流水线包括:
- 格式检查和语法验证;
- Provider 与模块依赖锁定;
- 静态安全和合规扫描;
- 测试环境 Plan 或集成测试;
- 生产 Plan 生成与人工审批;
- 使用同一份已审批计划 Apply;
- 保存日志、结果、State 版本和审计信息。
Ansible 流水线还应包含 YAML/Lint、语法检查、角色测试、Check Mode、分批执行、健康检查和失败回滚或停止策略。
生产 Apply 不应由开发者笔记本随意执行。流水线应使用短期凭据、受保护分支、环境审批和最小权限执行身份。
十二、秘密管理
Terraform 变量标记为 sensitive 只会减少部分输出展示,不代表秘密不会进入 State。应尽量传递密钥引用而不是秘密本身,并使用云密钥服务、Vault 或流水线秘密存储。
Ansible Vault 可以加密变量文件,但解密密钥仍需安全管理。模板渲染、调试输出、失败堆栈和命令参数都可能泄露秘密,应使用 no_log 并限制日志访问。
十三、测试策略
基础设施代码也需要测试:
- 静态测试:格式、语法、Lint、安全规则和策略。
- 单元或模块测试:验证变量、输出和资源属性。
- 集成测试:在隔离账号或项目中创建真实资源并验证。
- 合约测试:检查网络、端口、DNS、证书和监控是否符合平台约定。
- 灾难恢复测试:验证从代码、State 备份和数据备份恢复环境。
“Plan 成功”只表示配置可计算,不表示业务一定可用。
十四、常见误区与局限
Terraform 不是通用脚本工具
它擅长管理具有 API 和生命周期的资源,不适合长时间编排每个操作系统步骤或数据库业务迁移。
Ansible 不是资源状态数据库
Ansible 通常不维护类似 Terraform 的持久 State。它适合将节点配置到目标状态,但资源销毁、依赖图和云资源生命周期不是其最强领域。
自动化不能替代架构设计
代码可以快速复制错误。网络、权限、备份、容量和故障域设计不合理时,自动化只会更快地产生问题。
多团队协作需要治理成本
模块版本、State 拆分、Provider 升级、策略例外和责任边界都需要平台团队长期维护。
十五、适用场景
- 公有云、OpenStack 和多云资源交付;
- Kubernetes 集群与节点基础设施;
- 网络、DNS、负载均衡和安全策略标准化;
- 大规模 Linux/Windows 主机配置;
- 中间件、监控 Agent 和应用部署;
- 灾难恢复环境重建和临时测试环境。
只有少量长期不变的主机时,可以从 Ansible 或简单 Terraform 模块开始,不必一次建设复杂平台。
十六、生产最佳实践
- 每个环境或责任域使用独立 State,控制爆炸半径。
- 使用远端 State、锁、加密、版本和备份。
- 固定 Provider、Module、Collection 和 Role 版本。
- 所有变更经过 Pull Request、Plan 和审批。
- 生产使用短期凭据与最小权限服务账号。
- 避免控制台漂移,紧急变更必须回写代码。
- 对销毁、替换和数据库资源设置额外保护策略。
- Terraform 与 Ansible 保持清晰职责边界。
- 定期演练 State 恢复、资源导入和环境重建。
十七、总结
Terraform 与 Ansible 并不是竞争关系。Terraform 负责“需要哪些基础资源以及它们如何关联”,Ansible 负责“主机和应用最终应处于什么配置状态”。将二者放入 Git、评审、策略、流水线和审计体系后,基础设施交付才能从个人经验转变为可重复的工程能力。
参考资料:
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)