为什么 GitFlow 在基础设施上失败

发布: (2025年12月10日 GMT+8 04:02)
6 min read
原文: Dev.to

Source: Dev.to

TL;DR

在 Terraform 中使用 GitFlow(长期特性或环境分支)往往会导致 状态漂移 和脆弱的流水线。与应用代码不同,基础设施即代码(IaC)还有第三维——状态——它无法通过 git merge 合并。

制胜策略: 使用 基于主干的开发(Trunk‑Based Development)。把 main 当作唯一的真相来源。通过注入环境特定的变量(.tfvars),在环境之间(Dev → Stage → Prod)提升 相同的 代码提交,而不是在环境分支之间合并代码。

核心问题:“第三维”

在标准的应用开发中,你管理两个主要维度:

  • 代码: Git 中的逻辑。
  • 构建: 在服务器上运行的产物。

如果代码在 Git 中可以工作,通常构建也能正常运行。

在 Terraform 中还有第三个、占主导地位的维度:状态terraform.tfstate)。
状态将你的 Git 配置映射到 AWS/Azure/GCP 的真实 API。即使你把状态远程存储(S3、Terraform Cloud)以避免 JSON 合并冲突,也无法仅靠 Git 解决 逻辑分歧

当你在 Terraform 中使用 GitFlow 时,就把代码和状态解耦了。

GitFlow 陷阱:“状态踩踏”和“幽灵”

一种常见的反模式是把 Git 分支映射到环境:

  • feature/new-db → 沙箱
  • dev → 开发
  • main → 生产

场景

设想两位 DevOps 工程师 Alice 和 Bob 同时在不同特性上工作。

  • Alicedevelop 分出 feature/add-redis 分支。她添加一个 Redis 集群并部署到沙箱环境进行测试。
  • Bobdevelop 分出 feature/resize-vpc 分支。他修改 VPC CIDR 并部署到 同一个 沙箱环境(或另一个)。

因为 Terraform 按 地址 在状态文件中跟踪资源,Alice 和 Bob 现在处于竞争状态。

Mermaid Diagram

后果

当 Alice 或 Bob 最终合并回 develop 时,他们只是在合并文本文件。Git 无法合并 实时的基础设施状态。于是会出现“干净”的 Git 历史,却与云提供商的混乱现实相矛盾,导致下一次部署时很可能失败。

  • 共享环境风险(状态踩踏): 他们的锁相互覆盖或因状态文件与分支不同步而覆盖资源。
  • 独立环境风险(幽灵基础设施): 如果特性分支在动态环境中创建了资源,合并后删除分支却没有运行 terraform destroy,这些资源会继续在云上运行,成为“孤儿”,每月计费却不在任何代码库中。

解决方案:基于主干的开发

在基于主干的开发(TBD)中,main 上的每一次提交都可能被部署。不要维护长期分支。

工作流

不再通过在分支之间移动代码来提升(例如把 dev 合并到 prod),而是 提升产物。在 Terraform 中,“产物”就是你的模块代码加上特定的提交 SHA。

所有环境使用 相同的代码,仅更改 输入变量

流水线架构

Mermaid Diagram

实际实现

将仓库结构划分为逻辑基础设施(代码)和环境配置(变量)两部分。

目录结构

/my-infra
  /modules
    /vpc
    /k8s
  main.tf          # 通用入口点
  variables.tf     # 仅定义变量
  config/
    dev.tfvars     # 开发环境特定值(例如 instance_type = "t3.micro")
    prod.tfvars    # 生产环境特定值(例如 instance_type = "m5.large")

CI/CD 命令逻辑

开发阶段

# 使用后端配置(通常是部分配置)进行初始化
terraform init -backend-config="bucket=my-tf-state-dev"

# 使用该环境的特定变量进行计划
terraform plan -var-file="config/dev.tfvars" -out=tfplan

# 严格按照计划执行
terraform apply tfplan

生产提升

# 同样的代码,不同的状态后端和变量
terraform init -backend-config="bucket=my-tf-state-prod"
terraform plan -var-file="config/prod.tfvars" -out=tfplan
terraform apply tfplan

为什么更安全

  • 不可变性: 在开发中测试通过的 Terraform 代码就是在生产中运行的代码。不存在 Dev 与 Prod 分支之间的“糟糕合并”。
  • 状态隔离: 开发和生产拥有完全独立的状态文件(由后端配置决定),互不干扰。
  • 快速反馈: 若提交在开发阶段失败,流水线会中止,永远不会进入生产。

例外:共享模块

在 Terraform 中有一个特定领域需要使用 语义化版本 …(内容续)

Back to Blog

相关文章

阅读更多 »