Multi-tenant Streamlit Platform for Research
CMBCluster is a multi-tenant Streamlit platform designed specifically for research teams. Built on the proven JupyterHub architecture pattern, it provides isolated, persistent research environments for each user while maintaining enterprise-grade security and scalability.
The platform follows the JupyterHub architecture pattern with these key components:
graph TB
Users[π₯ Users] --> Proxy[π Proxy]
Proxy --> Hub[π― Hub - Authenticate user]
Hub --> PV[πΎ Pods + Volumes / USER SESSION]
CloudVolumes[βοΈ Cloud Volumes] --> PV
ImageRegistry[π¦ Image Registry] --> PV
Proxy -.->|ROUTE INFOSEND| Hub
Hub -.->|SIGNED OUTUSER REDIRECT| Proxy
Proxy -.->|SIGNED IN USERREDIRECT| PV
Hub -.->|VOLUME PROVIDE/POD CREATE/USER REDIRECT| PV
Hub -.->|CULL PODSIF STALE| PV
subgraph "Kubernetes Cluster"
Proxy
Hub
PV
end
style Users fill:#f9f,stroke:#333,stroke-width:2px
style Proxy fill:#9f9,stroke:#333,stroke-width:2px
style Hub fill:#9f9,stroke:#333,stroke-width:2px
style PV fill:#99f,stroke:#333,stroke-width:2px
style CloudVolumes fill:#bbf,stroke:#333,stroke-width:2px
style ImageRegistry fill:#bbf,stroke:#333,stroke-width:2px
- Google OAuth Integration: Seamless single sign-on
- RBAC: Role-based access control with admin/user permissions
- Network Policies: Kubernetes-native network isolation
- Pod Security: Non-root containers with security contexts
- Auto-scaling: Horizontal pod autoscaling based on demand
- Resource Management: Configurable CPU/memory limits per user
- Load Balancing: NGINX ingress with SSL termination
- High Availability: Multi-replica deployments with health checks
- Scientific Computing: Pre-installed research libraries (pandas, numpy, scipy, matplotlib)
- Interactive Analysis: Streamlit-based data exploration interface
- Persistent Workspaces: User data persists across sessions
- Collaborative Tools: Shared data access and project management
- Kubernetes-Native: Built for modern container orchestration
- GKE Optimized: Tested and optimized for Google Kubernetes Engine
- Helm Charts: Easy deployment and configuration management
- CI/CD Ready: GitHub Actions integration for automated deployments
- Google Cloud Platform Account with billing enabled
- Local Development Tools:
# macOS brew install google-cloud-sdk kubectl helm docker # Ubuntu/Debian sudo apt-get install google-cloud-sdk kubectl helm docker.io # CentOS/RHEL sudo yum install google-cloud-sdk kubectl helm docker
- Domain Name (for production deployment)
git clone https://github.com/archetana/cmbcluster.git
cd cmbcluster
# Copy environment template
cp .env.example .env
# Edit configuration
vim .env
Required environment variables:
PROJECT_ID=cambridge-infosys
BASE_DOMAIN=cmbcluster.yourdomain.com
GOOGLE_CLIENT_ID=your-oauth-client-id
GOOGLE_CLIENT_SECRET=your-oauth-secret
SECRET_KEY=your-generated-secret-key
# Start local environment
make dev
# Or using docker-compose directly
docker-compose up --build
Access at: http://localhost:8501
# Setup GKE cluster
make setup PROJECT_ID=your-project DOMAIN=your-domain.com
# Deploy application
make deploy
# Start all services
docker-compose up --build
# Access points:
# Frontend: http://localhost:8501
# Backend API: http://localhost:8000
# API Docs: http://localhost:8000/docs
# User Environment: http://localhost:8502
# Make the script executable
chmod +x scripts/build-images.sh
chmod +x scripts/setup-cluster.sh
chmod +x scripts/deploy.sh
chmod +x scripts/cleanup.sh
chmod +x scripts/local-dev.sh
# Build images
make build
# Run tests
make test
# View logs
make logs
# Stop services
docker-compose down
# Clean up everything
make clean
cmbcluster/
βββ README.md # This file
βββ .env.example # Environment template
βββ .gitignore # Git ignore rules
βββ docker-compose.yml # Local development setup
βββ Makefile # Build and deployment commands
βββ backend/ # FastAPI backend service
β βββ Dockerfile
β βββ requirements.txt
β βββ main.py # Application entry point
β βββ auth.py # OAuth authentication
β βββ pod_manager.py # Kubernetes pod management
β βββ config.py # Configuration settings
β βββ models.py # Data models
βββ frontend/ # Streamlit frontend application
β βββ Dockerfile
β βββ requirements.txt
β βββ main.py # Main UI application
β βββ config.py # Frontend configuration
β βββ components/ # Reusable UI components
β β βββ auth.py
β β βββ api_client.py
β βββ pages/ # Multi-page UI
β βββ Dashboard.py
β βββ Environment.py
β βββ Settings.py
βββ user-environment/ # User research environment container
β βββ Dockerfile
β βββ requirements.txt
β βββ app.py # Streamlit research application
βββ k8s/ # Kubernetes manifests
β βββ namespace.yaml
β βββ rbac.yaml
β βββ backend-deployment.yaml
β βββ frontend-deployment.yaml
β βββ ingress.yaml
βββ helm/ # Helm chart templates
β βββ Chart.yaml
β βββ values.yaml
β βββ templates/
β βββ backend.yaml
β βββ frontend.yaml
β βββ ingress.yaml
βββ scripts/ # Deployment and utility scripts
β βββ setup-cluster.sh
β βββ build-images.sh
β βββ deploy.sh
β βββ cleanup.sh
β βββ local-dev.sh
βββ terraform/ # Infrastructure as code (optional)
βββ main.tf
βββ variables.tf
βββ outputs.tf
# Authenticate with Google Cloud
gcloud auth login
gcloud config set project YOUR_PROJECT_ID
# Setup cluster and infrastructure
./scripts/setup-cluster.sh YOUR_PROJECT_ID
This creates:
- GKE cluster with autoscaling (1-10 nodes)
- NGINX Ingress Controller with LoadBalancer
- cert-manager for automated SSL certificates
- Required service accounts and RBAC policies
- Storage classes for persistent volumes
- Go to Google Cloud Console
- Navigate to APIs & Services > Credentials
- Create OAuth 2.0 Client ID
- Add authorized redirect URIs:
https://api.yourdomain.com/auth/callback
- Update
.env
with client ID and secret
# Build and push container images
./scripts/build-images.sh YOUR_PROJECT_ID
# Deploy with Helm
./scripts/deploy.sh YOUR_PROJECT_ID yourdomain.com
Point your domain to the ingress IP:
# Get ingress IP
kubectl get ingress -n cmbcluster
# Create DNS records:
# A record: yourdomain.com -> INGRESS_IP
# A record: *.yourdomain.com -> INGRESS_IP
# A record: api.yourdomain.com -> INGRESS_IP
- Access Platform: Navigate to
https://yourdomain.com
- Login: Click "π Login with Google" and authenticate
- Launch Environment: Click ":material/rocket_launch: Launch Environment" to create your research pod
- Start Research: Access your isolated Streamlit environment with:
- Pre-installed research libraries (pandas, numpy, scipy, matplotlib)
- Persistent workspace storage (
/workspace
) - Scientific computing tools (NumPy, SciPy, Matplotlib)
- Data visualization capabilities (Plotly, Seaborn)
# Pre-installed libraries available in user environments
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
import pandas as pd
import plotly.express as px
import astropy
import healpy as hp
import camb
# Persistent workspace
workspace_dir = "/workspace" # Your files persist here
# Monitor deployments
kubectl get pods -n cmbcluster
# View logs
kubectl logs -f deployment/cmbcluster-backend -n cmbcluster
kubectl logs -f deployment/cmbcluster-frontend -n cmbcluster
# Scale deployments
kubectl scale deployment cmbcluster-backend --replicas=5 -n cmbcluster
# List user environments
kubectl get pods -l app=cmbcluster-user-env -n cmbcluster
# Clean up inactive environments
kubectl delete pods -l app=cmbcluster-user-env --field-selector status.phase=Succeeded -n cmbcluster
Variable | Description | Default | Required |
---|---|---|---|
PROJECT_ID |
GCP Project ID | - | β |
BASE_DOMAIN |
Platform domain | cmbcluster.local |
β |
GOOGLE_CLIENT_ID |
OAuth Client ID | - | β |
GOOGLE_CLIENT_SECRET |
OAuth Secret | - | β |
SECRET_KEY |
JWT signing key | - | β |
MAX_INACTIVE_HOURS |
Auto-cleanup time | 1H |
β |
MAX_USER_PODS |
Pods per user | 1 |
β |
TOKEN_EXPIRE_HOURS |
JWT expiration | 24 |
β |
NAMESPACE |
Kubernetes namespace | cmbcluster |
β |
FILE_ENCRYPTION_KEY |
Environment file encryption key | - |
β οΈ Important: TheFILE_ENCRYPTION_KEY
is required for production deployments to encrypt uploaded environment files. See ENCRYPTION.md for details.
Default user environment resources:
userEnvironment:
defaultResources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 2000m
memory: 4Gi
storage:
size: 10Gi
storageClass: standard-rwo
Customize deployment in helm/values.yaml
:
# Backend scaling
backend:
replicaCount: 2
resources:
limits:
cpu: 1000m
memory: 1Gi
# Frontend scaling
frontend:
replicaCount: 2
# Auto-scaling
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 10
- Route Info Send: Forward user requests to Hub
- User Routing: Direct authenticated users to their pods
- SSL Termination: Handle HTTPS certificates
- Load Balancing: Distribute traffic across replicas
- Authenticate User: Google OAuth integration
- Signed Out User Redirect: Send unauthenticated users to login
- Volume Provide/Pod Create: Provision user resources
- User Redirect: Route users to their environments
- Cull Pods If Stale: Clean up inactive environments
- Image Pull: Download user environment containers
- User Session: Maintain persistent workspace state
- Resource Isolation: Dedicated CPU/memory/storage per user
- Data Persistence: User files survive pod restarts
1. User β Proxy β Hub (check authentication)
2. Hub β Google OAuth (if not authenticated)
3. Hub β Create/Find User Pod
4. Proxy β User Pod (direct traffic)
5. User Pod β Streamlit App (research environment)
# Check all services
kubectl get pods -n cmbcluster
# Backend health
curl https://api.yourdomain.com/health
# Frontend health
curl https://yourdomain.com/_stcore/health
# Backend logs
kubectl logs -f deployment/cmbcluster-backend -n cmbcluster
# Frontend logs
kubectl logs -f deployment/cmbcluster-frontend -n cmbcluster
# User environment logs
kubectl logs -n cmbcluster
# Ingress logs
kubectl logs -f deployment/ingress-nginx-controller -n ingress-nginx
The platform exposes Prometheus metrics:
# Backend metrics
cmbcluster_active_users
cmbcluster_pods_created_total
cmbcluster_authentication_requests_total
# Resource metrics
cmbcluster_cpu_usage
cmbcluster_memory_usage
cmbcluster_storage_usage
sequenceDiagram
participant U as User
participant P as Proxy
participant H as Hub
participant G as Google OAuth
U->>P: Access platform
P->>H: Check authentication
H->>G: Redirect to OAuth
G->>H: Return user info
H->>H: Create JWT token
H->>P: Redirect with token
P->>U: Access granted
- TLS 1.3: All traffic encrypted in transit
- Network Policies: Pod-to-pod communication restrictions
- Pod Security: Non-root containers, read-only filesystems
- RBAC: Kubernetes role-based access control
- Secrets Management: Encrypted credential storage
- Workspace Isolation: Each user has dedicated storage
- Encryption at Rest: Persistent volumes encrypted
- Data Retention: Configurable cleanup policies
- Backup Support: Regular workspace backups
# Check pod status
kubectl get pods -n cmbcluster
kubectl describe pod -n cmbcluster
kubectl logs -n cmbcluster
# Common causes:
# - Image pull errors
# - Resource constraints
# - Storage mounting issues
# Check OAuth configuration
kubectl get secret cmbcluster-secrets -n cmbcluster -o yaml
# Verify redirect URLs in Google Cloud Console
# Ensure domain matches configuration
# Check ingress status
kubectl get ingress -n cmbcluster
kubectl describe ingress cmbcluster-ingress -n cmbcluster
# Verify certificates
kubectl get certificates -n cmbcluster
kubectl describe certificate cmbcluster-tls -n cmbcluster
# Check persistent volumes
kubectl get pv
kubectl get pvc -n cmbcluster
# Storage class issues
kubectl get storageclass
# Get all resources
kubectl get all -n cmbcluster
# Check events
kubectl get events -n cmbcluster --sort-by='.lastTimestamp'
# Pod shell access (for debugging)
kubectl exec -it -n cmbcluster -- /bin/bash
# Port forwarding for local access
kubectl port-forward service/cmbcluster-backend 8000:80 -n cmbcluster
# Backend tests
cd backend
python -m pytest tests/
# Frontend tests
cd frontend
python -m pytest tests/
# End-to-end testing
pytest tests/integration/
# Load testing
locust -f tests/load/locustfile.py
# Test local deployment
make dev
curl http://localhost:8000/health
curl http://localhost:8501/_stcore/health
We welcome contributions! Please see our Contributing Guide for details.
# 1. Fork and clone repository
git clone https://github.com/yourusername/cmbcluster.git
cd cmbcluster
# 2. Create feature branch
git checkout -b feature/your-feature-name
# 3. Make changes and test locally
make dev
make test
# 4. Commit and push
git commit -m "Add your feature"
git push origin feature/your-feature-name
# 5. Create pull request
- Python: Follow PEP 8, use Black formatter
- Docker: Multi-stage builds, minimal base images
- Kubernetes: Follow security best practices
- Documentation: Update README and inline docs
- GPU Support: CUDA-enabled environments for ML workloads
- Advanced Monitoring: Grafana dashboards and alerting
- User Quotas: Storage and compute limits per user
- Backup System: Automated workspace backups
- Multi-cloud Support: AWS EKS and Azure AKS deployment
- Jupyter Integration: Built-in Jupyter notebook support
- Collaborative Features: Real-time collaboration tools
- Data Pipeline Integration: Connect with external data sources
- Enterprise SSO: SAML and LDAP integration
- Advanced Analytics: Usage analytics and cost optimization
- Custom Environments: User-defined container images
- Federation: Multi-cluster deployments
- π Documentation: GitHub Wiki
- π Bug Reports: Issue Tracker
- π¬ Discussions: GitHub Discussions
- π§ Email: [email protected]
- Slack: Join our CMBCluster Slack
- Monthly Meetings: First Friday of each month at 10 AM PST
- Office Hours: Wednesdays 2-3 PM PST
This project is licensed under the MIT License - see the LICENSE file for details.
- Built on the JupyterHub architecture pattern
- Inspired by the research community needs
- Special thanks to early adopters and contributors
- Container orchestration powered by Kubernetes
CMBCluster - Empowering research through scalable, secure, and collaborative computing environments.
For more information, visit our GitHub repository or contact us at [email protected].