什么是基础设施即代码(IaC)?核心优势和主流工具怎么选?
答案
基础设施即代码(Infrastructure as Code,IaC)是用代码而不是手动操作来定义、部署和管理 IT 基础设施的方式。把服务器、网络、存储这些原本靠运维人员点控制台或写脚本一个个创建的资源,全部用声明式或命令式的配置文件描述出来,交给工具自动化执行。
IaC 解决的核心问题是:基础设施的可重复性和一致性。当你在开发、测试、生产三套环境中分别手动配置 50 台服务器时,几乎不可能保证它们完全一样。而用 IaC,同样的代码跑出来的环境就是一样的,不管跑多少次。
IaC 的核心优势
- 环境一致性:同一份代码在任何环境产出相同的基础设施,彻底消除"在我机器上能跑"的问题
- 可版本控制:基础设施变更像代码提交一样有记录,谁改了什么、什么时候改的,一目了然,还能回滚
- 快速复制与销毁:几分钟创建一套完整环境,用完即删,临时测试环境不再是负担
- 自动化减少人为错误:手工操作 100 台机器出错概率远高于执行一份经过审查的配置代码
- 文档即代码:代码本身就是最准确的基础设施文档,不存在文档和实际不一致的情况
声明式 vs 命令式
这是 IaC 工具最根本的分类维度,选错范式比选错工具后果更严重。
声明式告诉系统"我要什么",不关心怎么到达那个状态。Terraform 写一个 aws_instance 资源描述期望的 EC2 配置,Terraform 自己算出需要调哪些 API、按什么顺序调。好处是即使中间执行中断,重跑一遍就能收敛到期望状态。
命令式告诉系统"做什么",步骤是写死的。Ansible Playbook 里 task 的顺序就是执行顺序,先装 Nginx 再启动服务。好处是逻辑直观、调试方便,坏处是步骤之间有隐式依赖,漏了一步后面可能全错。
实际项目中两者经常搭配使用:Terraform 负责创建基础设施(VPC、EC2、RDS),Ansible 负责在已创建的机器上配置软件和服务。
幂等性
幂等性是 IaC 的关键特性:同一份配置执行一次和执行十次,最终状态相同。Terraform 的 apply 无论跑多少次,只要配置没变,基础设施状态就不变。Ansible 的 apt 模块在 Nginx 已安装的情况下不会再装一遍。
没有幂等性,重试就是一个定时炸弹——你可能重复创建资源、重复写入配置,最终实际状态和期望状态越跑越远。
主流工具对比
Terraform
HashiCorp 出品的声明式 IaC 工具,当前行业事实标准。
- 用 HCL 语言描述资源,语法简洁,学习成本不高
- 通过 Provider 机制支持 AWS、GCP、Azure、阿里云等几乎所有云平台
- 状态文件(
terraform.tfstate)记录已管理的资源,是增量变更的基础 - 模块化设计让 VPC、数据库等基础设施可以像函数一样复用
hclresource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro" tags = { Environment = "production" } }
需要注意 Terraform 的状态管理是生产环境最大的运维风险点——状态文件损坏意味着 Terraform 失去对资源的追踪,所以务必使用远程状态存储(如 S3 + DynamoDB 锁)并开启状态加密。
Ansible
Red Hat 维护的命令式自动化工具,主打配置管理。
- 无 Agent 架构,通过 SSH 连接目标机器,不需要在远程装任何客户端
- YAML 格式的 Playbook,可读性强,上手快
- 模块丰富,覆盖系统配置、软件安装、网络设备管理
yaml- name: Deploy web server hosts: webservers become: yes tasks: - name: Install nginx apt: name: nginx state: present - name: Ensure nginx is running service: name: nginx state: started
Ansible 的短板在于大规模并发——SSH 串行执行在管理上千台机器时速度不理想,这时候通常需要配合 Ansible Tower / AWX 来做任务调度。
CloudFormation / CDK
AWS 原生方案。CloudFormation 用 JSON/YAML 模板,与 AWS 服务深度集成但只支持 AWS。CDK 用 TypeScript、Python 等语言编写,编译后生成 CloudFormation 模板,弥补了原模板语言表达能力弱的缺点。
选 CloudFormation 的理由通常只有一个:组织深度绑定 AWS 生态,且不想引入第三方工具的授权和合规成本。
Pulumi
允许用 TypeScript、Python、Go 等通用编程语言写 IaC,不像 HCL 那样需要学新语法。对于开发团队来说,能复用现有的语言生态和工具链(IDE 提示、单元测试、包管理)是个实实在在的优势。但在运维主导的团队里,HCL 的声明式约束反而更安全——不容易写出带复杂逻辑的"意大利面条式"基础设施代码。
Terraform 和 Ansible 怎么配合?
这是面试中最高频的追问方向。典型分工:
- Terraform 创建云资源(VPC、子网、安全组、EC2 实例、RDS 数据库)
- Terraform 通过
remote-exec或输出实例 IP 到 inventory 文件 - Ansible 拿到 inventory 后在实例上安装软件、配置服务、注入环境变量
也可以用 Terraform 的 local-exec 在资源创建后直接触发 Ansible Playbook,实现一条命令从零到完整服务上线。
配置漂移怎么处理?
配置漂移指实际基础设施状态和代码定义的期望状态不一致,通常因为有人手动改了控制台或者临时脚本绕过了 IaC 流程。
Terraform 的应对方式:
terraform plan会检测漂移,显示实际状态和期望状态的差异terraform apply会将漂移的资源拉回期望状态- 生产环境建议开启漂移检测定时任务(如每天
terraform plan),一旦发现非预期变更立即告警
更根本的做法是限制控制台权限,让所有变更只能通过代码提交触发,这就是 GitOps 的思路。
IaC 落地的坑
- 状态文件管理:Terraform 状态文件包含敏感信息且是单点故障源,必须远程存储、加密、加锁、定期备份
- 密钥管理:数据库密码、API Key 绝不能明文写在代码里,用 Vault 或云厂商的 Secrets Manager
- 模块粒度:拆太细管理成本高,拆太粗一个模块管所有资源,变更影响面太大。经验是按业务域拆分,比如网络模块、数据库模块、应用模块
- 测试成本:IaC 测试不像应用代码那样跑个单测就行,通常需要
terraform plan预检 + 真实环境的集成测试,成本不低
追问
Q: Terraform 的状态锁定是什么?为什么需要?
状态锁定防止多人同时操作同一套基础设施。如果两个人同时 terraform apply,可能出现一个基于旧状态创建资源、另一个基于同样旧状态删除资源的情况,导致实际状态混乱。DynamoDB 等后端支持自动加锁,apply 期间其他操作会被阻塞。
Q: 不可变基础设施和 IaC 是什么关系?
不可变基础设施的核心思想是部署后不修改,需要变更就替换整个实例。IaC 天然支持这种模式——Terraform 修改 EC2 的 ami 或 instance_type 时,默认行为就是销毁旧实例、创建新实例。这种"换而不是改"的方式避免了配置漂移的累积,和 IaC 的声明式理念高度契合。
Q: 怎么在 IaC 流程中做安全合规?
在 CI 流水线中集成安全扫描工具:tfsec 检查 Terraform 配置中的安全风险(如公开的 S3 Bucket),checkov 做策略合规检查,terraform plan 的输出可以做审批门控——高风险变更(如删除数据库)必须人工确认后才能 apply。