Operations Deployment Kubernetes - osama1998H/Moca GitHub Wiki

Kubernetes Deployment

Deploy Moca on Kubernetes for cloud-native, horizontally scalable workloads. The moca generate k8s command produces all required manifests.

Prerequisites

  • Kubernetes 1.28+
  • kubectl configured against your target cluster
  • Moca CLI installed locally
  • Container images available (pre-built from ghcr.io or locally built)

Step 1: Generate Manifests

Run the generator from your project root:

moca generate k8s

This produces a k8s/ directory with the following manifests:

Manifest Purpose
namespace.yaml Dedicated namespace for Moca resources
configmap.yaml Non-secret configuration (domain, feature flags)
secret.yaml Database password, Redis password, Meilisearch API key, secret key
deployment-server.yaml moca-server Deployment + Service
deployment-worker.yaml moca-worker Deployment
deployment-scheduler.yaml moca-scheduler Deployment (single replica)
deployment-outbox.yaml moca-outbox Deployment (single replica)

Step 2: Configure Secrets

The generated secret.yaml uses placeholder values. Replace them with your base64-encoded secrets before applying:

echo -n "your-db-password" | base64
echo -n "your-redis-password" | base64
echo -n "your-meili-api-key" | base64
echo -n "your-secret-key" | base64

For production, prefer an external secrets manager instead of storing secrets in-cluster:

Step 3: Apply Manifests

Apply the manifests in order:

kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secret.yaml
kubectl apply -f k8s/deployment-server.yaml
kubectl apply -f k8s/deployment-worker.yaml
kubectl apply -f k8s/deployment-scheduler.yaml
kubectl apply -f k8s/deployment-outbox.yaml

Step 4: Verify

Check that all pods are running:

kubectl get pods -n moca

Inspect server logs:

kubectl logs -n moca -l app=moca-server --tail=50

Ingress Configuration

The generator produces a basic Ingress. For TLS with cert-manager, annotate the Ingress resource:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: moca-ingress
  namespace: moca
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - mysite.example.com
      secretName: moca-tls
  rules:
    - host: mysite.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: moca-server
                port:
                  number: 8000

HPA Tuning

Horizontal Pod Autoscaler configuration for CPU and memory-based scaling:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: moca-server-hpa
  namespace: moca
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: moca-server
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

Recommended scaling bounds per process:

Process Min Replicas Max Replicas Notes
moca-server 2 10 Scale on CPU + memory
moca-worker 1 5 Scale on queue depth (KEDA recommended)
moca-scheduler 1 1 Leader election enforces single active instance
moca-outbox 1 1 Single instance per site

Multi-Tenant Considerations

  • Use a dedicated namespace per environment (e.g., moca-staging, moca-production).
  • PostgreSQL schema-per-tenant isolation is enforced at the application level — all tenants share the same database pods.
  • For high tenant counts (1 000+), use Meilisearch tenant tokens instead of per-tenant indexes to reduce index overhead. See ADR-006.

Database

For production, run PostgreSQL outside the cluster (managed services recommended):

  • AWS RDS for PostgreSQL / Aurora PostgreSQL
  • Google Cloud SQL for PostgreSQL
  • Azure Database for PostgreSQL

Running stateful workloads inside Kubernetes adds operational complexity (volume management, failover, backups) that managed services handle automatically. Store the connection string in the Kubernetes Secret generated by moca generate k8s.