4. 基础设施即代码入门

在 Confluent DataOps 的持续交付链路中,基础设施即代码(Infrastructure as Code,IaC)解决的是“环境与资源如何被可重复地创建、变更和销毁”的问题。Confluent Cloud 上的环境(Environment)、集群(Cluster)、服务账号(Service Account)、ACL、Topic 与 Schema 都是可被 API 管理的资源,Terraform 通过 Provider 把这些资源抽象为声明式配置:你描述“最终状态”,Terraform 负责计算差异并调用 Confluent Cloud API 完成收敛。

理解 Terraform 管理 Confluent Cloud 的关键,是分清两类对象:控制面资源(环境、集群、服务账号、角色绑定、ACL)和数据面资源(Topic、Schema、Schema 兼容性配置)。控制面资源决定“谁能在哪个集群上做什么”,数据面资源决定“数据以什么结构流动”。二者在 Terraform 中都属于同一份状态文件(state),但生命周期与变更风险不同:改 ACL 可能立即影响生产读写,改 Topic 分区数通常不可逆,改 Schema 兼容性可能阻断生产者。

Terraform 的声明式并不等于“随便改”。对 Confluent Cloud 而言,删除集群、缩减分区、收紧 ACL 都属于高风险变更,必须结合 terraform plan 的输出逐条确认。

Provider 与认证:先让 Terraform 能“说话”

Confluent Cloud 的 Terraform Provider 需要两类凭据:Cloud API Key(管理组织级资源,如环境、集群、服务账号)和集群 API Key(管理集群内资源,如 Topic、ACL)。推荐做法是把 Cloud API Key 通过环境变量注入,而不是写进代码:

export CONFLUENT_CLOUD_API_KEY="CCLOUD_API_KEY_示例"
export CONFLUENT_CLOUD_API_SECRET="CCLOUD_API_SECRET_示例"

# provider.tf
terraform {
  required_providers {
    confluent = {
      source  = "confluentinc/confluent"
      version = "~> 2.0"
    }
  }
}

provider "confluent" {
  # 从环境变量读取,避免密钥入库
}

这里的环境变量名是示例约定,实际以 Provider 文档为准。核心原则是:密钥不进入 Git,不进入 state 的明文可读字段。state 中会保存资源属性,因此远程后端(如 S3 + DynamoDB 锁)应开启加密与访问控制。

用声明式配置描述一条最小可用链路

下面是一段教学示例,展示从环境到 Topic 的声明式定义。参数值均为示例,实际使用时需替换为你的组织 ID、区域与命名规范。

resource "confluent_environment" "dev" {
  display_name = "dataops-dev"
}

resource "confluent_kafka_cluster" "standard" {
  display_name = "dataops-dev-kafka"
  availability = "SINGLE_ZONE"
  cloud        = "AWS"
  region       = "us-east-1"
  standard {}

  environment {
    id = confluent_environment.dev.id
  }
}

resource "confluent_service_account" "app_producer" {
  display_name = "svc-order-producer"
  description  = "订单事件生产者"
}

resource "confluent_kafka_topic" "orders" {
  kafka_cluster {
    id = confluent_kafka_cluster.standard.id
  }
  topic_name       = "orders.created.v1"
  partitions_count = 6
  rest_endpoint    = confluent_kafka_cluster.standard.rest_endpoint

  credentials {
    key    = var.cluster_api_key
    secret = var.cluster_api_secret
  }
}

这段配置体现了 Terraform 的依赖推导:confluent_kafka_cluster.standard.id 被 Topic 引用,Terraform 会先建集群再建 Topic。若把 partitions_count 从 6 改为 12,plan 会显示原地更新;若改为 3,Confluent Cloud 不允许缩减分区,plan 阶段或 apply 阶段会报错——这正是“声明式也要懂约束”的典型场景。

ACL 与 Schema:把治理也纳入版本控制

服务账号创建后本身没有权限,需要 ACL 或 RBAC 角色绑定。以 ACL 为例,生产者需要 WRITE 与 DESCRIBE,消费者需要 READ 与 DESCRIBE。用 Terraform 表达时,通常按“主体 + 资源 + 操作”三元组逐条声明:

resource "confluent_kafka_acl" "producer_write" {
  kafka_cluster { id = confluent_kafka_cluster.standard.id }
  resource_type = "TOPIC"
  resource_name = "orders.created.v1"
  pattern_type  = "LITERAL"
  principal     = "User:${confluent_service_account.app_producer.id}"
  host          = "*"
  operation     = "WRITE"
  permission    = "ALLOW"
  rest_endpoint = confluent_kafka_cluster.standard.rest_endpoint
  credentials {
    key    = var.cluster_api_key
    secret = var.cluster_api_secret
  }
}

Schema 侧则通过 Schema Registry 资源声明 subject 与兼容性。例如为 orders.created.v1-value 注册 Avro Schema,并设置 BACKWARD 兼容性。这样,Schema 变更也走 MR/PR 评审,而不是在控制台里“手改一下”。

工作流:plan 是评审对象,apply 是执行动作

把上述资源放进同一目录后,标准工作流是 terraform init → terraform plan -out=tfplan → 人工评审 → terraform apply tfplan。在 CI 中,plan 输出可作为 MR 评论附件,让 Reviewer 看到“将新增 1 个 Topic、修改 2 条 ACL、无销毁”。若 plan 出现 destroy,必须显式确认,必要时用 prevent_destroy = true 保护集群与关键 Topic。

Terraform 声明式管理 Confluent Cloud 资源关系 声明式配置(.tf) environment / cluster service_account / acl topic / schema 期望状态(Desired State) State 状态文件 记录已创建资源 ID 与属性 远程后端 + 加密 + 锁 禁止明文密钥入库 Terraform 引擎 init → plan → apply 差异计算(Diff) 依赖图排序 Confluent Cloud 控制面 Environment · Cluster · Service Account · ACL 数据面 Topic · Schema Registry Subject 高风险变更 删集群 · 缩分区 · 收紧 ACL · 改兼容性 API 调用 POST /environments POST /clusters/{id}/topics POST /acls · /subjects 变更评审闭环: terraform plan 输出 → MR 评审 → 确认无 destroy → apply → 验证资源状态 保护措施:prevent_destroy · 远程 state 锁 · 密钥环境变量注入 · 按环境分目录/工作区

目录与工作区:让 dev / staging / prod 不互相污染

常见做法是按环境拆分目录,例如 envs/dev、envs/prod,各自引用 modules/confluent-kafka 模块。模块内定义变量 environment_name、cluster_name、topic_specs,环境目录只传参。这样 dev 与 prod 的差异被收敛到变量文件,而不是复制粘贴两份资源定义。若使用 Terraform Workspace,则要确保 state 隔离,避免误在 prod 工作区执行 dev 的 plan。

实操检查清单

检查项判断依据不通过时的处理
密钥是否入库Git 历史中无 API Key/Secret 明文轮换密钥,改用环境变量或 Vault
plan 是否含 destroyplan 输出中无 -/+ destroy 关键资源加 prevent_destroy 或拆分变更
Topic 分区是否可逆新分区数 ≥ 当前值不可缩减,需新建 Topic 迁移
ACL 是否最小权限principal 仅绑定所需 operation移除通配 * 资源名
Schema 兼容性与现有消费者兼容策略一致先评估再改,避免阻断生产

把上述流程固化到 CI 后,Confluent Cloud 的资源变更就具备了可审计、可回滚、可复现的基础。下一步才是把 Terraform 与 CI/CD 流水线结合,让 plan 成为合并请求的必过门禁。