Files
UmbraDatastore/docs/DEPLOYMENT_GUIDE.md
umbra audio cce2ce55dc Initial commit: UmbraDatastore configuration and deployment scripts
- Database deployment script (scripts/deploy-database.sh)
- Kubernetes manifests for CNPG PostgreSQL cluster (k8s/base/)
- Documentation (docs/DEPLOYMENT_GUIDE.md, DATASTORE_SPEC.md, INTEGRATION_SPEC.md)
- README with architecture overview and operations guide
2026-10-31 19:47:27 -07:00

307 lines
8.7 KiB
Markdown

# UmbraTrans Kubernetes Deployment - Quick Start
## Prerequisites
- Kubernetes cluster (v1.28+)
- NFS server accessible from cluster (`192.168.123.14:/mnt/umbra-data`)
- S3-compatible storage for backups
- cert-manager installed for TLS
- nginx-ingress controller
- NVIDIA GPU operator (for worker nodes)
- CloudNativePG operator
## 1. Install Operators
```bash
# CloudNativePG
kubectl apply -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.24/releases/cnpg-1.24.0.yaml
# NFS CSI Driver
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/v4.7.0/deploy/example/nfs-driver.yaml
# cert-manager (if not installed)
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml
# NVIDIA GPU Operator (on GPU nodes)
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm install gpu-operator nvidia/gpu-operator -n gpu-operator --create-namespace
```
## 2. Configure Secrets
```bash
# Create namespace
kubectl create namespace umbratrans
# Database credentials (CNPG will also create these)
kubectl create secret generic umbratrans-db-credentials \
-n umbratrans \
--from-literal=username=umbratrans \
--from-literal=password=$(openssl rand -base64 32) \
--from-literal=dsn="postgresql://umbratrans:PASSWORD@umbratrans-db-rw:5432/umbratrans?sslmode=require"
# SMTP credentials
kubectl create secret generic umbratrans-smtp \
-n umbratrans \
--from-literal=host=smtp.example.com \
--from-literal=port=587 \
--from-literal=username=umbra@example.com \
--from-literal=password=YOUR_SMTP_PASSWORD \
--from-literal=sender=umbratrans@umbra.example.com
# Application secrets
kubectl create secret generic umbratrans-secrets \
-n umbratrans \
--from-literal=token_pepper=$(openssl rand -base64 32)
# Backup credentials
kubectl create secret generic umbratrans-backup-credentials \
-n umbratrans \
--from-literal=ACCESS_KEY_ID=YOUR_S3_ACCESS_KEY \
--from-literal=SECRET_ACCESS_KEY=YOUR_S3_SECRET_KEY
# PgBouncer admin
kubectl create secret generic umbratrans-pgbouncer-admin \
-n umbratrans \
--from-literal=username=pgbouncer_admin \
--from-literal=password=$(openssl rand -base64 32)
```
## 3. Update Configuration
Edit these files with your values:
- `k8s/base/01-postgresql.yaml` - S3 backup endpoint
- `k8s/base/02-nfs-storage.yaml` - NFS server IP (`192.168.123.14`)
- `k8s/base/03-web-deployment.yaml` - Ingress host (`umbratrans.bdmurphy.me`)
- `k8s/base/05-ingress-network.yaml` - TLS hosts
## 4. Build Images
```bash
# Build web image
docker build -f Dockerfile.web -t umbratrans-web:latest .
docker push your-registry/umbratrans-web:latest
# Build worker image
docker build -f Dockerfile.worker -t umbratrans-worker:latest .
docker push your-registry/umbratrans-worker:latest
# Update image references in k8s/base/kustomization.yaml
```
## 5. Deploy
```bash
# Development
kubectl apply -k k8s/overlays/dev
# Production
kubectl apply -k k8s/overlays/prod
```
## 6. Run Migrations
```bash
# Migrations run automatically via initContainer on web deployment
# Or run manually:
kubectl run migrate --rm -it --image=umbratrans-web:latest \
--env="UMBRA_ENV=production" \
--env="UMBRATRANS_DATABASE_DSN=$(kubectl get secret umbratrans-db-credentials -n umbratrans -o jsonpath='{.data.dsn}' | base64 -d)" \
-- python -m umbratrans_web.cli migrate --allow-production
```
## 7. Import Existing Productions
```bash
# One-time import
kubectl apply -f k8s/base/06-import-job.yaml
# Or run manually:
kubectl run import --rm -it --image=umbratrans-worker:latest \
--env="UMBRA_ENV=production" \
--env="UMBRATRANS_DATABASE_DSN=..." \
--env="UMBRATRANS_PRODUCTIONS_ROOT=/mnt/productions" \
-- python -m umbratrans_web.cli import-productions \
--organization umbra \
--allow-production \
--confirm
```
## 8. Verify Deployment
```bash
# Check pods
kubectl get pods -n umbratrans
# Check web health
curl -k https://umbratrans.bdmurphy.me/api/health
# Check database
kubectl exec -n umbratrans umbratrans-db-1 -- pg_isready -U umbratrans
# Check workers processing jobs
kubectl logs -n umbratrans -l app=umbratrans-worker-translation -f
```
## 9. Monitoring
```bash
# Port-forward Prometheus
kubectl port-forward -n monitoring svc/prometheus 9090
# Port-forward Grafana
kubectl port-forward -n monitoring svc/grafana 3000
```
## 10. Common Operations
### Scale Workers
```bash
# Translation workers
kubectl scale deployment umbratrans-worker-translation -n umbratrans --replicas=10
# Audio workers
kubectl scale deployment umbratrans-worker-audio -n umbratrans --replicas=5
```
### View Logs
```bash
# Web
kubectl logs -n umbratrans -l app=umbratrans-web -f
# Translation worker
kubectl logs -n umbratrans -l app=umbratrans-worker-translation -f
# Audio worker
kubectl logs -n umbratrans -l app=umbratrans-worker-audio -f
# Database
kubectl logs -n umbratrans -l app=umbratrans-db -f
```
### Database Access
```bash
# Connect to primary
kubectl exec -it -n umbratrans umbratrans-db-1 -- psql -U umbratrans -d umbratrans
# Connect via PgBouncer (pooled)
kubectl run -it --rm pgclient --image=postgres:16 -- \
psql "postgresql://umbratrans:PASSWORD@umbratrans-db-pgbouncer:6432/umbratrans"
```
### Backup/Restore
```bash
# Create manual backup
kubectl apply -f - <<EOF
apiVersion: postgresql.cnpg.io/v1
kind: Backup
metadata:
name: manual-backup-$(date +%s)
namespace: umbratrans
spec:
cluster: umbratrans-db
EOF
# List backups
kubectl get backups -n umbratrans
# Restore to new cluster
kubectl apply -f - <<EOF
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: umbratrans-db-restored
namespace: umbratrans
spec:
instances: 1
storage:
size: 50Gi
bootstrap:
recovery:
source: umbratrans-db
backup:
name: manual-backup-1234567890
EOF
```
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Web pod CrashLoopBackOff | Check logs: `kubectl logs -n umbratrans -l app=umbratrans-web` |
| Workers not picking jobs | Verify DB connectivity, check job queue: `SELECT * FROM jobs WHERE status='queued'` |
| NFS mount failures | Check NFS server reachable, CSI driver pods running |
| GPU not allocated | Verify GPU operator, node labels `nvidia.com/gpu.present=true` |
| Migration failures | Check migration logs, run manually with `--dry-run` first |
| TLS certificate issues | Check cert-manager logs, verify DNS challenge |
## File Inventory
```
k8s/
├── base/
│ ├── 00-namespace.yaml
│ ├── 01-postgresql.yaml # CNPG cluster
│ ├── 02-nfs-storage.yaml # NFS CSI, PVs, PVCs
│ ├── 03-web-deployment.yaml # Web API + UI
│ ├── 04-worker-deployments.yaml # Translation + Audio workers
│ ├── 05-ingress-network.yaml # Ingress + NetworkPolicies
│ ├── 06-import-job.yaml # Production import job
│ ├── 07-monitoring-secrets.yaml # Secrets, ServiceMonitors, Alerts
│ └── kustomization.yaml
├── overlays/
│ ├── dev/kustomization.yaml # Dev overrides
│ ├── staging/kustomization.yaml # Staging overrides
│ └── prod/kustomization.yaml # Production overrides
Dockerfile.web # Web container
Dockerfile.worker # Worker container (GPU)
DATASTORE_SPEC.md # Complete datastore contract
umbratrans_web/cli.py # CLI: migrate, import-productions, worker
```
## CLI Commands Reference
```bash
# Bootstrap admin (dev only)
python -m umbratrans_web.cli bootstrap-admin --email admin@example.com
# Serve web (dev/prod)
python -m umbratrans_web.serve --host 0.0.0.0 --port 8442 --repository postgres --allow-production
# Run migrations
python -m umbratrans_web.cli migrate --allow-production
# Import productions
python -m umbratrans_web.cli import-productions --organization umbra --allow-production --confirm
# Run workers
python -m umbratrans_web.cli worker translation --allow-production
python -m umbratrans_web.cli worker audio --allow-production
# Import audio bundle
python -m umbratrans_web.cli import-audio --bundle /path/to/bundle --organization-id <uuid> --commit --confirm <hash>
```
## External Service Integration
For **UmbraAudio** and **UmbraFormat** (running on separate machines), see:
**→ [INTEGRATION_SPEC.md](INTEGRATION_SPEC.md)**
This document covers:
- PostgreSQL connection parameters (PgBouncer on 6432)
- NFS mount configuration (/mnt/umbra-data)
- Job queue protocol (claim/complete via `FOR UPDATE SKIP LOCKED`)
- Artifact storage protocol (content-addressed, NFS + PostgreSQL)
- Compute node registration & heartbeats
- Model registry
- Audio import bundle format
- Format metadata API
- Webhooks for job completion
- Required database roles and grants
- Health checks and monitoring metrics