--- title: "MinIO for ML Model and Dataset Storage" description: "Use MinIO as S3-compatible storage for ML workflows. Learn bucket organization for models and datasets, versioning, Python SDK integration, and high-performance data pipelines." category: "Infraestructura de IA y ML" language: es source: https://cubepath.com/es/docs/infraestructura-de-ia-y-ml/minio-para-almacenamiento-de-modelos-ml updated: 2026-04-04 --- # MinIO para Almacenamiento de Modelos y Datasets de ML MinIO es un servidor de almacenamiento de objetos compatible con la API de AWS S3 que puedes instalar en tu propio servidor, ideal para almacenar modelos de machine learning, datasets y artefactos de experimentos sin depender de servicios cloud externos. Con soporte para versionado, high availability y un Python SDK que funciona exactamente igual que boto3 con S3, MinIO se integra perfectamente con MLflow, DVC y los principales frameworks de ML. Esta guía cubre la instalación, organización de buckets, versionado y la construcción de pipelines de datos de alto rendimiento. ## Requisitos Previos - Servidor Linux (Ubuntu 20.04+, CentOS 8+) - Al menos 4 GB de RAM - Disco dedicado para almacenamiento (SSD recomendado para mejor rendimiento) - Acceso root o sudo ## Instalación de MinIO ### Instalación como binario único ```bash # Descargar el binario de MinIO (servidor) wget https://dl.min.io/server/minio/release/linux-amd64/minio -O /usr/local/bin/minio chmod +x /usr/local/bin/minio # Verificar la instalación minio --version ``` ### Crear el entorno de MinIO ```bash # Crear el usuario del sistema para MinIO sudo useradd -r -s /bin/false -d /opt/minio minio-user # Crear los directorios necesarios sudo mkdir -p /opt/minio/data sudo mkdir -p /etc/minio # Asignar permisos sudo chown -R minio-user:minio-user /opt/minio # Crear el archivo de configuración de entorno sudo cat > /etc/minio/minio.env << 'EOF' # Credenciales de acceso (equivalente a AWS Access Key y Secret Key) MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=cambia-esta-clave-muy-segura # Directorio de datos MINIO_VOLUMES=/opt/minio/data # URL pública de acceso (para generar URLs firmadas correctamente) MINIO_SERVER_URL=https://minio.tudominio.com # URL de la consola web MINIO_BROWSER_REDIRECT_URL=https://minio-console.tudominio.com EOF sudo chmod 600 /etc/minio/minio.env ``` ### Configurar MinIO como servicio systemd ```bash sudo cat > /etc/systemd/system/minio.service << 'EOF' [Unit] Description=MinIO Object Storage After=network.target Wants=network-online.target [Service] User=minio-user Group=minio-user EnvironmentFile=/etc/minio/minio.env ExecStart=/usr/local/bin/minio server \ --console-address ":9001" \ --address ":9000" \ ${MINIO_VOLUMES} Restart=always RestartSec=10 # Deshabilitar los límites de archivos abiertos LimitNOFILE=65536 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable minio sudo systemctl start minio # Verificar el estado sudo systemctl status minio # Ver los logs sudo journalctl -u minio -f ``` Accede a la consola web: - **API S3**: `http://IP_SERVIDOR:9000` - **Consola Web**: `http://IP_SERVIDOR:9001` ## Configuración Inicial ### Instalar el cliente mc (MinIO Client) ```bash # Descargar mc wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /usr/local/bin/mc chmod +x /usr/local/bin/mc # Configurar la conexión al servidor MinIO mc alias set minio-local http://localhost:9000 minioadmin cambia-esta-clave-muy-segura # Verificar la conexión mc admin info minio-local ``` ### Crear la estructura inicial de buckets ```bash # Crear los buckets principales para ML mc mb minio-local/modelos mc mb minio-local/datasets mc mb minio-local/experimentos mc mb minio-local/artifacts # Verificar los buckets creados mc ls minio-local ``` ## Organización de Buckets para ML Una estructura de buckets bien organizada es fundamental para equipos de ML. ```bash # Estructura recomendada para proyectos ML # Bucket: modelos # modelos/ # ├── produccion/ # │ ├── clasificador-spam/ # │ │ ├── v1.0/model.pkl # │ │ ├── v1.1/model.pkl # │ │ └── latest -> v1.1/ # │ └── detector-fraude/ # │ └── v2.3/model.pkl # └── staging/ # └── clasificador-spam/ # └── v1.2-rc1/model.pkl # Bucket: datasets # datasets/ # ├── raw/ <- Datos originales sin procesar # ├── processed/ <- Datos procesados y listos para entrenamiento # ├── features/ <- Features extraídas # └── splits/ <- Train/val/test splits # Crear la estructura mc mb minio-local/modelos/produccion mc mb minio-local/modelos/staging mc mb minio-local/datasets/raw mc mb minio-local/datasets/processed mc mb minio-local/datasets/features ``` ### Configurar permisos por bucket ```bash # Crear una política de solo lectura para acceso a modelos de producción cat > /tmp/policy-modelos-readonly.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::modelos/*", "arn:aws:s3:::modelos" ] } ] } EOF # Crear el usuario para inferencia (solo lectura) mc admin user add minio-local usuario-inferencia clave-segura-2 mc admin policy create minio-local politica-solo-lectura /tmp/policy-modelos-readonly.json mc admin policy attach minio-local politica-solo-lectura --user usuario-inferencia ``` ## Versionado de Modelos ```bash # Habilitar el versionado en el bucket de modelos mc version enable minio-local/modelos # Verificar que el versionado está activo mc version info minio-local/modelos # Habilitar también para datasets mc version enable minio-local/datasets ``` ### Trabajar con versiones ```python #!/usr/bin/env python3 # Gestión de versiones de modelos con MinIO import boto3 from botocore.client import Config import json # Configurar el cliente S3 compatible con MinIO s3 = boto3.client( 's3', endpoint_url='http://localhost:9000', aws_access_key_id='minioadmin', aws_secret_access_key='cambia-esta-clave-muy-segura', config=Config(signature_version='s3v4'), region_name='us-east-1' ) def subir_modelo_con_metadata(ruta_local, bucket, clave, version_metadata): """Subir un modelo con metadatos de versión.""" with open(ruta_local, 'rb') as f: s3.put_object( Bucket=bucket, Key=clave, Body=f, # Metadatos personalizados para el modelo Metadata={ 'framework': version_metadata.get('framework', ''), 'accuracy': str(version_metadata.get('accuracy', '')), 'f1-score': str(version_metadata.get('f1_score', '')), 'training-date': version_metadata.get('training_date', ''), 'git-commit': version_metadata.get('git_commit', '') } ) print(f"Modelo subido: {bucket}/{clave}") def listar_versiones(bucket, prefijo): """Listar todas las versiones de un modelo.""" paginator = s3.get_paginator('list_object_versions') versiones = [] for pagina in paginator.paginate(Bucket=bucket, Prefix=prefijo): for version in pagina.get('Versions', []): versiones.append({ 'version_id': version['VersionId'], 'modificado': version['LastModified'], 'tamano': version['Size'], 'es_ultima': version['IsLatest'] }) return sorted(versiones, key=lambda x: x['modificado'], reverse=True) # Ejemplo de uso metadata = { 'framework': 'sklearn', 'accuracy': 0.956, 'f1_score': 0.951, 'training_date': '2024-01-15', 'git_commit': 'abc123' } subir_modelo_con_metadata( 'modelo_clasificador.pkl', 'modelos', 'produccion/clasificador-spam/model.pkl', metadata ) versiones = listar_versiones('modelos', 'produccion/clasificador-spam/') print(f"Versiones encontradas: {len(versiones)}") for v in versiones[:5]: print(f" - {v['version_id'][:8]}... | {v['modificado']} | {'ACTUAL' if v['es_ultima'] else ''}") ``` ## Integración con Python (boto3) ```python #!/usr/bin/env python3 # Pipeline completo de ML con MinIO import boto3 import joblib import numpy as np from io import BytesIO from sklearn.ensemble import RandomForestClassifier from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from botocore.client import Config # Cliente MinIO compatible con S3 s3 = boto3.client( 's3', endpoint_url='http://localhost:9000', aws_access_key_id='minioadmin', aws_secret_access_key='cambia-esta-clave', config=Config(signature_version='s3v4'), region_name='us-east-1' ) def guardar_dataset_en_minio(X, y, nombre): """Guardar un dataset de NumPy en MinIO.""" buffer = BytesIO() np.savez_compressed(buffer, X=X, y=y) buffer.seek(0) s3.put_object( Bucket='datasets', Key=f'processed/{nombre}.npz', Body=buffer ) print(f"Dataset guardado: datasets/processed/{nombre}.npz") def cargar_dataset_desde_minio(nombre): """Cargar un dataset desde MinIO.""" respuesta = s3.get_object( Bucket='datasets', Key=f'processed/{nombre}.npz' ) buffer = BytesIO(respuesta['Body'].read()) datos = np.load(buffer) return datos['X'], datos['y'] def guardar_modelo(modelo, nombre, version): """Guardar un modelo scikit-learn en MinIO.""" buffer = BytesIO() joblib.dump(modelo, buffer) buffer.seek(0) s3.put_object( Bucket='modelos', Key=f'produccion/{nombre}/{version}/model.pkl', Body=buffer ) print(f"Modelo guardado: modelos/produccion/{nombre}/{version}/model.pkl") def cargar_modelo(nombre, version='latest'): """Cargar un modelo desde MinIO.""" respuesta = s3.get_object( Bucket='modelos', Key=f'produccion/{nombre}/{version}/model.pkl' ) buffer = BytesIO(respuesta['Body'].read()) return joblib.load(buffer) # Pipeline de entrenamiento completo if __name__ == '__main__': # Generar datos de ejemplo X, y = make_classification(n_samples=10000, n_features=20, random_state=42) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # Guardar el dataset en MinIO guardar_dataset_en_minio(X_train, y_train, 'clasificacion-train-v1') guardar_dataset_en_minio(X_test, y_test, 'clasificacion-test-v1') # Entrenar el modelo modelo = RandomForestClassifier(n_estimators=100, random_state=42) modelo.fit(X_train, y_train) accuracy = modelo.score(X_test, y_test) print(f"Accuracy: {accuracy:.4f}") # Guardar el modelo en MinIO guardar_modelo(modelo, 'clasificador-ejemplo', 'v1.0') # Cargar el modelo y hacer predicciones modelo_cargado = cargar_modelo('clasificador-ejemplo', 'v1.0') predicciones = modelo_cargado.predict(X_test[:5]) print(f"Predicciones de prueba: {predicciones}") ``` ## Integración con MLflow ```python # Usar MinIO como artifact store para MLflow import mlflow # Configurar MLflow para usar MinIO como backend de artefactos # Las variables de entorno deben estar definidas antes de iniciar mlflow server import os os.environ['MLFLOW_S3_ENDPOINT_URL'] = 'http://localhost:9000' os.environ['AWS_ACCESS_KEY_ID'] = 'minioadmin' os.environ['AWS_SECRET_ACCESS_KEY'] = 'cambia-esta-clave' # Iniciar el servidor MLflow con MinIO como artifact store # mlflow server \ # --backend-store-uri sqlite:///mlflow.db \ # --default-artifact-root s3://artifacts/mlflow/ \ # --host 0.0.0.0 \ # --port 5000 mlflow.set_tracking_uri("http://localhost:5000") mlflow.set_experiment("experimento-minio") with mlflow.start_run(): # Los artefactos se guardan automáticamente en MinIO mlflow.log_param("n_estimators", 100) mlflow.log_metric("accuracy", 0.956) # Guardar el modelo en MinIO via MLflow modelo = RandomForestClassifier(n_estimators=100) mlflow.sklearn.log_model(modelo, "modelo") ``` ## CLI de MinIO (mc) ```bash # Copiar archivos a MinIO mc cp modelo.pkl minio-local/modelos/produccion/clasificador/v1.0/ # Sincronizar un directorio completo mc mirror ./experimentos/ minio-local/experimentos/ # Ver el contenido de un bucket mc ls minio-local/modelos/ # Ver las versiones de un archivo mc ls --versions minio-local/modelos/produccion/clasificador/ # Restaurar una versión anterior mc cp minio-local/modelos/produccion/clasificador/model.pkl \ --version-id "abc123..." \ ./modelo-restaurado.pkl # Crear una política de ciclo de vida (eliminar versiones antiguas) mc ilm rule add \ --noncurrent-expire-days 30 \ minio-local/modelos # Crear una URL firmada temporal (válida 24 horas) mc share download minio-local/modelos/produccion/clasificador/v1.0/model.pkl \ --expire 24h # Ver estadísticas del servidor mc admin info minio-local # Ver el uso de disco mc du minio-local ``` ## Solución de Problemas **El servicio MinIO no inicia** ```bash # Ver los logs detallados sudo journalctl -u minio -n 50 --no-pager # Verificar permisos del directorio de datos ls -la /opt/minio/data/ sudo chown -R minio-user:minio-user /opt/minio/ # Probar iniciar manualmente como el usuario minio sudo -u minio-user minio server /opt/minio/data --console-address :9001 ``` **Error de conexión desde Python/boto3** ```bash # Verificar que el servidor responde curl http://localhost:9000/minio/health/live # Verificar que las credenciales son correctas mc alias set test http://localhost:9000 minioadmin tu-clave mc ls test ``` **Las versiones no se almacenan** ```bash # Verificar que el versionado está habilitado mc version info minio-local/modelos # Debe mostrar: Versioning is enabled # Habilitarlo si no lo está mc version enable minio-local/modelos ``` ## Conclusión MinIO proporciona una solución de almacenamiento de objetos compatible con S3 que puedes instalar directamente en tu servidor, eliminando la dependencia de proveedores cloud externos para los datos más sensibles de tus proyectos de ML. Con el versionado de modelos, la integración nativa con MLflow y un Python SDK idéntico a boto3, MinIO se convierte en el componente central de cualquier plataforma MLOps privada y de alto rendimiento.