跳到主要内容

MLflow 追踪服务器

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

  • 协作:多个用户可以将运行日志记录到相同的端点,并查询其他用户记录的运行和模型。
  • 分享结果:追踪服务器还提供追踪 UI 端点,团队成员可以轻松探索彼此的结果。
  • 集中式访问:追踪服务器可以作为元数据和工件远程访问的代理运行,从而更容易地保护和审计数据访问。

启动追踪服务器

启动追踪服务器就像运行以下命令一样简单

mlflow server --host 127.0.0.1 --port 8080

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

[2023-11-01 10:28:12 +0900] [28550] [INFO] Starting gunicorn 20.1.0
[2023-11-01 10:28:12 +0900] [28550] [INFO] Listening at: http://127.0.0.1:8080 (28550)
[2023-11-01 10:28:12 +0900] [28550] [INFO] Using worker: sync
[2023-11-01 10:28:12 +0900] [28552] [INFO] Booting worker with pid: 28552
[2023-11-01 10:28:12 +0900] [28553] [INFO] Booting worker with pid: 28553
[2023-11-01 10:28:12 +0900] [28555] [INFO] Booting worker with pid: 28555
[2023-11-01 10:28:12 +0900] [28558] [INFO] Booting worker with pid: 28558
...

有许多选项可以配置服务器,有关更多详细信息,请参阅配置服务器

重要

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

请注意,出于安全原因,不建议在公共网络上运行服务器时这样做。您应该考虑使用反向代理(如 NGINX 或 Apache httpd),或通过 VPN 连接(有关更多详细信息,请参阅安全追踪服务器)。

日志记录到追踪服务器

追踪服务器启动后,通过将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)
注意

在 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 请求以获取工件。

重要

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

追踪服务器将客户端追踪请求中的 uri mlflow-artifacts:/ 解析为否则明确的对象存储目的地(例如,“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。

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

通过此设置,MLflow 客户端仍会向追踪服务器发出最低限度的 HTTP 请求以获取正确的远程存储 URI,但可以直接将工件上传到/从远程存储下载工件。虽然这可能不是访问和安全治理的最佳实践,但在您希望避免通过追踪服务器代理工件的开销时,它可能很有用。

注意

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

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

注意

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

可选地专门使用追踪服务器实例来处理工件

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

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

当追踪服务器配置为--artifacts-only模式时,除了与工件处理相关的任务(即模型日志记录、加载模型、日志记录工件、列出工件等)之外的任何任务都将返回 HTTPError。请参阅以下客户端 REST 调用 Python 示例,该示例尝试从配置为--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.

使用额外的 MLflow 服务器专门处理工件对于大规模 MLOps 基础设施非常有用。将运行时间更长、计算密集型任务(工件处理)与更快、更高容量的元数据功能(其他追踪 API 请求)解耦有助于最大限度地减少单个 MLflow 服务器处理两种类型负载的负担。

注意

如果 MLflow 服务器以--artifacts-only标志运行,则客户端应通过在工件的 uri 位置引用中包含hosthost:port定义来明确地与此服务器交互。否则,所有工件请求都将路由到 MLflow 追踪服务器,从而失去运行独立工件服务器的目的。

安全追踪服务器

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

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

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

追踪服务器版本控制

可以通过查询/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参数。如果源与模式不匹配,则请求将被拒绝并返回错误。

示例:限制为 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("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 存储桶的模型版本

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()函数应用。
  • 使用标准正则表达式语法进行模式匹配。

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

通过启用了工件代理的追踪服务器上传或下载大型工件时,服务器可能需要很长时间才能处理请求。如果超过超时限制(默认为 30 秒),服务器将重新启动工作进程,导致客户端请求失败。

客户端代码示例

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:

追踪服务器日志

[2025-01-10 11:59:00 +0000] [82] [INFO] Starting gunicorn 20.1.0
[2025-01-10 11:59:00 +0000] [82] [DEBUG] Arbiter booted
[2025-01-10 11:59:00 +0000] [82] [INFO] Listening at: http://0.0.0.0:5000 (82)
...
[2025-01-10 11:59:01 +0000] [82] [CRITICAL] WORKER TIMEOUT (pid:86)
[2025-01-10 11:59:01 +0000] [86] [INFO] Worker exiting (pid: 86)
[2025-01-10 11:59:01 +0000] [179] [INFO] Booting worker with pid: 179

为了缓解此问题,可以通过在启动服务器时使用--gunicorn-opts选项来增加超时时长,如下所示

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

请参阅 Gunicorn 文档中的超时