Deploying Michelangelo AI UI
This guide covers how the Michelangelo AI UI fits into Michelangelo AI's Kubernetes deployments and how operators can adapt the configuration for their environments.
Context
The Michelangelo AI UI is a React-based web application that provides a graphical interface for managing projects, pipelines, and monitoring pipeline runs in the Michelangelo AI ML platform.
Audience
- Platform operators looking to understand UI deployment requirements
- Kubernetes administrators adapting the sandbox for production use
- Teams wanting to customize UI configuration for their environment
Key Concepts
- Sandbox Manifests: Reference Kubernetes YAML files providing working deployment templates
- ConfigMap Injection: Runtime configuration mounted into containers without rebuilding images
- gRPC-Web: Protocol enabling browser-based gRPC communication through HTTP/1.1
- Envoy Proxy: Service mesh proxy handling gRPC-Web translation
- Template Customization: Adapting reference manifests for specific infrastructure requirements
Setup
Prerequisites
- Kubernetes cluster with Michelangelo AI API server deployed
- Access to Michelangelo AI UI container image from GitHub Container Registry
UI Deployment Requirements
1. Container Deployment
Deploy the UI container with runtime configuration mounted:
Image Selection:
Available from GitHub Container Registry at ghcr.io/michelangelo-ai/ui:
- Latest development:
:main - Specific commit:
:sha-d550892(example) - Pull command:
docker pull ghcr.io/michelangelo-ai/ui:your-chosen-tag
Container Requirements:
- Configuration: Mount
config.jsonat/usr/share/nginx/html/config.json - Port: Container serves on port 80
The UI needs to know how to connect to your Michelangelo AI API server. This is configured through the ConfigMap mounted within the container.
- API endpoint: Point to your actual API server location
{
"apiBaseUrl": "http://your-api-server:8081"
}
2. Envoy Proxy Setup
The UI communicates with the API server through Envoy, which requires:
Port Configuration:
- Envoy listens on port 8081 for gRPC-Web requests
- API server runs on port 8081 (or your configured port)
- UI makes requests to Envoy, not directly to API server
CORS Configuration: Envoy must allow the UI's origin in CORS settings:
cors:
allow_origin_string_match:
- exact: "http://your-ui-domain:port"
Backend Routing: Envoy forwards UI requests to the API server. The cluster name in the route configuration must match the cluster definition:
# In the route configuration:
route:
cluster: michelangelo-apiserver # This name must match below
# In the clusters section:
clusters:
- name: michelangelo-apiserver # Must match the route cluster name
endpoints:
- endpoint:
address:
socket_address:
address: michelangelo-apiserver # Your API server service name
port_value: 8081 # Your API server port
Common Issue: Mismatched cluster names between route configuration and cluster definition will cause "no healthy upstream" errors.
3. Network Connectivity
Ensure network paths are configured:
- UI container → Envoy proxy (port 8081)
- Envoy proxy → API server (port 8081)
- External access → UI container (port 80)
External Access Details: The UI container serves the React application on port 80 (standard HTTP). Users need to be able to reach this port through your Kubernetes networking setup. Common approaches:
- NodePort: Direct access via
node-ip:30011(sandbox default - any cluster node's IP) - Ingress: Domain-based routing (e.g.,
michelangelo.yourcompany.com) - Port forwarding: Development access via
kubectl port-forward
The UI serves static files (HTML, JS, CSS) from nginx, so it's a standard web server that needs HTTP access from users' browsers.
Reference Implementation
For a complete working example, see the Sandbox Guide which includes all components configured and connected.
Verification
Once deployed, verify the connection chain:
- UI loads: Access the UI in browser
- Config loads: Check browser dev tools for
/config.json - API connectivity: Verify API calls succeed (no CORS errors in browser console)
Troubleshooting
Common Issues
Envoy "no healthy upstream" errors:
- Cause: Cluster name mismatch between route configuration and cluster definition
- Fix: Ensure the
cluster:field in routes matches thename:field in clusters section - Check: Envoy logs will show "no healthy upstream for cluster 'cluster-name'"
CORS errors in browser:
- Verify Envoy proxy CORS configuration includes your domain
- Check browser dev tools → Network tab for failed requests
- Ensure
allow_origin_string_matchincludes your access URL
FAQ
Q: Can I use a custom domain? A: Yes, configure an Ingress resource and update CORS settings in Envoy.
Q: What if my API server uses different ports?
A: Update both the apiBaseUrl in config.json and the Envoy cluster configuration.