Skip to main content

Kubernetes Deployment

Production-ready Helm chart for deploying LoyaltyOS on Kubernetes.

Prerequisites​

  • Kubernetes 1.25+
  • Helm 3.12+
  • Bitnami chart repository (for PostgreSQL and Redis sub-charts)
  • Optional: cert-manager (for TLS), Prometheus Operator (for ServiceMonitor), External Secrets Operator (for secret management)

Quick Start​

1. Add the Bitnami repository and update dependencies​

helm repo add bitnami https://charts.bitnami.com/bitnami
helm dependency update infra/k8s/helm/loyaltyos

2. Lint the chart​

helm lint infra/k8s/helm/loyaltyos

3. Dry-run to verify generated manifests​

helm template loyaltyos infra/k8s/helm/loyaltyos --debug

4. Install on a local cluster​

cat > my-values.yaml <<EOF
postgresql:
auth:
password: "dev-password-123"
redis:
auth:
password: "dev-redis-123"
api:
env:
JWT_SECRET: "dev-jwt-secret-at-least-32-chars!!"
API_KEY_SALT: "dev-salt"
KMS_MASTER_KEY: "0000000000000000000000000000000000000000000000000000000000000001"
EOF

helm install loyaltyos infra/k8s/helm/loyaltyos -f my-values.yaml

5. Wait for migrations and pods​

kubectl wait --for=condition=complete job/loyaltyos-migrations --timeout=120s
kubectl get pods -w

Architecture​

┌──────────────┐
│ Ingress │
│ (nginx/ALB) │
└──┬───┬───┬───┘
│ │ │
┌────────────┘ │ └────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ API Pods │ │ Admin Pod │ │Portal Pod │
│ (HPA 2+) │ │ (nginx) │ │ (nginx) │
└─────┬──────┘ └────────────┘ └────────────┘
│
┌────┴────┐
▼ ▼
┌────────┐ ┌───────┐ ┌──────────────┐
│PostgreSQL│ │ Redis │ │BullMQ Worker │
│(subchart)│ │(subchart)│ │ (separate │
└────────┘ └───────┘ │ scaling) │
└──────────────┘

Components​

ComponentKindScalingDescription
APIDeployment + HPA2–10 replicasFastify server, auto-scales on CPU/memory
AdminDeployment1 replicaReact SPA served via nginx+brotli
PortalDeployment1 replicaCustomer-facing portal via nginx+brotli
BullMQ WorkerDeployment2 replicasBackground job processor
MigrationsJob (Helm hook)run-oncePrisma migrate deploy
PostgreSQLStatefulSet (sub)1 replicaBitnami PostgreSQL 16.x
RedisStatefulSet (sub)1 replicaBitnami Redis 7.x

Key Toggles​

ValueDefaultDescription
api.enabledtrueDeploy the API server
admin.enabledtrueDeploy the Admin dashboard
portal.enabledtrueDeploy the Customer Portal
bullmqWorker.enabledtrueDeploy the BullMQ worker
api.autoscaling.enabledtrueEnable HPA for the API
ingress.enabledfalseCreate API Ingress
networkPolicy.enabledtrueRestrict pod-to-pod traffic
monitoring.serviceMonitor.enabledtrueCreate Prometheus ServiceMonitor
externalSecrets.enabledfalseUse External Secrets Operator

Using External Databases​

postgresql:
enabled: false
redis:
enabled: false

externalDatabase:
enabled: true
host: my-rds-instance.aws.com
port: 5432
user: loyaltyos
password: "secure-password"
database: loyaltyos
ssl: true

externalRedis:
enabled: true
host: my-elasticache.aws.com
port: 6379
password: "redis-password"

Local Development with kind​

kind create cluster --name loyaltyos

# Install ingress-nginx
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml

# Install with ingress enabled
helm install loyaltyos infra/k8s/helm/loyaltyos \
--set ingress.enabled=true \
--set ingress.hosts[0].host=api.loyaltyos.local

Troubleshooting​

# Migrations job logs
kubectl logs job/loyaltyos-migrations

# Test DB connectivity
kubectl port-forward svc/loyaltyos-postgresql 5432:5432
psql -h localhost -U loyaltyos -d loyaltyos

# Check HPA status
kubectl get hpa loyaltyos-api

# Check Prometheus metrics
kubectl port-forward svc/loyaltyos-api 3002:3002
curl http://localhost:3002/metrics