Skip to main content

Kubernetes

Stateless Deployment + Service + ConfigMap + Secret.

Deployment

# auth-backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-backend
spec:
replicas: 3
selector:
matchLabels: { app: auth-backend }
template:
metadata:
labels: { app: auth-backend }
spec:
containers:
- name: auth
image: ghcr.io/identsphere/server:0.1
ports:
- containerPort: 4000
envFrom:
- configMapRef:
name: auth-config
env:
- name: IDENTSPHERE_JWT_SECRET
valueFrom:
secretKeyRef:
name: auth-secrets
key: jwt-secret
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: auth-secrets
key: database-url
resources:
requests: { cpu: 200m, memory: 256Mi }
limits: { cpu: 1000m, memory: 1Gi }
readinessProbe:
httpGet: { path: /health, port: 4000 }
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet: { path: /health, port: 4000 }
initialDelaySeconds: 30
periodSeconds: 30

Service + Ingress

---
apiVersion: v1
kind: Service
metadata:
name: auth-backend
spec:
selector: { app: auth-backend }
ports:
- port: 80
targetPort: 4000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auth-backend
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: 6m # avatar uploads up to 5 MiB
spec:
ingressClassName: nginx
tls:
- hosts: [auth.example.com]
secretName: auth-tls
rules:
- host: auth.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service: { name: auth-backend, port: { number: 80 } }

ConfigMap + Secret

---
apiVersion: v1
kind: ConfigMap
metadata:
name: auth-config
data:
IDENTSPHERE_PUBLIC_BASE_URL: "https://auth.example.com"
IDENTSPHERE_FROM_EMAIL: "no-reply@example.com"
IDENTSPHERE_COOKIES_SECURE: "true"
IDENTSPHERE_RP_ID: "auth.example.com"
IDENTSPHERE_RP_ORIGIN: "https://auth.example.com"
IDENTSPHERE_APP_NAME: "Acme"
RUST_LOG: "info,identsphere=debug"
---
apiVersion: v1
kind: Secret
metadata:
name: auth-secrets
type: Opaque
stringData:
jwt-secret: "REPLACE_WITH_OPENSSL_RAND_HEX_32"
database-url: "postgres://user:pw@postgres:5432/auth?sslmode=require"

Migrations as a Job

Run before each rollout:

apiVersion: batch/v1
kind: Job
metadata:
name: auth-migrate
spec:
ttlSecondsAfterFinished: 600
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: ghcr.io/identsphere/server:0.1
command: ["IdentSphere", "migrate", "up", "--schema", "identsphere"]
envFrom:
- secretRef: { name: auth-secrets }

Hook into your CI as a pre-deploy step. Migrations are idempotent and take an advisory lock.

Horizontal Pod Autoscaler

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: auth-backend
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: auth-backend
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70

CPU-based scaling tracks Argon2id load well.

PodDisruptionBudget

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: auth-backend
spec:
minAvailable: 2
selector:
matchLabels: { app: auth-backend }

Helm

A community Helm chart will live in charts/auth-backend/ (planned). For now, paste the manifests above into templates/ and add a basic values.yaml over the values you want to parameterize.

Secrets management

The Secret YAML above is illustrative. In production use:

  • AWS: External Secrets Operator + Secrets Manager.
  • GCP: External Secrets Operator + Secret Manager.
  • Azure: AKS + CSI driver + Key Vault.
  • HashiCorp Vault: VSO or vault-injector.

Avoid checking the secret YAML into Git.