ZenML Pro Workspace Server 快照(Workload Manager)支持配置指南
【免费下载链接】zenmlZenML 🙏: One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml
本篇技术指南讲解如何为自托管(self-hosted)的 ZenML Pro Workspace Server 启用 Snapshot(Workload Manager)支持,使流水线能够直接从 ZenML Pro UI 运行。你将掌握 Workload Manager 的两种实现(Kubernetes / AWS)、三种 runner 镜像管理方案、完整的 Helm 环境变量配置与 Kubernetes RBAC 权限拆分方法,并了解 ZenML 开源仓库中对应的接口与执行链路实现。
概述:从 UI 直接运行快照
Workspace Server 内置了Workload Manager特性,它允许你在 ZenML Pro UI 中直接运行流水线快照(Snapshot),而不必依赖本地 CLI 或 SDK 环境。该特性的本质是:Workload Manager 会在一个可访问的 Kubernetes 集群中创建临时(ad-hoc)的流水线 runner Pod/Job,由这些 Job 以与 CLI/SDK 相同的方式启动流水线。
启用该功能有两个硬性前提(来自原文档的警告提示):
- Snapshot 支持仅从ZenML Pro Workspace Server 0.90.0 版本起可用;
- Snapshot 支持仅适用于部署在 Kubernetes 上的 Workspace Server,部署在 AWS ECS 或其他平台的 Workspace Server 目前不受支持。
从源码看,Workload Manager 的启用与否由服务端配置字段workload_manager_implementation_source决定:该字段非空时,server_config.py 中的workload_manager_enabled属性返回True,而runs_endpoints.py、pipeline_snapshot_endpoints.py、run_templates_endpoints.py等路由会据此开放对应的快照运行能力。
前置条件
在开始配置前,需要满足以下基础要求:
- 一个可从 Workspace Server 访问的Kubernetes 集群(1.24+);
- 为 runner Pod 准备的专用命名空间(namespace);
- 具备创建/管理 Pod 权限的服务账号(Service Account)与 RBAC 权限;
- 为服务账号配置的镜像拉取密钥(image pull secrets)。
理解 Workload Manager 子特性
从 UI 运行流水线依赖运行 Kubernetes Job(即 "runner" Job),这些 Job 与从 CLI/SDK 运行流水线的方式一致。由于这些 Job 需要携带正确 Python 包依赖的容器镜像才能启动流水线,你需要根据实际需求选择以下三种 runner 镜像来源之一:
复用快照容器镜像(Reuse snapshot container images):直接复用运行快照时为该快照构建的流水线容器镜像。这要求 runner Job 拥有所有存储这些镜像的容器注册表(即 ZenML Stack 中使用的 Container Registries)的拉取权限。此方案仅能运行与包含同一容器注册表的 Stack 关联的快照。
按需构建 runner 镜像(Build on-demand):Workspace Server 在需要时会启动额外的 Kubernetes Job 来构建 runner 镜像并推送到已配置的容器注册表。这要求 "builder" Kubernetes Job 拥有向私有容器注册表推送的权限,同时 "runner" Job 拥有从同一注册表拉取的权限。这是最灵活的方案,可以运行与任意 Stack、任意集成关联的快照。
使用预构建 runner 镜像(Pre-built image):为所有运行提供一个预先构建好的单一 runner 镜像(存储在你自己的容器注册表中)。这是最简单、最快的方案,但你需要自行确保镜像中包含正确的 Python 包依赖。此方案限制最大,要求预先构建包含所有可能 Stack 与集成依赖的容器镜像。
外部日志存储(Store logs externally):默认情况下,ZenML Pro UI 中展示的日志从 "runner" Job Pod 中提取。由于 Pod 可能消失,你可以配置外部日志存储。目前仅 AWS 实现支持外部日志。启用后需要配置日志存放的 S3 bucket 与 region,并授予 ZenML Pro Workspace Server Pod 对该 bucket 的写权限。
两种 Workload Manager 实现
- Kubernetes:在与 ZenML Pro Workspace Server 相同的 Kubernetes 集群中运行流水线;
- AWS:在 Kubernetes 实现的基础上扩展,支持向 AWS ECR 构建/推送镜像,并将日志存储到 AWS S3。
源码中的接口设计
在开源仓库中,Workload Manager 的行为被抽象为WorkloadManagerInterface(见 workload_manager_interface.py),核心方法包括:
run():在容器中运行命令(对应启动 runner 流水线);build_and_push_image():构建并推送 Docker 镜像(对应按需构建 runner 镜像);delete_workload():删除工作负载;get_logs():获取工作负载日志;log():写入工作负载日志消息。
同时定义了WorkloadType枚举(SNAPSHOT与RUN),用于区分工作负载对应的实体类型。仓库内置的 in_memory_workload_manager.py 是一个通过subprocess在服务器本机直接运行的InMemoryWorkloadManager实现;而文档中提到的zenml_cloud_plugins.kubernetes_workload_manager.KubernetesWorkloadManager与zenml_cloud_plugins.aws_kubernetes_workload_manager.AWSKubernetesWorkloadManager则来自 ZenML Pro 的云插件包(zenml_cloud_plugins),不在本开源仓库内。
服务端启动时会调用initialize_workload_manager()(见 zen_server_api.py),其逻辑位于 utils.py:读取server_config().workload_manager_implementation_source配置,通过source_utils.load_and_validate_class加载并校验实现类,实例化后存入全局单例供后续调用。若实现类无法加载,只会记录警告而不会导致服务启动失败。
第一步:为 Workload Manager 创建 Kubernetes 资源
创建一个专用的命名空间和服务账号,用于启动 runner Job:
# 创建命名空间 kubectl create namespace zenml-workload-manager # 创建服务账号 kubectl -n zenml-workload-manager create serviceaccount zenml-workload-manager第二步:选择 Workload Manager 实现
你的实现选择决定了需要在 ZenML Workspace Server Helm 部署中额外配置的环境变量。
Option A:Kubernetes 实现(基础版)
提供通用的 Kubernetes 功能来运行快照:
server: environment: ZENML_SERVER_WORKLOAD_MANAGER_IMPLEMENTATION_SOURCE: zenml_cloud_plugins.kubernetes_workload_manager.KubernetesWorkloadManager ZENML_KUBERNETES_WORKLOAD_MANAGER_NAMESPACE: zenml-workload-manager ZENML_KUBERNETES_WORKLOAD_MANAGER_SERVICE_ACCOUNT: zenml-workload-managerOption B:AWS 实现
在 Kubernetes 基础上提供 AWS 特有能力,包括外部 S3 日志与 ECR 集成:
server: environment: ZENML_SERVER_WORKLOAD_MANAGER_IMPLEMENTATION_SOURCE: zenml_cloud_plugins.aws_kubernetes_workload_manager.AWSKubernetesWorkloadManager ZENML_KUBERNETES_WORKLOAD_MANAGER_NAMESPACE: zenml-workload-manager ZENML_KUBERNETES_WORKLOAD_MANAGER_SERVICE_ACCOUNT: zenml-workload-manager ZENML_AWS_KUBERNETES_WORKLOAD_MANAGER_REGION: eu-central-1 # 如需将日志外部存储到 S3,还需要设置以下环境变量: ZENML_KUBERNETES_WORKLOAD_MANAGER_ENABLE_EXTERNAL_LOGS: "true" ZENML_AWS_KUBERNETES_WORKLOAD_MANAGER_BUCKET: s3://my-bucket/run-template-logs第三步:配置 Runner 镜像来源
根据你对 runner 镜像的管理方式,在 Workspace Server Helm 部署中配置相应环境变量:
Option 1:复用快照容器镜像
server: environment: ZENML_KUBERNETES_WORKLOAD_MANAGER_BUILD_RUNNER_IMAGE: "false" # 保持为空或不设置该变量即可复用快照容器镜像 # ZENML_KUBERNETES_WORKLOAD_MANAGER_RUNNER_IMAGE:Option 2:由 ZenML 构建 Runner 镜像(按需构建)
server: environment: ZENML_KUBERNETES_WORKLOAD_MANAGER_BUILD_RUNNER_IMAGE: "true" ZENML_KUBERNETES_WORKLOAD_MANAGER_DOCKER_REGISTRY: internal-registry.mycompany.com/zenmlOption 3:使用预构建的 Runner 镜像
server: environment: ZENML_KUBERNETES_WORKLOAD_MANAGER_BUILD_RUNNER_IMAGE: "false" ZENML_KUBERNETES_WORKLOAD_MANAGER_RUNNER_IMAGE: internal-registry.mycompany.com/zenml/zenml:<ZENML_OSS_VERSION>源码中的镜像与执行细节
从源码可以更直观地理解这些配置背后的执行逻辑。在 utils.py 的_build_and_run()函数中,整个快照运行流程为:
- 根据 stack 与 build 信息生成 Dockerfile(
build_runner_dockerfile()→generate_dockerfile(),见同文件 L1116-L1148)。生成的 Dockerfile 以zenmldocker/zenml:{zenml_version}-py{python_version}作为父镜像(可通过ENV_ZENML_RUNNER_PARENT_IMAGE环境变量覆盖),随后安装 stack 所需的 APT 包与 PyPI 依赖(默认通过uv安装); - 基于 Dockerfile 内容计算 MD5 哈希(
generate_image_hash()),以zenml-runner:{image_hash}作为镜像名,调用workload_manager().build_and_push_image()构建并推送 runner 镜像; - 写入 "Starting pipeline run." 日志,随后以
ENV_ZENML_RUNNER_POD_TIMEOUT(默认 180 秒)作为超时,调用workload_manager().run()启动 runner 工作负载。
runner 工作负载通过build_runner_environment()(同文件 L1066-L1113)注入环境:包括ZENML_STORE_URL(服务器地址)、ZENML_STORE_TYPE=REST、ZENML_STORE_API_TOKEN(一个永不过期、作用域限定到该流水线运行的 API token,由generate_access_token生成)以及ZENML_STORE_VERIFY_SSL=True。runner 启动后便以 REST 客户端身份回连 Workspace Server 执行流水线。
第四步:配置权限
运行 ZenML Workspace Server 的 Kubernetes 服务账号需要额外权限:
- 在第一步设置的 workload manager 命名空间中创建和管理 Job 的权限;
- 如果使用 AWS 实现且启用了外部 S3 日志,还需要向所配置 S3 bucket 写入的权限。
第一步设置的 workload manager Kubernetes 服务账号还需要以下容器注册表权限:
- 从存储 runner 镜像的容器注册表拉取镜像的权限;
- 如果选择按需构建 runner 镜像,还需要向 runner 镜像目标注册表推送镜像的权限。
授予这些权限有多种方式:
- 授予整个集群对容器注册表的访问权限;
- 使用隐式工作负载身份访问容器注册表——大多数云厂商支持通过授予 Kubernetes 服务账号对容器注册表的访问权限来实现;
- 配置一个对容器注册表具有隐式访问权限的服务账号——将某个云服务身份(例如 GCP 服务账号、AWS IAM 角色等)与 Kubernetes 服务账号关联;
- 为服务账号配置镜像拉取密钥(image pull secret)——与上一种方式类似,但使用 Kubernetes Secret 而非云服务身份。
推荐的权限最小化拆分(least-privilege split)
建议为以下两种身份使用独立的服务账号:
- 运行 Workspace Server Pod 的服务账号;
ZENML_KUBERNETES_WORKLOAD_MANAGER_SERVICE_ACCOUNT中为 runner/builder Job 配置的服务账号。
Workspace Server 服务账号的 RBAC(位于 workload manager 命名空间内)
Workspace Server 负责创建、监控、清理 workload manager Job,并抓取 Pod 日志。需要授予:
batch/jobs:create、get、deletecollectioncore/pods:listcore/pods/log:get
这与源码中 Workload Manager 的日志获取路径相互印证:runs_endpoints.py会调用workload_manager().get_logs()提取 runner 日志并合并到流水线运行的日志集合中(见 runs_endpoints.py)。
Workload manager runner/builder 服务账号
由 workload manager 启动的 runner/builder Job 本身不需要对 workload manager 控制回路的 Kubernetes API 权限。该账号主要需要:
- 对 runner 镜像的容器注册表拉取权限;
- 如果启用了按需构建,则需要容器注册表推送权限;
- 工作负载实现所需的可选云权限(例如启用 AWS 外部日志时的 S3 写权限)。
环境变量参考
Workload Manager 配置支持的全部环境变量如下:
| 变量 | 是否必需 | 说明 |
|---|---|---|
ZENML_SERVER_WORKLOAD_MANAGER_IMPLEMENTATION_SOURCE | 是 | 实现类(见上方两种实现选项) |
ZENML_KUBERNETES_WORKLOAD_MANAGER_NAMESPACE | 是 | runner Job 所在的 Kubernetes 命名空间 |
ZENML_KUBERNETES_WORKLOAD_MANAGER_SERVICE_ACCOUNT | 是 | runner Job 使用的 Kubernetes 服务账号 |
ZENML_KUBERNETES_WORKLOAD_MANAGER_BUILD_RUNNER_IMAGE | 否 | 是否构建 runner 镜像(默认:false) |
ZENML_KUBERNETES_WORKLOAD_MANAGER_DOCKER_REGISTRY | 条件必需 | runner 镜像所在的注册表(构建镜像时必需) |
ZENML_KUBERNETES_WORKLOAD_MANAGER_RUNNER_IMAGE | 否 | 预构建的 runner 镜像(不构建时使用) |
ZENML_KUBERNETES_WORKLOAD_MANAGER_ENABLE_EXTERNAL_LOGS | 否 | 是否外部存储日志(默认:false,仅 AWS) |
ZENML_KUBERNETES_WORKLOAD_MANAGER_POD_RESOURCES | 否 | Pod 资源限制(JSON 格式) |
ZENML_KUBERNETES_WORKLOAD_MANAGER_TTL_SECONDS_AFTER_FINISHED | 否 | 已完成 Job 的清理时间(默认:2 天) |
ZENML_KUBERNETES_WORKLOAD_MANAGER_NODE_SELECTOR | 否 | 节点选择器(JSON 格式) |
ZENML_KUBERNETES_WORKLOAD_MANAGER_TOLERATIONS | 否 | 容忍度(JSON 格式) |
ZENML_KUBERNETES_WORKLOAD_MANAGER_JOB_BACKOFF_LIMIT | 否 | builder/runner Job 的重试上限 |
ZENML_KUBERNETES_WORKLOAD_MANAGER_POD_FAILURE_POLICY | 否 | builder/runner Job 的 Pod 失败策略 |
ZENML_SERVER_MAX_CONCURRENT_TEMPLATE_RUNS | 否 | 每个 Pod 的最大并发快照运行数(默认:2) |
AWS 特有变量:
| 变量 | 是否必需 | 说明 |
|---|---|---|
ZENML_AWS_KUBERNETES_WORKLOAD_MANAGER_BUCKET | 条件必需 | 日志存储的 S3 bucket(启用外部日志时必需) |
ZENML_AWS_KUBERNETES_WORKLOAD_MANAGER_REGION | 条件必需 | AWS 区域(构建镜像时必需) |
完整配置示例
最小化 Kubernetes 配置:
server: environment: ZENML_SERVER_WORKLOAD_MANAGER_IMPLEMENTATION_SOURCE: zenml_cloud_plugins.kubernetes_workload_manager.KubernetesWorkloadManager ZENML_KUBERNETES_WORKLOAD_MANAGER_NAMESPACE: zenml-workspace-namespace ZENML_KUBERNETES_WORKLOAD_MANAGER_SERVICE_ACCOUNT: zenml-workspace-service-account完整的 AWS 配置:
server: environment: ZENML_SERVER_WORKLOAD_MANAGER_IMPLEMENTATION_SOURCE: zenml_cloud_plugins.aws_kubernetes_workload_manager.AWSKubernetesWorkloadManager ZENML_KUBERNETES_WORKLOAD_MANAGER_NAMESPACE: zenml-workspace-namespace ZENML_KUBERNETES_WORKLOAD_MANAGER_SERVICE_ACCOUNT: zenml-workspace-service-account ZENML_KUBERNETES_WORKLOAD_MANAGER_BUILD_RUNNER_IMAGE: "true" ZENML_KUBERNETES_WORKLOAD_MANAGER_DOCKER_REGISTRY: 339712793861.dkr.ecr.eu-central-1.amazonaws.com ZENML_KUBERNETES_WORKLOAD_MANAGER_ENABLE_EXTERNAL_LOGS: "true" ZENML_KUBERNETES_WORKLOAD_MANAGER_POD_RESOURCES: '{"requests": {"cpu": "100m", "memory": "400Mi"}, "limits": {"memory": "700Mi"}}' ZENML_AWS_KUBERNETES_WORKLOAD_MANAGER_BUCKET: s3://my-bucket/run-template-logs ZENML_AWS_KUBERNETES_WORKLOAD_MANAGER_REGION: eu-central-1 ZENML_KUBERNETES_WORKLOAD_MANAGER_NODE_SELECTOR: '{"node-pool": "zenml-pool"}' ZENML_KUBERNETES_WORKLOAD_MANAGER_TOLERATIONS: '[{"key": "node-pool", "operator": "Equal", "value": "zenml-pool", "effect": "NoSchedule"}]' ZENML_SERVER_MAX_CONCURRENT_TEMPLATE_RUNS: 10使用预构建 runner 镜像的配置:
server: environment: ZENML_SERVER_WORKLOAD_MANAGER_IMPLEMENTATION_SOURCE: zenml_cloud_plugins.kubernetes_workload_manager.KubernetesWorkloadManager ZENML_KUBERNETES_WORKLOAD_MANAGER_NAMESPACE: zenml-workspace-namespace ZENML_KUBERNETES_WORKLOAD_MANAGER_SERVICE_ACCOUNT: zenml-workspace-service-account ZENML_KUBERNETES_WORKLOAD_MANAGER_BUILD_RUNNER_IMAGE: "false" ZENML_KUBERNETES_WORKLOAD_MANAGER_RUNNER_IMAGE: internal-registry.mycompany.com/zenml/zenml:<ZENML_OSS_VERSION> ZENML_KUBERNETES_WORKLOAD_MANAGER_POD_RESOURCES: '{"requests": {"cpu": "100m", "memory": "400Mi"}, "limits": {"memory": "700Mi"}}' ZENML_KUBERNETES_WORKLOAD_MANAGER_TTL_SECONDS_AFTER_FINISHED: 86400 ZENML_SERVER_MAX_CONCURRENT_TEMPLATE_RUNS: 2更新 Workspace 部署
将 workload manager 配置写入你的 workspace server Helm values 文件并重新部署:
helm upgrade zenml ./zenml-<version>.tgz \ --namespace zenml-workspace \ --values zenml-workspace-values.yaml关于自托管部署的整体架构与更多 Helm 部署细节,可继续阅读 Self-hosted Deployment Overview,并参考 Kubernetes 与 Helm 的官方文档深入了解 Job、RBAC 与 Helm values 机制。更多与快照执行、runner 构建相关的源码细节,可继续阅读 utils.py、workload_manager_interface.py 与 server_config.py。
【免费下载链接】zenmlZenML 🙏: One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考