- 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
287 lines
7.5 KiB
YAML
287 lines
7.5 KiB
YAML
# Copyright 2026 Umbra Tools (umbratools.com)
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
---
|
|
# Secret for database credentials (created by CNPG, but we reference it)
|
|
# This is a template - CNPG creates the actual secret
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: umbratrans-db-credentials
|
|
namespace: umbratrans
|
|
type: kubernetes.io/basic-auth
|
|
stringData:
|
|
username: "umbratrans"
|
|
password: "CHANGE_ME_GENERATED_BY_CNPG"
|
|
# DSN format: postgresql://user:pass@host:port/db?sslmode=require
|
|
dsn: "postgresql://umbratrans:CHANGE_ME@umbratrans-db-rw:5432/umbratrans?sslmode=require"
|
|
|
|
---
|
|
# Secret for SMTP credentials
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: umbratrans-smtp
|
|
namespace: umbratrans
|
|
type: Opaque
|
|
stringData:
|
|
host: "smtp.example.com"
|
|
port: "587"
|
|
username: "umbra@example.com"
|
|
password: "CHANGE_ME_SMTP_PASSWORD"
|
|
sender: "umbratrans@umbra.example.com"
|
|
|
|
---
|
|
# Secret for application secrets (token pepper, etc.)
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: umbratrans-secrets
|
|
namespace: umbratrans
|
|
type: Opaque
|
|
stringData:
|
|
token_pepper: "CHANGE_ME_32_BYTES_MINIMUM_BASE64_ENCODED"
|
|
|
|
---
|
|
# Secret for PgBouncer admin (generated by CNPG)
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: umbratrans-pgbouncer-admin
|
|
namespace: umbratrans
|
|
type: Opaque
|
|
stringData:
|
|
username: "pgbouncer_admin"
|
|
password: "CHANGE_ME_GENERATED_BY_CNPG"
|
|
|
|
---
|
|
# Secret for backup credentials (S3)
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: umbratrans-backup-credentials
|
|
namespace: umbratrans
|
|
type: Opaque
|
|
stringData:
|
|
ACCESS_KEY_ID: "CHANGE_ME"
|
|
SECRET_ACCESS_KEY: "CHANGE_ME"
|
|
|
|
---
|
|
# TLS certificate for ingress (managed by cert-manager)
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: umbratrans-tls
|
|
namespace: umbratrans
|
|
type: kubernetes.io/tls
|
|
data:
|
|
# cert-manager will populate this
|
|
tls.crt: ""
|
|
tls.key: ""
|
|
|
|
---
|
|
# ServiceMonitor for Prometheus (requires Prometheus Operator)
|
|
apiVersion: monitoring.coreos.com/v1
|
|
kind: ServiceMonitor
|
|
metadata:
|
|
name: umbratrans-web
|
|
namespace: umbratrans
|
|
labels:
|
|
release: prometheus
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
app: umbratrans-web
|
|
endpoints:
|
|
- port: http
|
|
path: /api/metrics
|
|
interval: 30s
|
|
namespaceSelector:
|
|
matchNames:
|
|
- umbratrans
|
|
|
|
---
|
|
apiVersion: monitoring.coreos.com/v1
|
|
kind: ServiceMonitor
|
|
metadata:
|
|
name: umbratrans-workers
|
|
namespace: umbratrans
|
|
labels:
|
|
release: prometheus
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
component: worker
|
|
endpoints:
|
|
- port: metrics
|
|
path: /metrics
|
|
interval: 30s
|
|
namespaceSelector:
|
|
matchNames:
|
|
- umbratrans
|
|
|
|
---
|
|
# PodMonitor for PostgreSQL (CNPG)
|
|
apiVersion: monitoring.coreos.com/v1
|
|
kind: PodMonitor
|
|
metadata:
|
|
name: umbratrans-db
|
|
namespace: umbratrans
|
|
labels:
|
|
release: prometheus
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
app: umbratrans-db
|
|
podMetricsEndpoints:
|
|
- port: metrics
|
|
path: /metrics
|
|
interval: 30s
|
|
|
|
---
|
|
# ConfigMap for custom PostgreSQL queries
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: umbratrans-db-queries
|
|
namespace: umbratrans
|
|
data:
|
|
umbratrans_queries.yaml: |
|
|
- name: umbratrans_projects_total
|
|
query: |
|
|
SELECT count(*) as value FROM projects;
|
|
metrics:
|
|
- value
|
|
- name: umbratrans_active_jobs
|
|
query: |
|
|
SELECT count(*) as value FROM jobs WHERE status IN ('queued', 'running', 'blocked');
|
|
metrics:
|
|
- value
|
|
- name: umbratrans_translation_queue_depth
|
|
query: |
|
|
SELECT count(*) as value FROM jobs WHERE kind = 'translate' AND status = 'queued';
|
|
metrics:
|
|
- value
|
|
- name: umbratrans_audio_queue_depth
|
|
query: |
|
|
SELECT count(*) as value FROM jobs WHERE kind LIKE 'audio%' AND status = 'queued';
|
|
metrics:
|
|
- value
|
|
- name: umbratrans_artifacts_total
|
|
query: |
|
|
SELECT count(*) as value FROM artifacts;
|
|
metrics:
|
|
- value
|
|
- name: umbratrans_artifacts_size_bytes
|
|
query: |
|
|
SELECT sum(byte_size) as value FROM artifacts;
|
|
metrics:
|
|
- value
|
|
- name: umbratrans_import_runs_total
|
|
query: |
|
|
SELECT count(*) as value FROM translation_imports;
|
|
metrics:
|
|
- value
|
|
|
|
---
|
|
# PrometheusRule for alerts
|
|
apiVersion: monitoring.coreos.com/v1
|
|
kind: PrometheusRule
|
|
metadata:
|
|
name: umbratrans-alerts
|
|
namespace: umbratrans
|
|
labels:
|
|
release: prometheus
|
|
spec:
|
|
groups:
|
|
- name: umbratrans.rules
|
|
rules:
|
|
- alert: UmbraTransWebDown
|
|
expr: up{job="umbratrans-web"} == 0
|
|
for: 2m
|
|
labels:
|
|
severity: critical
|
|
annotations:
|
|
summary: "UmbraTrans web is down"
|
|
description: "UmbraTrans web has been down for more than 2 minutes."
|
|
|
|
- alert: UmbraTransHighErrorRate
|
|
expr: |
|
|
sum(rate(http_requests_total{job="umbratrans-web",code=~"5.."}[5m]))
|
|
/
|
|
sum(rate(http_requests_total{job="umbratrans-web"}[5m])) > 0.05
|
|
for: 5m
|
|
labels:
|
|
severity: warning
|
|
annotations:
|
|
summary: "High error rate on UmbraTrans web"
|
|
description: "Error rate is above 5% for the last 5 minutes."
|
|
|
|
- alert: UmbraTransDBConnectionsHigh
|
|
expr: |
|
|
pg_stat_database_numbackends / pg_settings_max_connections > 0.8
|
|
for: 5m
|
|
labels:
|
|
severity: warning
|
|
annotations:
|
|
summary: "PostgreSQL connections near limit"
|
|
description: "Database connections are above 80% of max_connections."
|
|
|
|
- alert: UmbraTransTranslationQueueBacklog
|
|
expr: umbratrans_translation_queue_depth > 100
|
|
for: 10m
|
|
labels:
|
|
severity: warning
|
|
annotations:
|
|
summary: "Translation queue backlog"
|
|
description: "Translation queue has more than 100 pending jobs for 10 minutes."
|
|
|
|
- alert: UmbraTransAudioQueueBacklog
|
|
expr: umbratrans_audio_queue_depth > 50
|
|
for: 10m
|
|
labels:
|
|
severity: warning
|
|
annotations:
|
|
summary: "Audio queue backlog"
|
|
description: "Audio queue has more than 50 pending jobs for 10 minutes."
|
|
|
|
- alert: UmbraTransDiskSpaceLow
|
|
expr: |
|
|
(kubelet_volume_stats_available_bytes / kubelet_volume_stats_capacity_bytes) < 0.1
|
|
for: 5m
|
|
labels:
|
|
severity: critical
|
|
annotations:
|
|
summary: "Disk space low on UmbraTrans volumes"
|
|
description: "Less than 10% disk space remaining on persistent volumes."
|
|
|
|
- alert: UmbraTransWorkerTranslationDown
|
|
expr: |
|
|
kube_deployment_status_replicas_available{deployment="umbratrans-worker-translation"} < 1
|
|
for: 5m
|
|
labels:
|
|
severity: critical
|
|
annotations:
|
|
summary: "No translation workers available"
|
|
description: "All translation worker pods are down."
|
|
|
|
- alert: UmbraTransWorkerAudioDown
|
|
expr: |
|
|
kube_deployment_status_replicas_available{deployment="umbratrans-worker-audio"} < 1
|
|
for: 5m
|
|
labels:
|
|
severity: critical
|
|
annotations:
|
|
summary: "No audio workers available"
|
|
description: "All audio worker pods are down."
|
|
|
|
- alert: UmbraTransImportJobFailed
|
|
expr: |
|
|
kube_job_status_failed{job=~"umbratrans-import.*"} > 0
|
|
for: 1m
|
|
labels:
|
|
severity: warning
|
|
annotations:
|
|
summary: "UmbraTrans import job failed"
|
|
description: "Production import job has failed."
|