4. 基础设施即代码入门
在持续交付体系中,工作区、集群、作业和权限如果依赖人工在 UI 上点击创建,就会出现“环境漂移”:开发环境能跑、生产环境缺一个权限或集群配置不同,导致发布失败。基础设施即代码(Infrastructure as Code,IaC)的核心思想是:把这些资源写成版本化的声明文件,由工具负责计算差异并执行变更。本节围绕 Databricks 场景,讲清 Terraform 与 Databricks Asset Bundles(DAB)两种主流方式的定位、写法与协作关系。
一、两种 IaC 工具的分工
Terraform 由 HashiCorp 提供,通过 Databricks Provider 管理“平台侧资源”:工作区、集群策略、实例池、用户与组、服务主体、权限授权(如 databricks_permissions)、Unity Catalog 的 catalog/schema 等。它的状态文件(state)记录了资源与真实环境的映射,适合管理生命周期长、跨云、跨服务的底层设施。
Databricks Asset Bundles 是 Databricks 官方推出的打包与部署工具,基于 databricks.yml 描述“数据与 AI 项目侧资源”:作业(job)、流水线(pipeline)、模型服务、以及作业所依赖的 notebook、Python wheel、配置文件。它天然支持多目标(dev/staging/prod)、变量覆盖和 databricks bundle deploy 一键部署,更贴近数据工程师的日常交付。
实践中常见的组合是:Terraform 负责工作区、集群策略、Unity Catalog 与权限等“地基”,DAB 负责作业与流水线等“上层应用”。两者通过集群策略 ID、服务主体、catalog 名称等参数衔接。
二、Terraform 声明式管理示例
下面示例用 Terraform 创建一个集群策略、一个服务主体,并把作业运行权限授予该服务主体。示例参数为教学假设值,实际使用时需替换为你的工作区地址与主体 ID。
terraform {
required_providers {
databricks = { source = "databricks/databricks", version = "~> 1.50" }
}
backend "s3" {
bucket = "corp-tfstate"
key = "databricks/prod/terraform.tfstate"
region = "cn-north-1"
}
}
provider "databricks" {
host = var.workspace_url
}
resource "databricks_cluster_policy" "etl_policy" {
name = "etl-standard-policy"
definition = jsonencode({
"spark_version" = { "type" = "fixed", "value" = "14.3.x-scala2.12" },
"node_type_id" = { "type" = "allowlist", "values" = ["i3.xlarge", "i3.2xlarge"] },
"autoscale.min_workers" = { "type" = "range", "minValue" = 2, "maxValue" = 8 },
"custom_tags.team" = { "type" = "fixed", "value" = "data-eng" }
})
}
resource "databricks_service_principal" "etl_sp" {
display_name = "sp-etl-prod"
}
resource "databricks_permissions" "job_run" {
job_id = var.etl_job_id
access_control {
service_principal_name = databricks_service_principal.etl_sp.application_id
permission_level = "CAN_MANAGE_RUN"
}
}
执行流程为:terraform init 初始化后端与 Provider,terraform plan 输出将要新增/修改/销毁的资源清单,确认无误后 terraform apply 落地。若把 autoscale.max_workers 的 maxValue 从 8 改为 12,plan 会显示该策略的原地更新(update in-place),apply 后工作区策略即时生效,无需重建集群。
三、DAB 声明式管理示例
DAB 用一份 databricks.yml 描述作业及其多环境差异。下面示例定义一个每日 ETL 作业,dev 使用单节点、prod 使用自动伸缩集群,并引用 Terraform 创建的策略。
bundle:
name: daily-etl
variables:
cluster_policy_id:
description: 由 Terraform 输出的集群策略 ID
targets:
dev:
workspace:
host: https://dev-workspace.cloud.databricks.com
variables:
cluster_policy_id: "D0A1B2C3D4E5F6"
prod:
workspace:
host: https://prod-workspace.cloud.databricks.com
variables:
cluster_policy_id: "F6E5D4C3B2A1D0"
resources:
jobs:
daily_etl_job:
name: "daily-etl-${bundle.target}"
schedule:
quartz_cron_expression: "0 0 2 * * ?"
timezone_id: "Asia/Shanghai"
job_clusters:
- job_cluster_key: etl_cluster
new_cluster:
policy_id: ${var.cluster_policy_id}
spark_version: "14.3.x-scala2.12"
num_workers: 2
tasks:
- task_key: ingest
job_cluster_key: etl_cluster
notebook_task:
notebook_path: ./src/ingest.py
部署命令为 databricks bundle validate 校验语法与变量,databricks bundle deploy -t prod 上传源码并创建/更新作业,databricks bundle run daily_etl_job -t prod 触发一次运行。DAB 会在工作区中维护部署状态,重复 deploy 是幂等的。
四、权限与状态管理要点
权限声明要遵循最小权限原则:作业执行用服务主体而非个人账号,避免人员离职导致作业中断;目录与表权限通过 databricks_grants 或 databricks_permissions 显式声明,不要依赖 UI 手工授权。Terraform state 必须放远程后端并开启锁,禁止把 state 提交到 Git;DAB 的部署状态由工作区托管,但源码与 databricks.yml 必须进 Git。
掌握本节内容后,你应能判断哪些资源交给 Terraform、哪些交给 DAB,并写出可版本化、可评审、可回滚的声明式配置,为后续的持续交付流水线打下基础。