ZenML + Terraform 基础设施即代码实践:从组件化 Stack 架构到多环境隔离
2026/9/18 22:01:44 网站建设 项目流程

ZenML + Terraform 基础设施即代码实践:从组件化 Stack 架构到多环境隔离

【免费下载链接】zenmlZenML 🙏: One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml

导读

本文基于 ZenML 官方最佳实践文档,系统讲解如何用 Terraform 官方 ZenML Provider 以基础设施即代码(IaC)的方式架构一套可支撑多团队、多环境、安全合规的 ML 基础设施。读完本文,你将掌握如何把 ZenML 的 Stack 组件抽象与 Terraform 资源建模一一映射,落地"组件化基础栈 + 环境感知认证 + 项目级资源共享与隔离"三套核心模式,以及组件版本化、服务连接器治理、配置合并、状态文件隔离等高级管理实践,并了解如何在仓库中对应的官方 Terraform 部署文档与基础设施即代码指南基础上进一步深入。

挑战:可扩展 ML 基础设施的架构难题

作为系统架构师,你要搭建一套可扩展的 ML 基础设施,需要同时满足:

  • 支撑多个需求各异、互不干扰的 ML 团队;
  • 在多个环境(dev、staging、prod)之间保持一致的工作方式;
  • 维持安全与合规标准,防止数据泄露与越权访问;
  • 让团队能快速迭代,不被基础设施瓶颈卡住。

这组需求在传统"为每个团队手工建一套云资源"的模式下几乎不可能优雅满足:要么各环境配置漂移,要么认证方式混杂,要么项目之间缺乏数据隔离。答案是把基础设施当作代码来管理,并让资源编排与 ML 平台本身解耦。

ZenML 方案:Stack 组件作为基础设施的抽象层

ZenML 引入 stack components(栈组件)作为对基础设施资源的抽象。一次管道运行所需的编排、存储、镜像、跟踪、部署等能力,都被建模为不同类型的组件,并聚合为一个Stack。从源码看,这一设计有非常清晰的落点:

  • src/zenml/enums.py#L214-L261 中的StackComponentType枚举定义了全部组件类型:artifact_storecontainer_registryorchestratorstep_operatorexperiment_trackermodel_deployeralerterannotatorimage_builder等,其中step_operatorexperiment_tracker等类型允许一个 Stack 内出现多个实例(supports_multiple_per_stack属性);
  • src/zenml/stack/stack.py#L161-L190 显示Stack类内部正是按StackComponentType将组件分组存放;
  • src/zenml/stack/stack_component.py#L67-L120 中的StackComponentConfig基类还支持以{{secret_name.key}}形式的密钥引用填充组件属性,为 Terraform 中敏感配置的安全注入提供了可能。

与 Terraform 结合后,这套抽象变成了一一对应的资源模型:每个组件对应zenml_stack_component资源,每个栈对应zenml_stack资源,每个云认证配置对应zenml_service_connector资源。接下来我们从零开始搭建这套架构。

集成前置条件:连接 ZenML 服务器与 Terraform Provider

在编写任何 HCL 之前,需要先打通 Terraform 与 ZenML 服务器之间的认证通道。依据 deploy-a-cloud-stack-with-terraform.md,你需要满足:

  1. 一个已部署、可从云侧访问的 ZenML 服务器(不能是zenml login --local启动的本地服务器);没有现成服务器时可用zenml login --pro快速接入 ZenML Pro。
  2. 一个服务账号(Service Account)与对应的 API Key,用于让 Terraform 以编程方式访问 ZenML 服务器。OSS 服务器上连接后执行即可:
zenml service-account create terraform-account

创建成功后会打印形如ZENKEY_...的 API Key(仅展示一次,务必安全保存),并给出使用该 Key 登录的命令示例:

zenml login https://842ed6a9-zenml.staging.cloudinfra.zenml.io --api-key
  1. Terraform 1.9 及以上版本,以及本机已通过云厂商 CLI/SDK 完成本地认证(GCP 的gcloud auth application-default login、AWS 的aws configure、Azure 的az login)。
  2. 配置 ZenML Provider 的环境变量(推荐用环境变量而非硬编码):
export ZENML_SERVER_URL="https://your-zenml-server.com" export ZENML_API_KEY="<your-api-key>"

ZenML Pro 用户注意:ZENML_SERVER_URL应填 Dashboard 中的 Workspace URL(形如https://1bfe8d94-zenml.cloudinfra.zenml.io),而ZENML_API_KEY使用 ZenML Pro 的 API Key 或 Personal Access Token。

完成上述准备后,即可在 Terraform 配置中声明 Provider:

terraform { required_providers { zenml = { source = "zenml-io/zenml" } } } provider "zenml" { # server_url = <取自 ZENML_SERVER_URL 环境变量,此处可不填> # api_key = <取自 ZENML_API_KEY 环境变量,此处可不填> }

Part 1:基础——Stack 组件化架构

问题

不同团队需要不同的 ML 基础设施配置,但你又希望保持一致性、可复用性,避免每个团队各自为政。

解法:基于组件的架构

把基础设施拆解为可复用的模块,每个模块与 ZenML Stack 组件一一对应。下面的基础模块zenml_stack_base统一声明 Provider、生成一致的随机后缀、创建共享的基础云资源(对象存储、容器镜像仓库、认证账号/服务账号/工作负载身份/角色/权限),并通过zenml_service_connectorzenml_stack_componentzenml_stack三类资源把基础设施"注册"进 ZenML:

# modules/zenml_stack_base/main.tf terraform { required_providers { zenml = { source = "zenml-io/zenml" } google = { source = "hashicorp/google" } } } resource "random_id" "suffix" { # This will generate a string of 12 characters, encoded as base64 which makes # it 8 characters long byte_length = 6 } # Create base infrastructure resources, including a shared object storage, # and container registry. This module should also create resources used to # authenticate with the cloud provider and authorize access to the resources # (e.g. user accounts, service accounts, workload identities, roles, # permissions etc.) module "base_infrastructure" { source = "./modules/base_infra" environment = var.environment project_id = var.project_id region = var.region # Generate consistent random naming across resources resource_prefix = "zenml-${var.environment}-${random_id.suffix.hex}" } # Create a flexible service connector for authentication resource "zenml_service_connector" "base_connector" { name = "${var.environment}-base-connector" type = "gcp" auth_method = "service-account" configuration = { project_id = var.project_id region = var.region service_account_json = module.base_infrastructure.service_account_key } labels = { environment = var.environment } } # Create base stack components resource "zenml_stack_component" "artifact_store" { name = "${var.environment}-artifact-store" type = "artifact_store" flavor = "gcp" configuration = { path = "gs://${module.base_infrastructure.artifact_store_bucket}/artifacts" } connector_id = zenml_service_connector.base_connector.id } resource "zenml_stack_component" "container_registry" { name = "${var.environment}-container-registry" type = "container_registry" flavor = "gcp" configuration = { uri = module.base_infrastructure.container_registry_uri } connector_id = zenml_service_connector.base_connector.id } resource "zenml_stack_component" "orchestrator" { name = "${var.environment}-orchestrator" type = "orchestrator" flavor = "vertex" configuration = { location = var.region workload_service_account = "${module.base_infrastructure.service_account_email}" } connector_id = zenml_service_connector.base_connector.id } # Create the base stack resource "zenml_stack" "base_stack" { name = "${var.environment}-base-stack" components = { artifact_store = zenml_stack_component.artifact_store.id container_registry = zenml_stack_component.container_registry.id orchestrator = zenml_stack_component.orchestrator.id } labels = { environment = var.environment type = "base" } }

这段配置体现了三个关键约定:

  • 连接器与组件解耦zenml_service_connector承载云认证信息,多个组件通过connector_id复用它,而不是各自内嵌凭据;
  • typeflavor分离type对应 StackComponentType(如artifact_storeorchestrator),flavor对应具体实现(如 GCP 的gcpArtifact Store、Vertex AI 的vertexOrchestrator);
  • labels贯穿始终:为每个资源打上environmenttypeproject等标签,便于在 ZenML 与云侧统一审计。

在基础栈之上,各团队可以按需扩展自己的训练栈。由于orchestrator类型允许栈内按需替换,团队可以只覆盖编排器而不必重造存储与镜像仓库:

# team_configs/training_stack.tf # Add training-specific components resource "zenml_stack_component" "training_orchestrator" { name = "${var.environment}-training-orchestrator" type = "orchestrator" flavor = "vertex" configuration = { location = var.region machine_type = "n1-standard-8" gpu_enabled = true synchronous = true } connector_id = zenml_service_connector.base_connector.id } # Create specialized training stack resource "zenml_stack" "training_stack" { name = "${var.environment}-training-stack" components = { artifact_store = zenml_stack_component.artifact_store.id container_registry = zenml_stack_component.container_registry.id orchestrator = zenml_stack_component.training_orchestrator.id } labels = { environment = var.environment type = "training" } }

这一"基础组件共享 + 团队组件定制"的模式,正是 ZenML 中Stack按类型组合组件的体现(见 src/zenml/stack/stack.py),也是多团队场景下保持一致性、避免重复造轮子的关键。

Part 2:环境管理与智能认证

问题

不同环境(dev、staging、prod)要求:

  • 不同的认证方式与安全级别;
  • 环境专属的资源配置;
  • 环境间隔离,避免跨环境影响;
  • 一致的管理模式,同时保持灵活性。

解法:环境配置模式 + 智能认证

为环境感知的服务连接器(Service Connector)建立一套配置,例如开发环境使用更灵活的服务账号(service-account),生产环境走 workload identity / external account。把"每环境的资源配置"与"每环境的认证配置"放在同一个locals中集中管理:

locals { # Define configurations per environment env_config = { dev = { # Resource configuration machine_type = "n1-standard-4" gpu_enabled = false # Authentication configuration auth_method = "service-account" auth_configuration = { service_account_json = file("dev-sa.json") } } prod = { # Resource configuration machine_type = "n1-standard-8" gpu_enabled = true # Authentication configuration auth_method = "external-account" auth_configuration = { external_account_json = file("prod-sa.json") } } } } # Create environment-specific connector resource "zenml_service_connector" "env_connector" { name = "${var.environment}-connector" type = "gcp" auth_method = local.env_config[var.environment].auth_method dynamic "configuration" { for_each = try(local.env_config[var.environment].auth_configuration, {}) content { key = configuration.key value = configuration.value } } } # Create environment-specific orchestrator resource "zenml_stack_component" "env_orchestrator" { name = "${var.environment}-orchestrator" type = "orchestrator" flavor = "vertex" configuration = { location = var.region machine_type = local.env_config[var.environment].machine_type gpu_enabled = local.env_config[var.environment].gpu_enabled } connector_id = zenml_service_connector.env_connector.id labels = { environment = var.environment } }

这里的auth_methodconfiguration语义与 ZenML 源码中 AuthenticationMethodModel 的建模一一对应:每种认证方法都有一份 JSON Schema(config_schema)描述所需的配置字段,并可通过min/max/default_expiration_seconds声明是否支持临时凭据。这意味着你在 HCL 里填写的auth_methodconfiguration键值,最终会被 ZenML 按对应认证方法的 Schema 严格校验,写错字段会直接报错,从而在"基础设施即代码"层面保证了认证配置的正确性。

Part 3:资源共享与项目隔离

问题

不同 ML 项目通常要求数据与安全的严格隔离,防止未授权访问,确保符合安全合规策略。每个项目应有自己独立的资源(如 Artifact Store 或 Orchestrator),以避免数据泄露并维护各自环境的完整性。

解法:资源作用域(Resource Scoping)模式

核心思路是:共享底层物理资源,但在逻辑路径与组件层面做项目级隔离。这里用一个共享 GCS Bucket,通过projects/<project>/<environment>前缀为每个项目划分独立 Artifact Store;编排器则全局共享,避免重复建设:

locals { project_paths = { fraud_detection = "projects/fraud_detection/${var.environment}" recommendation = "projects/recommendation/${var.environment}" } } # Create shared artifact store components with project isolation resource "zenml_stack_component" "project_artifact_stores" { for_each = local.project_paths name = "${each.key}-artifact-store" type = "artifact_store" flavor = "gcp" configuration = { path = "gs://${var.shared_bucket}/${each.value}" } connector_id = zenml_service_connector.env_connector.id labels = { project = each.key environment = var.environment } } # The orchestrator is shared across all stacks resource "zenml_stack_component" "project_orchestrator" { name = "shared-orchestrator" type = "orchestrator" flavor = "vertex" configuration = { location = var.region project = var.project_id } connector_id = zenml_service_connector.env_connector.id labels = { environment = var.environment } } # Create project-specific stacks separated by artifact stores resource "zenml_stack" "project_stacks" { for_each = local.project_paths name = "${each.key}-stack" components = { artifact_store = zenml_stack_component.project_artifact_stores[each.key].id orchestrator = zenml_stack_component.project_orchestrator.id } labels = { project = each.key environment = var.environment } }

通过for_each+locals,同一份 HCL 就能为任意数量的项目生成相互隔离的 Artifact Store 与项目专属 Stack,既满足了"数据隔离"的安全底线,又最大化复用了共享的编排资源——这正是多项目场景中最值得借鉴的模式。

Part 4:高级 Stack 管理实践

在基础模式之上,原文还给出了五条可落地的进阶实践,分别解决版本、认证、配置、组织与状态管理问题。

1. Stack 组件版本化

用统一的stack_version驱动命名与标签,让每个 Stack 的版本可追溯:

locals { stack_version = "1.2.0" common_labels = { version = local.stack_version managed_by = "terraform" environment = var.environment } } resource "zenml_stack" "versioned_stack" { name = "stack-v${local.stack_version}" labels = local.common_labels }

2. Service Connector 治理

为不同环境与用途创建语义清晰的连接器:生产用 workload identity,非生产用 service account;并通过resource_type/resource_id将连接器的作用域锁定到特定云资源:

# Create environment-specific connectors with clear purposes resource "zenml_service_connector" "env_connector" { name = "${var.environment}-${var.purpose}-connector" type = var.connector_type # Use workload identity for production auth_method = var.environment == "prod" ? "workload-identity" : "service-account" # Use a specific resource type and resource ID resource_type = var.resource_type resource_id = var.resource_id labels = merge(local.common_labels, { purpose = var.purpose }) }

这种"最小权限 + 明确用途"的写法,让认证配置也能像代码一样走评审、版本化与审计。

3. 组件配置管理:基础配置 + 环境覆盖

把公共配置抽到base_configs,把环境差异放到env_configs,最后用merge+try合并出最终配置,保持 DRY:

# Define reusable configurations locals { base_configs = { orchestrator = { location = var.region project = var.project_id } artifact_store = { path_prefix = "gs://${var.bucket_name}" } } # Environment-specific overrides env_configs = { dev = { orchestrator = { machine_type = "n1-standard-4" } } prod = { orchestrator = { machine_type = "n1-standard-8" } } } } resource "zenml_stack_component" "configured_component" { name = "${var.environment}-${var.component_type}" type = var.component_type # Merge configurations configuration = merge( local.base_configs[var.component_type], try(local.env_configs[var.environment][var.component_type], {}) ) }

4. Stack 组织与依赖

用模块封装相关组件,并显式声明依赖链与可选组件。depends_on确保基础设施与安全模块先行就绪,条件表达式则让编排器、实验跟踪器等按团队需求可选挂载:

# Group related components with clear dependency chains module "ml_stack" { source = "./modules/ml_stack" depends_on = [ module.base_infrastructure, module.security ] components = { # Core components artifact_store = module.storage.artifact_store_id container_registry = module.container.registry_id # Optional components based on team needs orchestrator = var.needs_orchestrator ? module.compute.orchestrator_id : null experiment_tracker = var.needs_tracking ? module.mlflow.tracker_id : null } labels = merge(local.common_labels, { stack_type = "ml-platform" }) }

这与 ZenML 允许experiment_trackerstep_operator等组件在单个 Stack 内按需多实例的设计(见 src/zenml/enums.py#L249-L261)相吻合:基础设施的组织方式应当与 ZenML 的组件组合规则对齐。

5. 状态管理

把"基础设施状态"与"ZenML 注册状态"分离存储,避免互相干扰;基础设施变更通过terraform_remote_state数据源被 ZenML 侧引用,从而在terraform apply时自动拿到最新的资源 ID:

terraform { backend "gcs" { prefix = "terraform/state" } # Separate state files for infrastructure and ZenML workspace_prefix = "zenml-" } # Use data sources to reference infrastructure state data "terraform_remote_state" "infrastructure" { backend = "gcs" config = { bucket = var.state_bucket prefix = "terraform/infrastructure" } }

从配置到运行:两阶段方法与完整工作流

理解上述模式后,还需要明确 ZenML + Terraform 协作的整体结构。基础设施即代码指南将整个流程划分为两个阶段:

  1. 基础设施部署(Infrastructure Deployment):创建云资源,通常由平台团队负责,例如 GCS 存储桶、Artifact Registry 镜像仓库;
  2. ZenML 注册(ZenML Registration):把这些资源注册为 ZenML Stack 组件与 Stack。

官方维护的zenml-stack/{aws,gcp,azure}模块(见 deploy-a-cloud-stack-with-terraform.md)会同时完成两个阶段;而如果你已经用自有 Terraform 代码部署好了云资源,就可以像前文那样只写zenml_service_connectorzenml_stack_componentzenml_stack三类资源完成"纯注册"。

无论走哪条路,日常使用的工作流都是一致的:

# 1. 初始化并应用 Terraform 配置 terraform init terraform apply # 2. 安装对应云集成(以 GCP 为例) zenml integration install gcp # 3. 激活新创建的 Stack zenml stack set <zenml_stack_id> # 4. 查看并验证 Stack 配置 zenml stack describe

terraform apply完成后会打印出创建的zenml_stack_idzenml_stack_name。需要清理环境时,在保存 Terraform 配置与状态文件的同一目录下执行:

terraform destroy

这会删除所有被纳管的云资源,同时注销 ZenML 服务器上注册的 Stack。注意:不要随意删除保存 Terraform 配置与状态文件的目录,除非你确定不再需要由 Terraform 管理这些资源。

最佳实践清单

要让这套 IaC 体系长期保持整洁、可扩展、可维护,原文建议始终遵循以下原则:

  • localsvariables保持配置 DRY,避免复制粘贴;
  • 跨资源使用一致的命名约定(如zenml-${environment}-${project}-${type});
  • 文档化所有必填配置字段,降低团队上手成本;
  • 组织 Stack 时考虑组件依赖关系
  • 分离基础设施与 ZenML 注册的状态文件,降低爆炸半径;
  • 使用 Terraform workspaces 管理不同环境
  • 由 ML 运维团队负责管理注册状态,保持对 ZenML Stack 组件及其配置的控制权,从而让基础设施与 ML 运维对齐,获得更好的变更跟踪与审计能力。

结论

用 ZenML 与 Terraform 架构 ML 基础设施,能够在保持清晰基础设施模式的同时,为 ML 团队交付一套灵活、可维护且安全的环境。官方 ZenML Terraform Provider 将"组件—连接器—栈"三元模型无缝映射为 HCL 资源,配合本文的组件化基础栈、环境感知认证、项目级隔离与状态/版本治理四套模式,即可把多团队、多环境、高合规要求的 ML 平台落地为真正可审计、可回滚的代码。

【免费下载链接】zenmlZenML 🙏: One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询