如何根据部署环境动态修改Databricks Notebook中的变量?
一、不用Databricks CLI的动态变量替代方案
以下几种方案均可实现环境变量的动态注入,全程通过Terraform或Databricks原生能力完成,无需CLI操作:
1. Terraform模板渲染生成Notebook
将Notebook编写为模板文件(例如s3_migration_notebook.ipynb.tpl),用占位符标记需动态替换的变量(如${s3_bucket_name}、${aws_account_id})。在Terraform中通过templatefile函数,根据当前部署环境(由var.environment参数传入DEV/QA/PROD)渲染对应环境的Notebook内容,再通过databricks_notebook资源部署。
示例Terraform代码片段:
resource "databricks_notebook" "s3_migration" { path = "/${var.environment}/s3_migration" language = "PYTHON" content_base64 = base64encode(templatefile("${path.module}/templates/s3_migration_notebook.ipynb.tpl", { s3_bucket_name = var.s3_bucket_name aws_account_id = var.aws_account_id })) }
2. 注入Databricks环境变量
通过Terraform配置Databricks的Workspace级或Cluster级环境变量,Notebook直接读取这些变量即可:
- Cluster级:在
databricks_cluster资源的spark_env_vars块中定义环境变量,不同环境传入对应值 - Workspace级:用
databricks_workspace_conf资源设置全局环境变量(适合跨集群共享的配置)
Notebook读取示例(Python):
import os s3_bucket = os.environ.get("S3_MIGRATION_BUCKET") aws_account = os.environ.get("AWS_TARGET_ACCOUNT")
3. Terraform直接管理Databricks Secrets
无需CLI,直接通过Terraform的databricks_secret_scope和databricks_secret资源创建密钥与密钥范围,Notebook中用dbutils.secrets.get()读取即可,全程由Terraform代码管控。
示例Terraform代码:
resource "databricks_secret_scope" "s3_migration" { name = "${var.environment}-s3-migration-scope" } resource "databricks_secret" "s3_bucket" { scope = databricks_secret_scope.s3_migration.name key = "s3-bucket-name" string_value = var.s3_bucket_name }
Notebook读取示例:
import os s3_bucket = dbutils.secrets.get(scope=f"{os.environ.get('ENV')}-s3-migration-scope", key="s3-bucket-name")
二、Terraform控制Notebook的特定代码单元
Terraform本身没有直接“控制代码单元”的功能,但可通过以下方式实现类似需求:
拆分模板片段拼接:将Notebook中不同环境需调整的代码单元拆为单独模板文件(如
dev_data_filter.tpl、prod_data_filter.tpl),Terraform根据当前环境变量选择对应片段,通过templatefile和字符串拼接生成完整Notebook内容。模板内嵌条件判断:在Notebook模板中加入Terraform条件逻辑,根据环境变量渲染不同代码单元。示例模板片段:
<% if var.environment == "prod" %> # PROD环境专属逻辑:全量同步数据 sync_full_dataset() <% else %> # DEV/QA环境专属逻辑:同步测试子集 sync_test_subset() <% endif %>
- 字符串替换修改代码块:将Notebook内容作为字符串处理,用Terraform的
replace函数定位特定代码单元并替换内容。例如替换代码块中的变量值或逻辑:
content_base64 = base64encode(replace( file("${path.module}/notebooks/s3_migration_base.ipynb"), "#__ENV_SPECIFIC_LOGIC__", var.environment == "prod" ? "sync_full_dataset()" : "sync_test_subset()" ))
内容的提问来源于stack exchange,提问作者wookash

