Instalación de MLflow para Gestión del Ciclo de Vida de ML

MLflow es la plataforma open source más extendida para gestionar el ciclo de vida completo de proyectos de machine learning: seguimiento de experimentos, comparación de métricas, registro de modelos y despliegue. Instalado en un servidor Linux, MLflow centraliza todos los experimentos del equipo, almacena los artefactos y permite comparar fácilmente resultados de diferentes entrenamientos. Esta guía cubre la instalación del servidor MLflow con almacenamiento en base de datos y artefactos en S3, junto con su integración en flujos de trabajo de entrenamiento.

Requisitos Previos

  • Servidor Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+)
  • Python 3.8 o superior
  • MySQL o PostgreSQL para el backend de metadatos
  • S3 o almacenamiento local para artefactos
  • Acceso root o sudo
# Instalar dependencias del sistema
sudo apt-get update
sudo apt-get install -y python3-pip python3-venv mysql-server

# En CentOS/Rocky
sudo dnf install -y python3-pip mysql-server

Instalación de MLflow

# Crear un entorno virtual dedicado para MLflow
python3 -m venv /opt/mlflow-venv
source /opt/mlflow-venv/bin/activate

# Instalar MLflow con soporte para MySQL y S3
pip install mlflow[extras]
pip install mysqlclient boto3

# Verificar la instalación
mlflow --version

Configuración del Backend de Almacenamiento

MLflow usa dos tipos de almacenamiento:

  1. Backend Store: Metadatos (parámetros, métricas, etiquetas) → MySQL/PostgreSQL
  2. Artifact Store: Archivos grandes (modelos, datasets) → S3/local

Configurar la base de datos MySQL

# Iniciar MySQL
sudo systemctl start mysql
sudo systemctl enable mysql

# Crear la base de datos y usuario para MLflow
sudo mysql << 'EOF'
CREATE DATABASE mlflow CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mlflow'@'localhost' IDENTIFIED BY 'clave_segura_aqui';
GRANT ALL PRIVILEGES ON mlflow.* TO 'mlflow'@'localhost';
FLUSH PRIVILEGES;
EOF

# Verificar la conexión
mysql -u mlflow -p mlflow -e "SHOW TABLES;"

Configurar el almacenamiento de artefactos

# Opción 1: Directorio local
mkdir -p /var/lib/mlflow/artifacts
chown -R mlflow:mlflow /var/lib/mlflow/

# Opción 2: Bucket S3 (recomendado para equipos)
# Asegúrate de tener AWS CLI configurado con las credenciales correctas
aws s3 mb s3://mlflow-artifacts-servidor --region eu-west-1

# Configurar las credenciales de AWS para el usuario de MLflow
sudo -u mlflow aws configure

Archivo de configuración de MLflow

# Crear el archivo de variables de entorno
cat > /etc/mlflow/mlflow.env << 'EOF'
# URI del backend de metadatos (MySQL)
MLFLOW_BACKEND_STORE_URI=mysql+mysqldb://mlflow:clave_segura_aqui@localhost/mlflow

# URI del almacén de artefactos
MLFLOW_DEFAULT_ARTIFACT_ROOT=s3://mlflow-artifacts-servidor/

# Puerto del servidor
MLFLOW_PORT=5000

# Host de escucha
MLFLOW_HOST=0.0.0.0

# Credenciales AWS para artefactos en S3
AWS_ACCESS_KEY_ID=TU_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=TU_SECRET_KEY
AWS_DEFAULT_REGION=eu-west-1
EOF

# Proteger el archivo de configuración
chmod 600 /etc/mlflow/mlflow.env

Iniciar el Servidor MLflow

# Activar el entorno virtual
source /opt/mlflow-venv/bin/activate

# Iniciar el servidor con MySQL y S3
mlflow server \
  --backend-store-uri mysql+mysqldb://mlflow:clave_segura_aqui@localhost/mlflow \
  --default-artifact-root s3://mlflow-artifacts-servidor/ \
  --host 0.0.0.0 \
  --port 5000

# O con almacenamiento local (más sencillo para empezar)
mlflow server \
  --backend-store-uri mysql+mysqldb://mlflow:clave_segura_aqui@localhost/mlflow \
  --default-artifact-root /var/lib/mlflow/artifacts/ \
  --host 0.0.0.0 \
  --port 5000

# Acceder a la interfaz web
# http://IP_SERVIDOR:5000

Configurar como Servicio del Sistema

# Crear el usuario del sistema para MLflow
sudo useradd -r -s /bin/false -d /var/lib/mlflow mlflow
sudo mkdir -p /var/lib/mlflow /etc/mlflow
sudo chown mlflow:mlflow /var/lib/mlflow

# Crear el servicio systemd
sudo cat > /etc/systemd/system/mlflow.service << 'EOF'
[Unit]
Description=Servidor MLflow
After=network.target mysql.service

[Service]
Type=simple
User=mlflow
Group=mlflow
WorkingDirectory=/var/lib/mlflow
EnvironmentFile=/etc/mlflow/mlflow.env
ExecStart=/opt/mlflow-venv/bin/mlflow server \
    --backend-store-uri ${MLFLOW_BACKEND_STORE_URI} \
    --default-artifact-root ${MLFLOW_DEFAULT_ARTIFACT_ROOT} \
    --host ${MLFLOW_HOST} \
    --port ${MLFLOW_PORT}
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable mlflow
sudo systemctl start mlflow

# Verificar el estado
sudo systemctl status mlflow

# Ver logs
sudo journalctl -u mlflow -f

Integración en el Código de Entrenamiento

#!/usr/bin/env python3
# Ejemplo completo de experimento ML con MLflow

import mlflow
import mlflow.sklearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, f1_score
import numpy as np

# Configurar el servidor MLflow remoto
mlflow.set_tracking_uri("http://IP_SERVIDOR_MLFLOW:5000")

# Seleccionar o crear el experimento
mlflow.set_experiment("clasificacion-iris")

# Parámetros del experimento
n_estimators = 100
max_depth = 5
random_state = 42

# Iniciar una nueva ejecución (run)
with mlflow.start_run(run_name="rf-baseline"):

    # Registrar los parámetros
    mlflow.log_param("n_estimators", n_estimators)
    mlflow.log_param("max_depth", max_depth)
    mlflow.log_param("random_state", random_state)

    # Cargar los datos y entrenar
    X, y = load_iris(return_X_y=True)
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=random_state
    )

    modelo = RandomForestClassifier(
        n_estimators=n_estimators,
        max_depth=max_depth,
        random_state=random_state
    )
    modelo.fit(X_train, y_train)

    # Evaluar el modelo
    predicciones = modelo.predict(X_test)
    accuracy = accuracy_score(y_test, predicciones)
    f1 = f1_score(y_test, predicciones, average='weighted')

    # Registrar las métricas
    mlflow.log_metric("accuracy", accuracy)
    mlflow.log_metric("f1_score", f1)

    # Registrar el modelo como artefacto
    mlflow.sklearn.log_model(
        modelo,
        "modelo-iris",
        registered_model_name="IrisClassifier"  # Registra en el Model Registry
    )

    # Registrar archivos adicionales (plots, configs, etc.)
    import matplotlib.pyplot as plt
    fig, ax = plt.subplots()
    ax.bar(range(len(modelo.feature_importances_)), modelo.feature_importances_)
    plt.savefig("/tmp/feature_importance.png")
    mlflow.log_artifact("/tmp/feature_importance.png")

    print(f"Accuracy: {accuracy:.4f}")
    print(f"F1 Score: {f1:.4f}")
    print(f"Run ID: {mlflow.active_run().info.run_id}")

Variables de entorno para los científicos de datos

# Los miembros del equipo configuran en su ~/.bashrc o en el proyecto
export MLFLOW_TRACKING_URI="http://IP_SERVIDOR_MLFLOW:5000"

# Para S3 con credenciales específicas
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...

Registro de Modelos

import mlflow
from mlflow.tracking import MlflowClient

client = MlflowClient(tracking_uri="http://IP_SERVIDOR_MLFLOW:5000")

# Registrar un modelo existente desde un run
run_id = "abc123..."
mlflow.register_model(
    f"runs:/{run_id}/modelo-iris",
    "IrisClassifier"
)

# Gestionar versiones del modelo
# Transición a Staging para pruebas
client.transition_model_version_stage(
    name="IrisClassifier",
    version=1,
    stage="Staging"
)

# Promover a Production cuando esté validado
client.transition_model_version_stage(
    name="IrisClassifier",
    version=1,
    stage="Production"
)

# Cargar el modelo de producción para inferencia
modelo_prod = mlflow.sklearn.load_model("models:/IrisClassifier/Production")
# Ver los modelos registrados desde la CLI
mlflow models list --tracking-uri http://IP_SERVIDOR_MLFLOW:5000

Proxy Inverso con Nginx

# /etc/nginx/sites-available/mlflow
server {
    listen 80;
    server_name mlflow.tudominio.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name mlflow.tudominio.com;

    ssl_certificate /etc/letsencrypt/live/mlflow.tudominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mlflow.tudominio.com/privkey.pem;

    # Autenticación básica para proteger el acceso
    auth_basic "MLflow - Acceso Restringido";
    auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        client_max_body_size 500M;  # Para subida de modelos grandes
    }
}
# Crear usuario para autenticación básica
sudo apt-get install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd mlflow-admin

sudo ln -s /etc/nginx/sites-available/mlflow /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Solución de Problemas

Error: Can't connect to MySQL server

# Verificar que MySQL está corriendo
sudo systemctl status mysql

# Verificar las credenciales
mysql -u mlflow -p -h localhost mlflow -e "SELECT 1;"

# Comprobar la URI de conexión
echo "mysql+mysqldb://mlflow:clave@localhost/mlflow" | python3 -c "
import sys; from sqlalchemy import create_engine
engine = create_engine(sys.stdin.read().strip())
print('Conexión OK')
"

El servidor MLflow no responde

# Verificar los logs
sudo journalctl -u mlflow -n 30

# Verificar que el puerto está escuchando
sudo ss -tlnp | grep 5000

Error al subir artefactos a S3

# Verificar las credenciales AWS del usuario mlflow
sudo -u mlflow aws s3 ls s3://mlflow-artifacts-servidor/

# Verificar las variables de entorno
sudo -u mlflow env | grep AWS

La interfaz web es muy lenta con muchos experimentos

# Añadir índices a la base de datos MySQL
mysql -u mlflow -p mlflow << 'EOF'
CREATE INDEX IF NOT EXISTS idx_runs_experiment ON runs(experiment_id);
CREATE INDEX IF NOT EXISTS idx_metrics_run ON metrics(run_uuid);
EOF

Conclusión

MLflow como servidor centralizado transforma la gestión de experimentos de machine learning de un caos de archivos dispersos a un sistema estructurado con historial completo, comparación visual de métricas y registro versionado de modelos. Con MySQL como backend y S3 para artefactos, el servidor escala fácilmente para equipos de cualquier tamaño y permite promover modelos de forma controlada desde experimentos hasta producción.