MLflow Tracking Server
MLflow tracking server 是一个独立的 HTTP 服务器,它提供了多个 REST API 端点用于跟踪运行/实验。虽然 MLflow Tracking 可以在本地环境中使用,但在团队开发工作流中托管一个 tracking server 非常强大。
- 协作:多个用户可以向同一端点记录运行,并查询其他用户记录的运行和模型。
- 共享结果:tracking server 还提供 Tracking UI 端点,团队成员可以在此轻松探索彼此的结果。
- 集中访问:tracking server 可以作为元数据和工件的远程访问代理运行,从而更容易地保护和审计对数据的访问。
启动 Tracking Server
启动 tracking server 就像运行以下命令一样简单:
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。
服务器默认监听 https://:5000,并且仅接受来自本地计算机的连接。要让服务器接受来自其他计算机的连接,您需要传递 --host 0.0.0.0 来监听所有网络接口(或特定接口地址)。这通常是在 Kubernetes pod 或 Docker 容器 中运行服务器时所需的配置。
MLflow 3.5.0+ 包含内置的安全中间件,以防止 DNS 重新绑定和 CORS 攻击。当使用 --host 0.0.0.0 时,请配置 --allowed-hosts 选项来指定哪些域可以访问您的服务器。有关详细信息,请参阅 Security Configuration。
记录到 Tracking Server
启动 tracking server 后,可以通过设置 MLFLOW_TRACKING_URI 环境变量为服务器的 URI(包括其 scheme 和 port,例如 http://10.0.0.1:5000)来连接本地客户端,或者调用 mlflow.set_tracking_uri()。
MLflow API,如 mlflow.start_run()、mlflow.log_param()、mlflow.start_trace() 会向您的远程 tracking server 发送 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")
配置服务器
本节介绍如何为一些常见用例配置 tracking server。本节要求您对 tracking server 架构有基本了解,如果您还不熟悉,请访问 Architecture Overview。
后端存储
默认情况下,tracking server 使用 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。
远程工件存储
使用 Tracking Server 进行代理工件访问(默认)
默认情况下,tracking server 将工件存储在本地文件系统的 ./mlartifacts 目录下。要将 tracking server 配置为连接到远程存储并提供工件,请使用 --artifacts-destination 标志启动服务器。
mlflow server \
--host 0.0.0.0 \
--port 8885 \
--artifacts-destination s3://my-bucket
通过此设置,MLflow server 作为访问远程工件的代理。MLflow 客户端向服务器发送 HTTP 请求来获取工件。
如果您正在使用远程存储,则必须配置服务器访问工件的凭据。请注意,MLflow 工件代理访问服务允许用户对 tracking server 可访问的所有工件假定访问权限。有关详细信息,请参阅 Manage Access。
tracking server 将客户端的跟踪请求中的 mlflow-artifacts:/ URI 解析为显式的对象存储目标(例如,“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 客户端会缓存每个运行的工件位置信息。因此,不建议在运行的运行结束之前修改其工件位置。
使用不代理工件访问的 Tracking Server
在某些情况下,您可能希望直接访问远程存储而不通过 tracking server 进行代理。在这种情况下,您可以使用 --no-serve-artifacts 标志启动服务器,并将 --default-artifact-root 设置为您希望重定向请求的远程存储 URI。
mlflow server --no-serve-artifacts --default-artifact-root s3://my-bucket
通过此设置,MLflow 客户端仍然向 tracking server 发送最少的 HTTP 请求以获取正确的远程存储 URI,但可以直接将工件上传/下载到/从远程存储。虽然这对于访问和安全治理来说可能不是一个好习惯,但在您想避免通过 tracking server 代理工件的开销时可能会有用。
--serve-artifacts 和 --default-artifact-root 这两个选项看起来相似,但用途不同。如果您选择了错误的选项,工件记录请求将不会按照预期路径进行,并可能导致访问问题。经验法则是:
- 希望服务器代理上传? 指定
--artifacts-destination选项,并且不要设置--default-artifact-root。新实验将获得mlflow-artifacts:/...运行 URI,客户端通过服务器上传和下载工件。凭据由 tracking server 管理,客户端无需设置它们。 - 希望客户端直接写入存储? 设置
--default-artifact-root选项和--no-serve-artifacts。运行将获得s3://.../gs://...URI,并且客户端必须具有访问存储的凭据。
如果 MLflow 服务器使用 --no-serve-artifacts 选项启动,客户端将直接将工件推送到工件存储。默认情况下,它不会通过 tracking server 代理这些工件。
因此,客户端需要直接访问工件存储。有关设置这些凭据的说明,请参阅 Artifact Stores 文档。
当创建一个实验时,tracking server 配置中的工件存储位置会记录在实验的元数据中。当启用代理工件存储时,在非代理模式下运行 tracking server 时创建的任何现有实验将继续使用非代理工件位置。为了使用代理工件记录,必须创建一个新实验。如果启用 tracking server 的目的是在 -serve-artifacts 模式下消除客户端对底层存储的身份验证需求,则应创建新实验供客户端使用,以便在迁移后 tracking server 可以处理身份验证。
可选地使用仅用于工件处理的 Tracking Server 实例
MLflow Tracking Server 可以配置为使用不同的后端存储和工件存储,并为客户端提供一个统一的端点。
但是,如果 tracking server 请求量足够大且出现性能问题,tracking server 可以配置为 --artifacts-only 模式运行,与指定 --no-serve-artifacts 的实例协同工作。此配置确保工件的处理与所有其他 tracking server 事件处理相隔离。
当 tracking server 配置为 --artifacts-only 模式时,除工件处理相关的任务(即,模型记录、加载模型、记录工件、列出工件等)外,任何其他任务都将返回 HTTPError。以下是客户端在 Python 中尝试从配置为 --artifacts-only 模式的服务器列出实验的 REST 调用示例:
# 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 其他 Tracking API 请求中更快、更高吞吐量的元数据功能解耦,可以帮助减轻单个 MLflow 服务器同时处理这两种类型负载的负担。
如果 MLflow 服务器使用 --artifacts-only 标志运行,客户端应通过在 URI 位置引用中包含 host 或 host:port 来明确地与该服务器交互。否则,所有工件请求都将路由到 MLflow Tracking server,从而违背运行独立工件服务器的目的。
安全地使用 Tracking Server
内置安全中间件
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"
有关详细配置选项,请参阅 Security Configuration。
身份验证和加密
对于生产部署,我们建议使用反向代理(NGINX、Apache httpd)或 VPN 来添加:
- TLS/HTTPS 加密以实现安全通信。
- 身份验证通过代理身份验证头。
您可以使用以下环境变量将身份验证头传递给 MLflow:
MLFLOW_TRACKING_USERNAME和MLFLOW_TRACKING_PASSWORD- 用于 HTTP Basic 身份验证的用户名和密码。要使用 Basic 身份验证,您必须设置两个环境变量。MLFLOW_TRACKING_TOKEN- 用于 HTTP Bearer 身份验证的令牌。如果设置了 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参数(请参阅 requests main interface)。当您使用自签名服务器证书时,可以使用此选项在客户端进行验证。如果设置了此项,则MLFLOW_TRACKING_INSECURE_TLS必须未设置(即为 false)。MLFLOW_TRACKING_CLIENT_CERT_PATH- SSL 客户端证书文件(.pem)的路径。设置requests.request函数的cert参数(请参阅 requests main interface)。这可用于使用(自签名)客户端证书。
有关笔记本集成和 UI 嵌入选项,请参阅 Network Security 配置。
Tracking Server 版本管理
可以通过查询 /version 端点来找到在服务器上运行的 MLflow 的版本。这可以用于在运行实验之前检查 MLflow 的客户端版本是否与远程 tracking server 同步。例如:
import requests
import mlflow
response = requests.get("http://<mlflow-host>:<mlflow-port>/version")
assert response.text == mlflow.__version__ # Checking for a strict version match
模型版本源验证
tracking server 可以配置为使用正则表达式模式验证模型版本源。此安全功能有助于确保只有来自已批准来源的模型版本才能在您的模型注册表中注册。
配置
在启动 tracking server 时设置 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
当设置了此环境变量时,tracking server 将使用指定的正则表达式模式验证模型版本创建请求中的 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 的客户端版本是否与远程 tracking server 同步。例如:
import requests
import mlflow
response = requests.get("http://<mlflow-host>:<mlflow-port>/version")
assert response.text == mlflow.__version__ # Checking for a strict version match
处理上传/下载大工件时的超时问题
当通过 tracking server 上传或下载大工件(启用了工件代理)时,服务器可能需要很长时间来处理请求。如果超过超时限制,服务器将终止请求,导致客户端请求失败。
客户端代码示例
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:
Tracking Server 日志
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。
命令行选项完整列表
请运行 mlflow server --help 以获取完整的命令行选项列表。