1. 课程导入与漂移认知
在开始学习 Terraform 配置漂移检测与修复之前,先建立一个清晰的认知:Terraform 的核心价值在于用代码描述基础设施的期望状态,并通过 terraform apply 让真实环境收敛到这个期望状态。但真实世界并不会停在那一刻。当有人通过云控制台手动改了一个安全组规则、当自动扩缩容调整了实例数量、当某个运维脚本临时修改了标签,代码里记录的期望状态与云端实际状态之间就会出现偏差。这种偏差,就是配置漂移(Configuration Drift)。
更准确地说,配置漂移是指 Terraform 状态文件(terraform.tfstate)或 Terraform 配置所声明的资源属性,与云平台上资源的真实属性之间出现了不一致。它可能表现为三种形态:一是配置与状态不一致,例如有人直接改了 .tf 文件但没执行 apply;二是状态与真实资源不一致,例如控制台手动删除了一个 RDS 实例,但 state 里还记录着它;三是配置与真实资源不一致,例如代码里写的是 instance_type = "t3.medium",而实际运行的是 t3.large。理解这三种不一致,是后续检测与修复的起点。
漂移的本质: Terraform 的期望状态(配置 + state)与云平台实际状态之间的差异。检测漂移,就是发现差异;修复漂移,就是让三者重新对齐。
漂移的成因非常多样,常见的有以下几类。第一类是人工干预:运维人员在紧急排障时直接登录控制台修改安全组、扩容磁盘或调整负载均衡权重,事后忘记回写到 Terraform 代码。第二类是外部系统自动变更:自动扩缩容组根据负载调整实例数、云厂商的自动修复策略替换了不健康的实例、合规扫描工具自动修改了加密配置。第三类是代码与状态脱节:团队成员在本地修改了 .tf 文件但未提交,或者多人并行 apply 导致状态覆盖。第四类是Provider 或 API 行为变化:云厂商升级 API 后,某些默认值或字段行为发生改变,导致 plan 时出现非预期的 diff。第五类是资源被外部删除或重建:例如有人手动删除了一个 S3 桶,或者云平台因欠费回收了资源。
漂移对基础设施稳定性的影响不容小觑。最直接的后果是下一次 apply 变得不可预测:你可能以为只是改一个标签,结果 Terraform 计划销毁并重建整个数据库实例。其次,漂移会破坏环境一致性:开发、测试、生产环境本应同构,但漂移让它们逐渐分叉,导致“在我机器上能跑”的经典问题。第三,漂移会削弱审计与合规能力:安全组被手动放开 0.0.0.0/0,但代码里没有记录,审计时无法追溯。第四,漂移会增加故障排查成本:当服务异常时,你无法确定当前运行状态到底由代码控制还是被人为修改过。
因此,检测与修复漂移不是一次性的任务,而是一个持续的工作流。这个工作流可以概括为四个阶段:发现、评估、修复、预防。发现阶段通过 terraform plan、terraform refresh 或第三方工具(如 driftctl、Terratest)识别差异;评估阶段判断差异是预期的还是意外的,是紧急的还是可延后的;修复阶段通过 terraform apply 让真实资源回归期望状态,或者反向更新代码以接纳合理的手动变更;预防阶段通过 CI/CD 流水线、策略即代码(如 Sentinel、OPA)和定期巡检减少漂移发生。
为了更具体地理解漂移检测,我们来看一个典型场景。假设你用 Terraform 创建了一台 EC2 实例,配置如下:
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.medium"
tags = {
Name = "web-server"
Environment = "production"
}
}
执行 terraform apply 后,state 中记录了实例 ID i-0abc123,真实资源运行的是 t3.medium。三天后,运维人员因为流量突增,在控制台把实例类型改成了 t3.large,并添加了一个临时标签 TempFix = "true"。此时,如果你执行 terraform plan,Terraform 会对比配置、state 和真实资源,输出类似以下的 diff:
~ instance_type = "t3.medium" -> "t3.large"
tags = {
+ TempFix = "true"
}
注意,plan 的输出方向是“从当前真实状态到配置期望状态”的变更计划。也就是说,Terraform 打算把 t3.large 改回 t3.medium,并移除 TempFix 标签。如果你直接执行 terraform apply,就会触发一次实例类型变更,这可能导致实例重启,影响线上服务。这就是漂移带来的风险:一个看似无害的手动修改,可能在下一次 apply 时引发非预期的停机。
注意: terraform plan 默认会刷新 state 以获取真实资源的最新属性,但刷新行为受 -refresh=false 参数影响。在生产环境中,建议先执行 terraform plan -refresh-only 来专门检测漂移,而不是直接 apply。
那么,面对漂移,我们应该如何决策?这里给出一个实用的判断框架。首先,问自己:这个手动变更是否合理?如果合理(例如紧急扩容),那么正确的修复方向是反向更新代码,把 t3.large 和 TempFix 标签写回 .tf 文件,然后执行 terraform apply 让 state 与代码对齐。如果手动变更不合理(例如误操作放开了安全组),那么正确的修复方向是让真实资源回归代码,直接执行 terraform apply 覆盖手动修改。其次,问自己:这个漂移是否紧急?如果涉及安全或合规,应立即修复;如果只是标签差异,可以纳入下一次迭代。
为了系统化地管理漂移,建议在团队中建立以下实践。第一,定期执行漂移检测:在 CI/CD 流水线中设置定时任务,每天或每周执行 terraform plan -refresh-only -detailed-exitcode,当退出码为 2 时表示存在漂移,触发告警。第二,限制控制台写权限:通过 IAM 策略限制运维人员直接修改生产资源,强制所有变更走 Terraform 流水线。第三,使用策略即代码:通过 Sentinel 或 OPA 定义规则,例如“禁止手动修改生产环境安全组”,在 plan 阶段拦截违规变更。第四,记录漂移事件:每次发现漂移后,记录变更内容、原因、修复方式和责任人,形成知识库,帮助团队识别高频漂移点。
最后,需要明确一个观念:漂移不可能被完全消除。云平台的自动行为、紧急故障处理、第三方工具的介入,都会持续产生漂移。我们的目标不是追求零漂移,而是让漂移可见、可控、可修复。通过建立检测机制、明确修复策略、完善预防措施,团队可以在享受 Terraform 声明式管理红利的同时,保持对基础设施真实状态的掌控力。接下来的章节,我们将深入讲解 terraform plan 的漂移检测原理、terraform refresh 与 import 的使用场景、以及如何编写自动化漂移巡检脚本。