跳到主要内容

MLflow 跟踪服务器

MLflow 跟踪服务器是一个独立的 HTTP 服务器,它提供多个 REST API 端点用于跟踪运行/实验。虽然 MLflow Tracking 可以在本地环境中使用,但在团队开发工作流程中托管跟踪服务器功能非常强大。

  • 协作:多个用户可以将运行记录到同一个端点,并查询其他用户记录的运行和模型。
  • 共享结果:跟踪服务器还提供 Tracking UI 端点,团队成员可以在此处轻松查看彼此的实验结果。
  • 集中式访问:跟踪服务器可以作为代理运行,用于远程访问元数据和工件 (artifacts),从而更易于保护和审计数据访问。

启动跟踪服务器

启动跟踪服务器非常简单,只需运行以下命令:

bash
mlflow server --host 127.0.0.1 --port 8080

服务器启动后,您应该会看到以下输出:

text
INFO: Started server process [28550]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit)

配置服务器有很多选项,详情请参阅 配置服务器

重要提示

服务器默认在 https://:5000 监听,并且仅接受来自本地机器的连接。要让服务器接受来自其他机器的连接,您需要传递 --host 0.0.0.0 以监听所有网络接口(或特定的接口地址)。在 **Kubernetes pod 或 Docker 容器**中运行服务器时,通常需要此配置。

MLflow 3.5.0+ 包含内置的安全中间件,用于防御 DNS 重绑定 (DNS rebinding) 和 CORS 攻击。使用 --host 0.0.0.0 时,请配置 --allowed-hosts 选项以指定哪些域名可以访问您的服务器。有关详细信息,请参阅 安全配置

只读文件系统

在具有只读根文件系统的容器中运行(在 Kubernetes 中常见,即 securityContext.readOnlyRootFilesystem: true)时,请使用 --artifacts-destination 配置远程工件存储(默认启用工件服务)。使用远程工件存储时,跟踪服务器在启动时不会创建本地目录,从而使其兼容只读环境。

bash
mlflow server \
--host 0.0.0.0 \
--backend-store-uri postgresql://user:pass@host/db \
--artifacts-destination s3://my-bucket

记录到跟踪服务器

跟踪服务器启动后,通过设置 MLFLOW_TRACKING_URI 环境变量为服务器的 URI(包括方案和端口,例如 http://10.0.0.1:5000)来连接您的本地客户端,或者调用 mlflow.set_tracking_uri()

诸如 mlflow.start_run(), mlflow.log_param(), mlflow.start_trace() 等 MLflow API 会向您的远程跟踪服务器发出 API 请求并记录数据。

python
import mlflow

remote_server_uri = "..." # set to your server URI, e.g. http://127.0.0.1:8080
mlflow.set_tracking_uri(remote_server_uri)
mlflow.set_experiment("/my-experiment")

# Logging a run
with mlflow.start_run():
mlflow.log_param("a", 1)
mlflow.log_metric("b", 2)

# Logging a trace
with mlflow.start_span(name="test_trace") as span:
span.set_inputs({"x": 1, "y": 2})
span.set_outputs(3)

配置服务器

本节介绍如何针对一些常见用例配置跟踪服务器。本节要求您具备跟踪服务器架构的基础知识,如果您还不熟悉,请访问 架构概述

后端存储

默认情况下,跟踪服务器使用 SQLite 数据库 (sqlite:///mlflow.db) 来存储运行元数据。您可以通过添加 --backend-store-uri 选项来配置不同的后端存储:

示例
bash
# Default: SQLite database (mlflow.db in current directory)
mlflow server

# PostgreSQL: connect to an existing PostgreSQL database
mlflow server --backend-store-uri postgresql://username:password@host:port/database

# File-based (legacy): use local filesystem under ./mlruns directory
mlflow server --backend-store-uri ./mlruns

SQLite 是默认的后端,对于大多数用例来说提供了良好的性能和可靠性。对于具有高并发性的生产部署,请考虑使用 PostgreSQL 或 MySQL。

追踪归档

MLflow 可以将旧的追踪跨度 (trace span) 有效负载从跟踪数据库归档到已配置的工件位置,同时确保这些追踪在 UI 和 API 中仍然可读。

注意

要求

追踪归档需要一个支持服务器所属归档的跟踪存储。归档 location 必须是真实的工件仓库 URI。调度程序仅归档已完成的追踪;正在进行的追踪将被跳过。

创建一个 YAML 配置文件并将 MLFLOW_TRACE_ARCHIVAL_CONFIG 指向它:

trace-archival.yaml
yaml
trace_archival:
enabled: true
location: s3://mlflow-trace-archive
retention: 30d
interval_seconds: 300
# Optional: omit this key to make each scheduler pass unbounded.
max_traces_per_pass: 1000
long_retention_allowlist:
# Experiment ID for customer-support-agent-prod
- 12345

然后使用该配置启动服务器,可以通过环境变量或 --trace-archival-config 标志进行配置:

bash
export MLFLOW_TRACE_ARCHIVAL_CONFIG=/etc/mlflow/trace-archival.yaml

mlflow server \
--backend-store-uri postgresql://user:pass@localhost/mlflow \
--default-artifact-root s3://mlflow-artifacts

# Or pass the config path directly
mlflow server \
--backend-store-uri postgresql://user:pass@localhost/mlflow \
--default-artifact-root s3://mlflow-artifacts \
--trace-archival-config /etc/mlflow/trace-archival.yaml
  • interval_seconds 控制调度程序检查归档工作的频率。
  • max_traces_per_pass 限制单次传递的工作量。如果省略此项,则传递不受限制,MLflow 将归档该运行中可以处理的所有符合条件的追踪。
  • long_retention_allowlist 包含允许保留追踪时间超过更广泛服务器或工作空间策略的实验 ID。

启用工作空间后,追踪归档设置将按以下顺序解析:

  1. 全局默认值提供基础归档位置和保留期限。
  2. 工作空间级别的 trace_archival_config 会覆盖该工作空间中所有追踪的默认值。
  3. 实验级别的设置可以进一步减少特定实验的保留期限。
  4. 如果实验要求的保留期限比更广泛的服务器或工作空间策略长,则只有当实验 ID 出现在 long_retention_allowlist 中时,才会遵守该较长的保留期限。

即使启用了工作空间,归档预算仍归服务器所有。max_traces_per_pass 适用于整个调度程序传递,而不是分别适用于每个工作空间。在每次传递时,MLflow 都会重新排列工作空间顺序,然后一次处理一个工作空间。这意味着在顺序中较早访问的工作空间可能会消耗部分或全部剩余的传递预算,然后再考虑后续的工作空间。在工作空间内,archive-now 候选项仍然优先于常规的基于保留期的归档。

例如,如果全局默认值为 30 天,工作空间配置为 90 天,实验 123 配置为 14 天,则实验 123 的追踪将保留 14 天。如果实验 123 配置为 180 天,其追踪将保留 90 天,除非将 123 添加到 long_retention_allowlist,在这种情况下它们将保留 180 天。

故障排除

  • 如果追踪归档从未运行,请确认 MLFLOW_TRACE_ARCHIVAL_CONFIG 指向有效的 YAML 文件,并且 trace_archival.enabledtrue
  • MLFLOW_TRACE_ARCHIVAL_CONFIG 的更改无需重启 MLflow 即可生效。服务器会自动以短缓存窗口(约 5 秒)刷新配置,并在后续的调度程序检查中应用更新后的设置。如果配置刷新失败,MLflow 将继续使用上一个有效配置,直到文件被修复。
  • 如果工作空间或实验未显示有效的保留期,请检查归档是否被禁用、配置错误或缺少归档位置。
  • 如果忽略了较长的实验保留期,请将该实验 ID 添加到服务器配置中的 long_retention_allowlist

有关最终用户工作流程和归档失败/重试行为,请参阅 归档追踪;有关工作空间级别的示例,请参阅 工作空间入门

远程工件存储

将跟踪服务器用于代理工件访问(默认)

默认情况下,跟踪服务器将其工件存储在本地文件系统的 ./mlartifacts 目录中。要配置跟踪服务器以连接到远程存储并提供工件服务,请使用 --artifacts-destination 标志启动服务器。

bash
mlflow server \
--host 0.0.0.0 \
--port 8885 \
--artifacts-destination s3://my-bucket

使用此设置,MLflow 服务器将作为访问远程工件的代理。MLflow 客户端会向服务器发出 HTTP 请求以获取工件。

重要提示

如果您使用远程存储,则必须配置服务器访问工件的凭据。请注意,MLflow 工件代理访问服务允许用户拥有对跟踪服务器可访问的所有工件的假定访问角色。有关详细信息,请参阅 管理访问

跟踪服务器会将客户端跟踪请求中的 mlflow-artifacts:/ URI 解析为明确的对象存储目的地(例如,“s3:/my_bucket/mlartifacts”),以便与工件进行交互。以下模式都将解析为配置的代理对象存储位置(在上述示例中为 s3://my-root-bucket/mlartifacts):

  • https://<host>:<port>/mlartifacts
  • http://<host>/mlartifacts
  • mlflow-artifacts://<host>/mlartifacts
  • mlflow-artifacts://<host>:<port>/mlartifacts
  • mlflow-artifacts:/mlartifacts
重要提示

MLflow 客户端会按运行缓存工件位置信息。因此,不建议在运行终止前更改运行的工件位置。

使用不代理工件访问的跟踪服务器

在某些情况下,您可能希望直接访问远程存储,而不通过跟踪服务器进行代理。在这种情况下,您可以启动带有 --no-serve-artifacts 标志的服务器,并将 --default-artifact-root 设置为您要将请求重定向到的远程存储 URI。

bash
mlflow server --no-serve-artifacts --default-artifact-root s3://my-bucket

使用此设置,MLflow 客户端仍会向跟踪服务器发出最少的 HTTP 请求以获取适当的远程存储 URI,但可以直接上传工件到远程存储/从远程存储下载工件。虽然这对于访问和安全治理来说可能不是最佳实践,但当您想避免通过跟踪服务器代理工件的开销时,它可能会很有用。

使用正确的配置键

--serve-artifacts--default-artifact-root 这两个选项看起来相似,但用于不同的目的。当您选择错误时,工件记录请求将不会通过预期的路径,并可能导致访问问题。经验法则是:

  1. 希望服务器代理上传? 指定 --artifacts-destination 选项且不要设置 --default-artifact-root。新的实验将获得 mlflow-artifacts:/... 运行 URI,客户端通过服务器上传和下载工件。凭据由跟踪服务器管理,客户端无需设置它们。
  2. 希望客户端直接写入存储? 设置 --default-artifact-root 选项和 --no-serve-artifacts。运行将获得 s3://... / gs://... URI,客户端必须具备访问该存储的凭据。
注意

如果 MLflow 服务器以 --no-serve-artifacts 选项启动,客户端将直接把工件推送到工件存储中。默认情况下,它不会通过跟踪服务器进行代理。

因此,客户端需要直接访问工件存储。有关设置这些凭据的说明,请参阅 工件存储文档

注意

创建实验时,来自跟踪服务器配置的工件存储位置会被记录在实验的元数据中。启用代理工件存储时,在非代理模式下运行跟踪服务器时创建的任何现有实验将继续使用非代理工件位置。为了使用代理工件记录,必须创建一个新实验。如果启用 --serve-artifacts 模式跟踪服务器的目的是消除客户端需要对底层存储进行身份验证的需要,则应创建供客户端使用的新实验,以便跟踪服务器可以在此迁移后处理身份验证。

可选:将跟踪服务器实例专门用于工件处理

MLflow 跟踪服务器可以配置为使用不同的后端存储和工件存储,并为客户端提供单一端点。

然而,如果跟踪服务器请求量足够大且观察到性能问题,可以将跟踪服务器配置为 --artifacts-only 模式,与指定了 --no-serve-artifacts 的实例协同工作。此配置确保了工件的处理与其他所有跟踪服务器事件的处理相隔离。

当跟踪服务器配置为 --artifacts-only 模式时,除工件处理相关的任务(即模型记录、加载模型、记录工件、列出工件等)之外的任何任务都将返回 HTTPError。请参阅以下 Python 客户端 REST 调用示例,该客户端尝试从配置为 --artifacts-only 模式的服务器列出实验:

bash
# Launch the artifact-only server
mlflow server --artifacts-only ...
python
import requests

# Attempt to list experiments from the server
response = requests.get("http://0.0.0.0:8885/api/2.0/mlflow/experiments/list")
输出
_
>> HTTPError: Endpoint: /api/2.0/mlflow/experiments/list disabled due to the mlflow server running in `--artifacts-only` mode.

使用额外的 MLflow 服务器专门处理工件对于大规模 MLOps 基础架构非常有用。将耗时较长、计算密集型的工件处理任务与来自其他跟踪 API 请求的更快速、高容量的元数据功能解耦,有助于减轻原本由单个 MLflow 服务器同时处理两种类型有效负载的负担。

注意

如果 MLflow 服务器运行了 --artifacts-only 标志,客户端应通过包含 hosthost:port 定义来明确与此服务器交互以进行工件引用。否则,所有工件请求都将路由到 MLflow 跟踪服务器,从而违背了运行不同工件服务器的目的。

保护跟踪服务器

内置安全中间件

MLflow 3.5.0+ 包含安全中间件,可自动防御常见的 Web 漏洞:

  • DNS 重绑定防护:验证 Host 头以防止对内部服务的攻击
  • CORS 防护:控制哪些 Web 应用程序可以访问您的 API
  • 点击劫持防御:X-Frame-Options 头控制 iframe 嵌入

使用简单的命令行选项配置这些功能:

bash
mlflow server --host 0.0.0.0 \
--allowed-hosts "mlflow.company.com" \
--cors-allowed-origins "https://app.company.com"

有关详细的配置选项,请参阅 安全配置

身份验证与加密

对于生产部署,我们建议使用反向代理 (NGINX, Apache httpd) 或 VPN 来添加:

  • TLS/HTTPS 加密以实现安全通信
  • 身份验证,通过代理身份验证头

您可以使用以下环境变量将身份验证头传递给 MLflow:

  • MLFLOW_TRACKING_USERNAMEMLFLOW_TRACKING_PASSWORD - 用于 HTTP 基本身份验证的用户名和密码。要使用基本身份验证,必须设置这两个环境变量。
  • MLFLOW_TRACKING_TOKEN - 用于 HTTP Bearer 身份验证的令牌。如果设置了基本身份验证,则优先使用基本身份验证。
  • MLFLOW_TRACKING_INSECURE_TLS - 如果设置为字面值 true,MLflow 不会验证 TLS 连接,这意味着它不会为 https:// 跟踪 URI 验证证书或主机名。不建议在生产环境中使用此标志。如果设置为 true,则不得设置 MLFLOW_TRACKING_SERVER_CERT_PATH
  • MLFLOW_TRACKING_SERVER_CERT_PATH - 要使用的 CA 证书包路径。设置 requests.request 函数的 verify 参数(请参阅 requests 主接口)。当使用自签名服务器证书时,可以使用此路径在客户端进行验证。如果设置了此项,则不得设置 MLFLOW_TRACKING_INSECURE_TLS(即必须为 false)。
  • MLFLOW_TRACKING_CLIENT_CERT_PATH - SSL 客户端证书文件 (.pem) 的路径。设置 requests.request 函数的 cert 参数(请参阅 requests 主接口)。这可用于使用(自签名)客户端证书。

有关 Notebook 集成和 UI 嵌入选项,请参阅 网络安全 配置。

跟踪服务器版本控制

运行在服务器上的 MLflow 版本可以通过查询 /version 端点找到。这可用于在运行实验之前检查客户端的 MLflow 版本是否与远程跟踪服务器同步。例如:

python
import requests
import mlflow

response = requests.get("http://<mlflow-host>:<mlflow-port>/version")
assert response.text == mlflow.__version__ # Checking for a strict version match

模型版本源验证

跟踪服务器可以配置为使用正则表达式模式验证模型版本源。此安全功能有助于确保只有来自已批准源的模型版本才会注册到您的模型注册表中。

配置

启动跟踪服务器时设置 MLFLOW_CREATE_MODEL_VERSION_SOURCE_VALIDATION_REGEX 环境变量:

bash
export MLFLOW_CREATE_MODEL_VERSION_SOURCE_VALIDATION_REGEX="^mlflow-artifacts:/.*$"
mlflow server --host 0.0.0.0 --port 5000

设置此环境变量后,跟踪服务器将根据指定的正则表达式模式验证模型版本创建请求中的 source 参数。如果源不匹配该模式,请求将被拒绝并返回错误。

示例:限制为 MLflow 工件

仅允许来自 MLflow 工件存储的模型版本:

bash
export MLFLOW_CREATE_MODEL_VERSION_SOURCE_VALIDATION_REGEX="^mlflow-artifacts:/.*$"
mlflow server --host 0.0.0.0 --port 5000

在此配置下:

python
import mlflow
from mlflow import MlflowClient

client = MlflowClient("https://:5000")

# This will work - source matches the pattern
client.create_model_version(
name="my-model",
source="mlflow-artifacts://1/artifacts/model",
run_id="abc123",
)

# This will fail - source doesn't match the pattern
client.create_model_version(
name="my-model",
source="s3://my-bucket/model",
run_id="def456",
) # Raises MlflowException: Invalid model version source

示例:限制为特定的 S3 存储桶

仅允许来自特定 S3 存储桶的模型版本:

bash
export MLFLOW_CREATE_MODEL_VERSION_SOURCE_VALIDATION_REGEX="^s3://(production-models|staging-models)/.*$"
mlflow server --host 0.0.0.0 --port 5000

此模式将允许如下源:

  • s3://production-models/model-v1/
  • s3://staging-models/experiment-123/model/

但会拒绝如下源:

  • s3://untrusted-bucket/model/
  • file:///local/path/model
注意
  • 如果未设置环境变量,则不执行源验证。
  • 验证仅适用于 /mlflow/model-versions/create API 端点。
  • 正则表达式使用 Python 的 re.search() 函数应用。
  • 使用标准的正则表达式语法进行模式匹配。

获取服务器版本

运行在服务器上的 MLflow 版本可以通过查询 /version 端点找到。这可用于在运行实验之前检查客户端的 MLflow 版本是否与远程跟踪服务器同步。例如:

python
import requests
import mlflow

response = requests.get("http://<mlflow-host>:<mlflow-port>/version")
assert response.text == mlflow.__version__ # Checking for a strict version match

处理上传/下载大工件时的超时问题

当通过启用了工件代理的跟踪服务器上传或下载大工件时,服务器可能需要很长时间来处理请求。如果超过超时限制,服务器将终止请求,导致客户端请求失败。

客户端代码示例:

python
import mlflow

mlflow.set_tracking_uri("<TRACKING_SERVER_URI>")
with mlflow.start_run():
mlflow.log_artifact("large.txt")

客户端回溯 (traceback):

text
Traceback (most recent call last):
File "/Users/user/python3.10/site-packages/requests/adapters.py", line 486, in send
resp = conn.urlopen(
File "/Users/user/python3.10/site-packages/urllib3/connectionpool.py", line 826, in urlopen
return self.urlopen(
...
File "/Users/user/python3.10/site-packages/urllib3/connectionpool.py", line 798, in urlopen
retries = retries.increment(
File "/Users/user/python3.10/site-packages/urllib3/util/retry.py", line 592, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='mlflow.example.com', port=443): Max retries exceeded with url: ... (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:2426)')))
During handling of the above exception, another exception occurred:

跟踪服务器日志:

bash
INFO: Started server process [82]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit)
...
WARNING: Request timeout exceeded
ERROR: Exception in ASGI application

为了缓解此问题,可以在启动服务器时使用 --uvicorn-opts 选项增加超时时间,如下所示:

bash
mlflow server --uvicorn-opts "--timeout-keep-alive=120" ...

对于仍在使用 gunicorn(通过 --gunicorn-opts)的用户,等效命令为:

bash
mlflow server --gunicorn-opts "--timeout=120" ...

有关更多配置选项,请参阅 uvicorn 设置文档

命令行选项完整列表

请运行 mlflow server --help 获取命令行选项的完整列表。