If youβve ever tried setting up Kubeflow on Kubernetes, you know the drill:
docker-compose.yml
gbnt
)Gubernator is a single-binary container orchestrator written in Go that combines:
/var/contenedores
) across cluster nodes. βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Data Scientist / AI Engineer β ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ β (https://*.kubeflow.gbnt.local) βΌ βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Built-in Caddy Ingress & CoreDNS Gateway β ββββββββ¬βββββββββββββββ¬βββββββββββββββ¬βββββββββββββββ¬ββββββββββ β β β β βΌ βΌ βΌ βΌ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β JupyterLab ββ MLflow ββ MinIO S3 ββ Ollama / vLLMβ β Workspace ββ Tracking ββ Artifacts & ββ Inference β β (PyTorch) ββ & Registry ββ Datasets ββ Serving β β (:8888) ββ (:5000) ββ (:9001) ββ (:11434) β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Capability | Kubernetes Kubeflow | Gubernator MLOps (kubeflow-stack ) |
|---|---|---|
| Control Plane Overhead | ||
| 16 GB β 32 GB RAM (etcd, Istio, K8s) | ||
| < 200 MB RAM (Go binary) | ||
| Configuration Format | ||
| Helm / Kustomize / CRD manifests | Standard docker-compose.yml |
|
| Deployment Time | ||
| 30β45 minutes | < 60 seconds | |
| Experiment Tracking | ||
| Katib + Kubeflow Metadata | MLflow Tracking + Model Registry | |
| Artifact Store | ||
| MinIO on PVCs | MinIO S3 with Granaries Storage | |
| Inference Serving | ||
| KServe + Knative + Istio | Ollama / vLLM (OpenAI API compatible) | |
| Domain Routing & TLS | ||
| VirtualServices + IngressGateway | Automatic Caddy Ingress (*.local ) |
Here is the entire stack defined in standard Docker Compose syntax:
version: "3.8"
services:
minio:
image: minio/minio:latest
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
- MINIO_ROOT_USER=kubeflow
- MINIO_ROOT_PASSWORD=gubernator123
ports:
- "9000:9000"
- "9001:9001"
volumes:
- /var/contenedores/kubeflow/minio_data:/data
labels:
- "ingress.host=minio.kubeflow.gbnt.local"
- "gbnt.caddy.port=9001"
- "gbnt.service.name=minio-s3"
mlflow:
image: ghcr.io/mlflow/mlflow:latest
restart: unless-stopped
command: >
mlflow server
--host 0.0.0.0
--port 5000
--workers 1
--allowed-hosts "*"
--backend-store-uri sqlite:////data/mlflow.db
--default-artifact-root s3://mlflow-artifacts/
environment:
- AWS_ACCESS_KEY_ID=kubeflow
- AWS_SECRET_ACCESS_KEY=gubernator123
- MLFLOW_S3_ENDPOINT_URL=http://minio.kubeflow.gbnt.local
- MLFLOW_S3_IGNORE_TLS=true
- MLFLOW_ALLOWED_HOSTS=*
ports:
- "5000:5000"
volumes:
- /var/contenedores/kubeflow/mlflow_data:/data
labels:
- "ingress.host=mlflow.kubeflow.gbnt.local"
- "gbnt.caddy.port=5000"
- "gbnt.service.name=mlflow-tracking"
jupyter-workspace:
image: quay.io/jupyter/pytorch-notebook:latest
restart: unless-stopped
environment:
- JUPYTER_TOKEN=gubernator-secret
- JUPYTER_ENABLE_LAB=yes
- AWS_ACCESS_KEY_ID=kubeflow
- AWS_SECRET_ACCESS_KEY=gubernator123
- MLFLOW_TRACKING_URI=http://mlflow.kubeflow.gbnt.local
- MLFLOW_S3_ENDPOINT_URL=http://minio.kubeflow.gbnt.local
ports:
- "8888:8888"
volumes:
- /var/contenedores/kubeflow/workspaces:/home/jovyan/work
- /var/contenedores/kubeflow/cache:/home/jovyan/.cache
labels:
- "ingress.host=notebooks.kubeflow.gbnt.local"
- "gbnt.caddy.port=8888"
- "gbnt.service.name=jupyterlab"
inference-engine:
image: ollama/ollama:latest
restart: unless-stopped
ports:
- "11434:11434"
volumes:
- /var/contenedores/kubeflow/models:/root/.ollama
labels:
- "ingress.host=inference.kubeflow.gbnt.local"
- "gbnt.caddy.port=11434"
- "gbnt.service.name=model-serving"
π οΈ Deploying in 1 Command
On your Gubernator cluster, run:
gbnt stack deploy kubeflow-stack -c docker-compose.yml
Or open the Gubernator Web Dashboard (http://localhost:4001), head over to Compose Studio, select the Kubeflow MLOps Blueprint, and click Deploy Stack.
Gubernator's scheduler automatically:
Prioritizes Centurion Worker nodes over the Manager.
Spreads the workloads evenly across available workers.
Automatically sets up internal DNS (CoreDNS) and reverse proxy routes (Caddy Ingress).
Generates instant TLS certificates for all services.
Instant Endpoints & Access
Immediately after deployment, your MLOps platform is ready:
JupyterLab Workspace: https://notebooks.kubeflow.gbnt.local (Token: gubernator-secret)
MLflow Experiment Tracking: https://mlflow.kubeflow.gbnt.local
MinIO S3 Console: https://minio.kubeflow.gbnt.local (User: kubeflow / Pass: gubernator123)
β‘ Ollama Inference Engine: https://inference.kubeflow.gbnt.local (OpenAI-compatible /v1/chat/completions)
π§ͺ Testing the End-to-End Pipeline in Python
Data scientists can write normal Python code to log experiments, save models to MinIO S3, and serve predictions:
import mlflow
import mlflow.sklearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
import os
os.environ["MLFLOW_S3_ENDPOINT_URL"] = "http://minio.kubeflow.gbnt.local"
os.environ["AWS_ACCESS_KEY_ID"] = "kubeflow"
os.environ["AWS_SECRET_ACCESS_KEY"] = "gubernator123"
mlflow.set_tracking_uri("http://mlflow.kubeflow.gbnt.local")
mlflow.set_experiment("iris-classification-demo")
with mlflow.start_run():
X, y = load_iris(return_X_y=True)
clf = RandomForestClassifier(n_estimators=100, max_depth=4)
clf.fit(X, y)
accuracy = clf.score(X, y)
mlflow.log_param("n_estimators", 100)
mlflow.log_metric("accuracy", accuracy)
mlflow.sklearn.log_model(clf, "model", registered_model_name="IrisProductionModel")
print(f"β
Training completed! Accuracy: {accuracy * 100:.2f}%")
`
Key Takeaways
You don't always need Kubernetes: If you are not running hundreds of parallel multi-step distributed DAG pipelines with Argo, Kubernetes adds unnecessary friction and cost.
Standard Compose is enough: With an orchestrator like Gubernator, you get clustering, load balancing, health checks, automated Ingress, and persistent storage using simple, familiar Docker Compose files.
Resource Efficiency: You save 10x-20x the RAM, allowing you to invest your hardware budget where it actually matters: GPUs and model training.
π Project Links
π GitHub Repository: mario-ezquerro/gubernator
π Documentation: Gubernator Docs
β Give it a star on GitHub if you found this useful!