跳至主内容

MLflow 跟踪服务器

MLflow tracking server 是一个独立的 HTTP 服务器,为跟踪运行/实验提供多个 REST API 端点。尽管可以在本地环境中使用 MLflow Tracking,但在团队开发工作流程中托管一个跟踪服务器更为强大:

  • 协作: 多个用户可以向相同的端点记录运行,并查询其他用户记录的运行和模型。
  • 共享结果:跟踪服务器还提供了Tracking UI端点,团队成员可以轻松地查看彼此的结果。
  • 集中访问: 跟踪服务器可以作为远程元数据和工件访问的代理运行,从而更容易确保对数据访问的安全性并进行审计。

启动跟踪服务器

启动跟踪服务器只需运行以下命令:

mlflow server --host 127.0.0.1 --port 8080

一旦服务器开始运行,你应该会看到以下输出:

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)

有许多选项可以配置服务器,更多细节请参见 Configure Server

important

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

请注意,出于安全原因,不建议在公共网络上运行的服务器上这样做。你应该考虑使用像 NGINX 或 Apache httpd 这样的反向代理,或通过 VPN 连接(有关详细信息,请参见 Secure Tracking Server)。

向跟踪服务器记录日志

一旦跟踪服务器启动,通过将 MLFLOW_TRACKING_URI 环境变量设置为服务器的 URI 以及其协议和端口(例如,http://10.0.0.1:5000)来连接本地客户端,或调用 mlflow.set_tracking_uri()

mlflow.start_run()mlflow.log_param()mlflow.log_metric() 这些调用随后会向你的远程跟踪服务器发出 API 请求。

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")
with mlflow.start_run():
mlflow.log_param("a", 1)
mlflow.log_metric("b", 2)
note

在 Databricks 上,mlflow.set_experiment() 中的实验名称必须是工作区中的有效绝对路径(例如,/Workspace/Users/mlflow-experiments/my-experiment)。

配置服务器

本节说明如何为一些常见用例配置跟踪服务器。请运行 mlflow server --help 查看命令行选项的完整列表。

后端存储

默认情况下,跟踪服务器会将运行元数据记录到本地文件系统的 ./mlruns 目录下。 你可以通过添加 --backend-store-uri 选项来配置不同的后端存储:

示例
mlflow server --backend-store-uri sqlite:///my.db

这将在当前目录创建一个 SQLite 数据库 my.db,并且来自客户端的日志记录请求将被指向该数据库。

远程工件存储

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

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

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

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

important

如果您使用远程存储,必须为服务器配置访问工件的凭据。请注意,MLflow 的工件代理访问服务使用户能够拥有一个对所有可被 Tracking Server 访问的工件的假定访问角色。有关更多详细信息,请参阅 Manage Access

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

  • https://:/mlartifacts
  • http:///mlartifacts
  • mlflow-artifacts:///mlartifacts
  • mlflow-artifacts://:/mlartifacts
  • mlflow-artifacts:/mlartifacts
important

MLflow 客户端按每个运行缓存工件位置信息。因此,不建议在运行结束之前更改该运行的工件位置。

在不代理工件访问的情况下使用跟踪服务器

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

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

在此设置下,MLflow 客户端仍然对跟踪服务器发出最少的 HTTP 请求以获取正确的远程存储 URI,但可以直接向远程存储上传工件或从远程存储下载工件。虽然这在访问和安全治理方面可能并不是一个好的做法,但当您想避免通过跟踪服务器代理工件带来的开销时,这可能很有用。

note

如果 MLflow 服务器 未配置 --serve-artifacts 选项,客户端会直接将工件推送到工件存储。默认情况下,它不会通过跟踪服务器代理这些。

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

note

当创建实验时,跟踪服务器配置中的 artifact 存储位置会记录在该实验的元数据中。启用代理的 artifact 存储后,在跟踪服务器以非代理模式运行时创建的任何现有实验将继续使用非代理的 artifact 存储位置。若要使用代理的 artifact 日志记录,必须创建新的实验。如果启用跟踪服务器的 -serve-artifacts 模式的目的是消除客户端对底层存储的认证需求,则应为客户端创建新的实验,以便在迁移后由跟踪服务器处理认证。

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

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

但是,如果跟踪服务器请求的数量足够大并且注意到性能问题,则可以将跟踪服务器配置为以 --artifacts-only 模式提供服务,与一个指定了 --no-serve-artifacts 的实例协同运行。此配置确保工件的处理与所有其他跟踪服务器事件处理相互隔离。

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

# Launch the artifact-only server
mlflow server --artifacts-only ...
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.

在大规模 MLOps 基础设施中,使用一个额外的 MLflow 服务器专门处理 artifact(工件)可能很有用。将 artifact 处理中运行时间更长且计算量更大的任务,与其他 Tracking API 请求中更快且更高吞吐量的元数据功能解耦,可以帮助将原本单一 MLflow 服务器同时处理这两类负载的负担降到最低。

note

如果 MLflow 服务以 --artifacts-only 标志运行,客户端应通过显式包含 hosthost:port 的定义来与该服务器交互,以用于工件的 URI 位置引用。否则,所有工件请求都会路由到 MLflow Tracking 服务器,从而失去运行独立工件服务器的目的。

安全跟踪服务器

The --host 选项会将服务暴露在所有接口上。如果在生产环境中运行服务器,我们建议不要广泛暴露内置服务器(因为它未经身份验证且未加密),而应将其置于像 NGINX 或 Apache httpd 这样的反向代理之后,或通过 VPN 连接。

然后,您可以使用这些环境变量将身份验证头传递给MLflow。

  • MLFLOW_TRACKING_USERNAMEMLFLOW_TRACKING_PASSWORD - 用于 HTTP 基本身份验证的用户名和密码。要使用基本身份验证,您必须设置 both 环境变量。
  • 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 main interface)。当您使用自签名服务器证书时,可以在客户端使用此项进行验证。如果设置了此项,则不得设置 MLFLOW_TRACKING_INSECURE_TLS(false)。
  • MLFLOW_TRACKING_CLIENT_CERT_PATH - 到 ssl 客户端证书文件(.pem)的路径。设置 cert 参数 of the requests.request function (see requests main interface)。这可用于使用(自签名的)客户端证书。

跟踪服务器版本管理

可以通过查询 /version 端点来获取服务器上运行的 MLflow 的版本。 这可用于在运行实验之前检查客户端侧的 MLflow 版本是否与远程跟踪服务器保持最新。 例如:

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 环境变量:

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

用法

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

示例:限制为 MLflow 工件

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

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

使用此配置:

import mlflow
from mlflow import MlflowClient

client = MlflowClient("http://localhost: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 存储桶的模型版本:

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
note
  • 如果未设置环境变量,则不会执行源验证。
  • 该验证仅适用于 /mlflow/model-versions/create API 端点。
  • 正则表达式是通过 Python 的 re.search() 函数应用的。
  • 使用标准正则表达式语法进行模式匹配。

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

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

示例客户端代码:

import mlflow

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

客户端回溯:

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:

跟踪服务器日志:

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 选项来增加超时时长,如下所示:

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

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

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

有关更多配置选项,请参阅 uvicorn settings documentation