1. 课程导入与工程全景

在传统运维模式中,基础设施的创建往往依赖工程师登录控制台手工点击,或通过脚本零散执行。这种方式在资源规模小、变更频率低时勉强可用,但一旦团队扩张、环境增多,就会暴露出三个致命问题:环境漂移(测试环境与生产环境配置不一致)、变更不可追溯(谁在什么时候改了安全组规则无从查证)、回滚困难(手工操作出错后难以快速恢复)。Terraform CI/CD 基础设施交付工程,正是为解决这些问题而生的工程实践体系。

它的核心定义可以概括为:以 Terraform 作为基础设施即代码(IaC)的声明式引擎,将基础设施的变更纳入版本控制,并通过持续集成与持续交付流水线,实现基础设施从代码提交到多环境部署的自动化、可审计、可回滚的交付过程。这里的关键词有三个:声明式、版本化、流水线化。声明式意味着我们描述"期望的最终状态"而非"执行步骤";版本化意味着每一次基础设施变更都有对应的 Git 提交记录;流水线化意味着变更经过自动化的校验、计划、审批与执行,而非人工手动操作。

为什么需要把 Terraform 放进 CI/CD

很多人会问:Terraform 本身已经能通过 terraform apply 完成部署,为什么还要套一层 CI/CD?答案在于协作与风险控制。当多人同时操作同一份基础设施时,本地执行会带来状态文件冲突、凭据泄露、误操作生产环境等风险。把 Terraform 放进流水线后,可以获得以下工程价值:

  • 一致性:所有环境使用同一份代码和同一套模块,消除手工差异。
  • 可审计:每次 plan 与 apply 的结果都留存在流水线日志中,配合 Git 历史形成完整审计链。
  • 可回滚:基础设施变更以代码提交为单位,回滚即回退提交并重新执行流水线。
  • 安全隔离:云凭据存放在 CI 系统的密钥管理中,工程师本地无需持有生产凭据。
  • 审批可控:生产环境的 apply 可设置人工审批门禁,防止误触发。

典型交付流水线全景

一条完整的 Terraform 基础设施交付流水线,通常包含以下阶段:代码提交触发 → 格式与静态检查 → 安全扫描 → terraform init 与 validate → terraform plan 生成变更计划 → 人工审批(生产环境)→ terraform apply 执行变更 → 结果验证与通知。下图展示了这条流水线的信号与数据流向,以及各阶段的关键产物。

Terraform CI/CD 基础设施交付流水线全景 代码提交 Git Push / PR 格式与静态检查 fmt / validate tflint 安全扫描 tfsec / checkov 敏感信息检测 变更计划 terraform plan 生成 plan 文件 人工审批 生产环境门禁 执行变更 terraform apply 应用 plan 文件 结果验证 健康检查 输出值核对 通知与归档 Slack / 邮件 日志留存 审批通过 远程状态后端 S3 + DynamoDB 状态锁与版本 读写状态 关键产物与判断依据 • plan 文件:记录本次变更将新增/修改/销毁的资源清单,是审批的核心依据 • 状态文件:Terraform 记录真实资源与代码映射的唯一来源,必须远程存储并加锁 • 流水线日志:包含每次执行的完整输出,是审计与排障的第一手资料 • 审批记录:生产环境变更的人工确认痕迹,满足合规要求

学习路径与工程能力地图

掌握 Terraform CI/CD 交付工程,需要沿着一条由浅入深的路径推进。本课程将围绕以下能力层次展开:

第一层:Terraform 语言与核心工作流。理解 HCL 语法、资源与数据源、变量与输出、模块化设计,以及 init / plan / apply / destroy 四步工作流的内部机制。这是所有后续工程实践的地基。

第二层:状态管理与远程后端。状态文件是 Terraform 的"记忆",必须理解本地状态与远程状态的差异、状态锁的作用、状态迁移与导入的操作方式。生产环境中,状态文件绝不能放在工程师本地磁盘上。

第三层:CI/CD 流水线设计。将 Terraform 命令编排进流水线,设计触发条件、阶段划分、缓存策略、审批门禁与失败处理。这一层需要同时理解 Terraform 和 CI 平台(如 GitHub Actions、GitLab CI、Jenkins)的能力边界。

第四层:多环境与模块化交付。使用目录结构或工作区隔离 dev / staging / prod 环境,通过模块复用基础设施定义,利用变量文件区分环境参数。这是从"能跑"到"可维护"的关键跨越。

第五层:安全、合规与可观测性。密钥管理、策略即代码(如 Sentinel、OPA)、漂移检测、成本预估与变更通知。这一层决定了基础设施交付能否在真实企业中长期稳定运行。

学习建议:本课程强调"可执行"。建议在本地或云上准备一个可用的云账号(或使用 LocalStack 等模拟环境),跟随每节的示例动手执行。Terraform 的很多坑——状态锁冲突、provider 版本不兼容、plan 与 apply 结果不一致——只有亲手遇到并解决,才能真正内化。

一个最小可运行的起点

为了建立直观感受,下面给出一个最小的 Terraform 配置示例。它声明了一个 AWS S3 存储桶,并输出其 ARN。虽然简单,但它包含了 Terraform 工程的基本要素:provider 声明、资源定义、输出定义。

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.region
}

variable "region" {
  type    = string
  default = "ap-southeast-1"
}

resource "aws_s3_bucket" "demo" {
  bucket = "tf-cicd-demo-bucket-2024"
  tags = {
    Environment = "dev"
    ManagedBy   = "terraform"
  }
}

output "bucket_arn" {
  value = aws_s3_bucket.demo.arn
}

执行 terraform init 后,Terraform 会下载 AWS provider 插件;执行 terraform plan,会输出类似 Plan: 1 to add, 0 to change, 0 to destroy 的摘要;执行 terraform apply 并确认后,存储桶被创建,终端打印出 bucket_arn 的值。这个"计划—确认—执行"的节奏,正是后续所有 CI/CD 流水线要自动化的核心动作。

当这个最小示例被放入流水线后,plan 的输出会成为审批依据,apply 会在受控环境中执行,状态文件会被推送到远程后端,整个过程留下完整的日志与审计记录。从本地命令到工程化交付,中间隔着的正是本课程要系统讲解的整套实践体系。