MLflow 跟踪服务器
MLflow 跟踪服务器是一个独立的 HTTP 服务器,为跟踪运行/实验提供多个 REST API 端点。虽然 MLflow 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)
有很多选项可以配置服务器,有关详细信息,请参阅 配置服务器。
默认情况下,服务器监听 https://:5000,并且只接受来自本地机器的连接。要让服务器接受来自其他机器的连接,您需要传递 --host 0.0.0.0 以监听所有网络接口(或特定的接口地址)。这通常是运行服务器时所需的配置 在 Kubernetes pod 或 Docker 容器中。
MLflow 3.5.0+ 包含内置的安全中间件,用于防止 DNS 重新绑定和 CORS 攻击。当使用 --host 0.0.0.0 时,配置 --allowed-hosts 选项以指定哪些域可以访问您的服务器。有关详细信息,请参阅 安全配置。
当在具有只读根文件系统的容器中运行时(Kubernetes 中常见,设置 securityContext.readOnlyRootFilesystem: true),使用 --artifacts-destination 配置远程工件存储(默认启用工件服务)。跟踪服务器在启动时不会在本地创建目录,如果使用远程工件存储,这使其与只读环境兼容。
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 API,例如 mlflow.start_run()、mlflow.log_param()、mlflow.start_trace() 会向您的远程跟踪服务器发出 API 请求并记录数据。
- Python
- TypeScript
- R
- Scala
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)
import * as mlflow from "mlflow-tracing";
mlflow.init({
trackingUri: "<your-tracking-server-uri>",
experimentId: "<your-experiment-id>",
});
const myFunc = mlflow.trace(
(a: number, b: number) => {
return a + b;
},
{ name: 'my-func' }
)
myFunc(1, 2);
library(mlflow)
install_mlflow()
remote_server_uri = "..." # set to your server URI
mlflow_set_tracking_uri(remote_server_uri)
mlflow_set_experiment("/my-experiment")
mlflow_log_param("a", "1")
import org.mlflow.tracking.MlflowClient
val remoteServerUri = "..." // set to your server URI
val client = new MlflowClient(remoteServerUri)
val experimentId = client.createExperiment("my-experiment")
client.setExperiment(experimentId)
val run = client.createRun(experimentId)
client.logParam(run.getRunId(), "a", "1")
配置服务器
本节介绍如何针对一些常见用例配置跟踪服务器。本节要求您对跟踪服务器架构有基本的了解,如果您还不熟悉,请访问 架构概述。
后端存储
默认情况下,跟踪服务器使用 SQLite 数据库 (sqlite:///mlflow.db) 来存储运行元数据。您可以通过添加 --backend-store-uri 选项来配置不同的后端存储
# 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。
远程工件存储
使用跟踪服务器进行代理工件访问(默认)
默认情况下,跟踪服务器将工件存储在其本地文件系统下的 ./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>/mlartifactshttp://<host>/mlartifactsmlflow-artifacts://<host>/mlartifactsmlflow-artifacts://<host>:<port>/mlartifactsmlflow-artifacts:/mlartifacts
MLflow 客户端会为每个运行缓存工件位置信息。因此,不建议在运行终止之前更改运行的工件位置。
使用跟踪服务器而*不*代理工件访问
在某些情况下,您可能希望直接访问远程存储而无需通过跟踪服务器代理。在这种情况下,您可以使用 --no-serve-artifacts 标志启动服务器,并将 --default-artifact-root 设置为您希望重定向请求的远程存储 URI。
mlflow server --no-serve-artifacts --default-artifact-root s3://my-bucket
使用此设置,MLflow 客户端仍然向跟踪服务器发出最少的 HTTP 请求以下载正确的远程存储 URI,但可以直接将工件上传到/从远程存储下载工件。虽然这可能不是访问和安全治理的好做法,但在您想避免通过跟踪服务器代理工件的开销时可能很有用。
两个选项 --serve-artifacts 和 --default-artifact-root 看起来相似,但用于不同的目的。当您选择错误的选项时,工件日志记录请求将不会通过预期的路径,并可能导致访问问题。经验法则是
- 希望服务器代理上传? 指定
--artifacts-destination选项,并且 不设置--default-artifact-root。新的实验将获得mlflow-artifacts:/...运行 URI,客户端通过服务器上传和下载工件。凭据由跟踪服务器管理,客户端无需设置它们。 - 希望客户端直接写入存储? 设置
--default-artifact-root选项和--no-serve-artifacts。运行将获得s3://.../gs://...URI,并且客户端必须具有访问存储的凭据。
如果使用 --no-serve-artifacts 选项启动 MLflow 服务器,客户端会直接将工件推送到工件存储。默认情况下,它不会通过跟踪服务器代理这些工件。
因此,客户端需要直接访问工件存储。有关设置这些凭据的说明,请参阅 工件存储文档。
当创建一个实验时,跟踪服务器配置中的工件存储位置会记录在实验的元数据中。启用代理工件存储时,任何在非代理模式下运行跟踪服务器时创建的现有实验将继续使用非代理工件位置。为了使用代理工件记录,必须创建一个新实验。如果启用 -serve-artifacts 模式的跟踪服务器的目的是消除客户端需要对底层存储进行身份验证的需求,则应为客户端创建新实验,以便跟踪服务器可以在此迁移后处理身份验证。
可选地使用 MLflow 跟踪服务器实例专用于工件处理
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 基础架构时可能很有用。将工件处理的耗时且计算密集型的任务与另一个跟踪服务器处理这两种类型有效载荷的更快、更高流量的元数据功能分离,有助于最大限度地减少单个 MLflow 服务器处理两者的负担。
如果 MLflow 服务器正在运行 --artifacts-only 标志,客户端应通过包含工件的 URI 位置引用的 host 或 host:port 定义与此服务器显式交互。否则,所有工件请求都将路由到 MLflow 跟踪服务器,从而失去了运行独立工件服务器的目的。
保护跟踪服务器
内置安全中间件
MLflow 3.5.0+ 包含安全中间件,可自动防止常见的 Web 漏洞
- DNS 重新绑定保护:验证 Host 标头以防止对内部服务的攻击
- CORS 保护:控制哪些 Web 应用程序可以访问您的 API
- 点击劫持预防:X-Frame-Options 标头控制 iframe 嵌入
使用简单的命令行选项配置这些功能
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_USERNAME和MLFLOW_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 主接口)。这可用于使用(自签名)客户端证书。
有关笔记本集成和 UI 嵌入选项,请参阅 网络安全 配置。
跟踪服务器版本控制
可以通过查询 /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/createAPI 端点。 - 正则表达式是使用 Python 的
re.search()函数应用的。 - 使用标准的正则表达式语法进行模式匹配。
获取服务器版本
可以通过查询 /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
处理上传/下载大工件时的超时
当通过跟踪服务器上传或下载大工件并启用工件代理时,服务器可能需要很长时间来处理请求。如果超过超时限制,服务器将终止请求,导致客户端上的请求失败。
客户端代码示例
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 设置文档。
命令行选项的完整列表
请运行 mlflow server --help 以获取命令行选项的完整列表。