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)
服务器有许多配置选项,有关更多详细信息,请参阅 配置服务器。
服务器默认监听 https://:5000,并且只接受来自本地机器的连接。要让服务器接受来自其他机器的连接,您需要传递 --host 0.0.0.0 来监听所有网络接口(或特定的接口地址)。在Kubernetes pod 或 Docker 容器中运行服务器时,通常需要进行此配置。
MLflow 3.5.0+ 包含内置安全中间件,可防止 DNS 重新绑定和 CORS 攻击。在使用 --host 0.0.0.0 时,请配置 --allowed-hosts 选项来指定哪些域名可以访问您的服务器。有关详细信息,请参阅 安全配置。
记录到 Tracking Server
一旦 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() 调用将向您的远程 tracking server 发出 API 请求。
- Python
- 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")
with mlflow.start_run():
mlflow.log_param("a", 1)
mlflow.log_metric("b", 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")
在 Databricks 上,mlflow.set_experiment() 中的实验名称必须是工作区中有效的绝对路径(例如,/Workspace/Users/mlflow-experiments/my-experiment)。
配置服务器
本节介绍如何为一些常见用例配置 tracking server。有关完整的命令行选项列表,请运行 mlflow server --help。
后端存储
默认情况下,tracking server 将运行的元数据记录到本地文件系统下的 ./mlruns 目录。您可以通过添加 --backend-store-uri 选项来配置不同的后端存储。
mlflow server --backend-store-uri sqlite:///my.db
这将创建一个名为 my.db 的 SQLite 数据库,并将其放在当前目录中,客户端的日志记录请求将指向此数据库。
远程构件存储
使用 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 可访问的构件的角色”。有关更多详细信息,请参阅 管理访问。
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 客户端仍然发出最少的 HTTP 请求到 tracking server 来获取正确的远程存储 URI,但可以直接上传/下载构件到/从远程存储。虽然这可能不是访问和安全治理的最佳实践,但当您想避免通过 tracking server 代理构件的开销时,它可能很有用。
如果 MLflow 服务器未配置 --serve-artifacts 选项,客户端会直接将构件推送到构件存储。默认情况下,它不会通过 tracking server 进行代理。
因此,客户端需要直接访问构件存储。有关设置这些凭据的说明,请参阅 构件存储文档。
当创建一个实验时,来自 tracking server 配置的构件存储位置会被记录在该实验的元数据中。在启用代理构件存储时,在非代理模式下运行 tracking server 时创建的任何现有实验将继续使用非代理构件位置。为了使用代理构件日志记录,必须创建一个新实验。如果启用 -serve-artifacts 模式下的 tracking server 的目的是消除客户端对底层存储进行身份验证的需要,那么应该为客户端创建新实验,以便在迁移后 tracking server 可以处理身份验证。
可选择使用 Tracking Server 实例专门处理构件
MLflow Tracking Server 可以配置为使用不同的后端存储和构件存储,并为客户端提供一个统一的端点。
然而,如果 tracking server 请求量足够大并注意到性能问题,tracking server 可以配置为以 --artifacts-only 模式运行,并与指定了 --no-serve-artifacts 的实例协同工作。此配置确保构件的处理与所有其他 tracking server 事件处理隔离。
当 tracking server 配置为 --artifacts-only 模式时,除构件处理任务(即模型日志记录、加载模型、日志记录构件、列出构件等)以外的任何任务都将返回 HTTPError。以下是一个 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.
使用额外的 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"
有关详细配置选项,请参阅 安全配置。
身份验证和加密
对于生产部署,我们建议使用反向代理(NGINX、Apache httpd)或 VPN 来添加:
- TLS/HTTPS 加密,用于安全通信。
- 身份验证,通过代理身份验证头。
您可以使用这些环境变量将身份验证头传递给 MLflow:
MLFLOW_TRACKING_USERNAME和MLFLOW_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参数(请参阅 requests 主接口)。当您使用自签名服务器证书时,可以使用此选项在客户端进行验证。如果设置了此选项,则MLFLOW_TRACKING_INSECURE_TLS必须未设置(即为 false)。MLFLOW_TRACKING_CLIENT_CERT_PATH- SSL 客户端证书文件(.pem)的路径。设置requests.request函数的cert参数(请参阅 requests 主接口)。这可用于使用(自签名)客户端证书。
有关笔记本集成和 UI 嵌入选项,请参阅 UI 访问与笔记本。
Tracking Server 版本管理
服务器上运行的 MLflow 版本可以通过查询 /version 端点来找到。这可用于在运行实验之前检查客户端 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()函数应用正则表达式。 - 使用标准的正则表达式语法进行模式匹配。
处理上传/下载大型构件时的超时
当通过 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 设置文档。