Skip to main content

Kubernetes

Deploy Batchivo on Kubernetes for production-grade scalability.

Prerequisites

  • Kubernetes cluster (1.25+)
  • kubectl configured
  • Helm 3 (optional, for charts)

Quick Start

# Apply namespace
kubectl apply -f infrastructure/k8s/namespace.yaml

# Create secrets
kubectl create secret generic backend-secrets \
--from-literal=SECRET_KEY=$(openssl rand -base64 64) \
--from-literal=DATABASE_URL=postgresql+psycopg://user:pass@postgres:5432/batchivo \
-n batchivo

# Apply all manifests
kubectl apply -f infrastructure/k8s/ -n batchivo

Manifests

Namespace

# infrastructure/k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: batchivo

Backend Deployment

# infrastructure/k8s/backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: batchivo
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: ghcr.io/techize/batchivo-backend:latest
ports:
- containerPort: 8000
envFrom:
- secretRef:
name: backend-secrets
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 10

Frontend Deployment

# infrastructure/k8s/frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: batchivo
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: ghcr.io/techize/batchivo-frontend:latest
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"

Services

# infrastructure/k8s/services.yaml
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: batchivo
spec:
selector:
app: backend
ports:
- port: 8000
targetPort: 8000
---
apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: batchivo
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80

Ingress

nginx Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: batchivo
namespace: batchivo
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- batchivo.example.com
secretName: batchivo-tls
rules:
- host: batchivo.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend
port:
number: 8000
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80

Database

For production, use a managed PostgreSQL service or deploy PostgreSQL with persistent storage.

PostgreSQL StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: batchivo
spec:
serviceName: postgres
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: batchivo
- name: POSTGRES_USER
value: batchivo
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secrets
key: password
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi

Monitoring

Batchivo exposes Prometheus metrics at /metrics when ENABLE_METRICS=true.

# ServiceMonitor for Prometheus Operator
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: batchivo-backend
namespace: batchivo
spec:
selector:
matchLabels:
app: backend
endpoints:
- port: http
path: /metrics