Kubernetes Deployment
Kubernetes Deployment
Message Center ships with a complete set of Kubernetes manifests in the k8s/ directory. This page covers what each manifest does, how to configure it for your environment, and the recommended deploy sequence.
Manifests Overview
k8s/
├── deployment.yaml — Application pod spec (replicas, resources, probes, volumes)
├── service.yaml — ClusterIP Service exposing port 3000
├── configmap.yaml — Non-secret environment variables
├── secret.yaml — Template for Kubernetes Secrets (edit before apply)
└── ingress.yaml — Ingress resource (nginx example; edit host)
Deployment
Resource limits
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
These are baseline values. See Capacity Planning for tuning guidance.
Health probes
Both probes target the /api/health endpoint:
livenessProbe:
httpGet:
path: /api/health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/health
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
The health endpoint returns 200 OK once the Next.js server is ready. It does not require MongoDB or Core to be reachable — those are checked separately via the Diagnostics page.
mTLS certificate volume
Certificates are injected via a Secret volume (see mTLS Certificates):
volumes:
- name: mtls-certs
secret:
secretName: message-center-mtls-certs
containers:
- name: core-admin
volumeMounts:
- name: mtls-certs
mountPath: /app/certs
readOnly: true
Rolling update strategy
The default strategy is RollingUpdate with maxUnavailable: 0 to ensure zero-downtime deploys:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
ConfigMap
k8s/configmap.yaml holds non-secret configuration:
data:
NODE_ENV: "production"
NEXTAUTH_URL: "https://admin.yourcompany.com"
MONGODB_DB: "message_center"
CORE_API_URL: "https://core.internal:8080"
CORE_HEALTH_URL: "http://core.internal:8092/health"
PROXY_LOGIN_URL: "https://proxy.internal:8088/api/v1/user/login"
AUDIT_RETENTION_DAYS: "90"
CORE_TLS_CERT_FILE: "/app/certs/core.crt"
CORE_TLS_KEY_FILE: "/app/certs/core.key"
CORE_TLS_CA_FILE: "/app/certs/ca.crt"
PROXY_TLS_CERT_FILE: "/app/certs/core.crt"
PROXY_TLS_KEY_FILE: "/app/certs/core.key"
PROXY_TLS_CA_FILE: "/app/certs/ca.crt"
Secrets
Create the application Secrets before first deploy:
kubectl create secret generic message-center-secrets \
--from-literal=NEXTAUTH_SECRET=$(openssl rand -base64 32) \
--from-literal=MONGODB_URI=mongodb://... \
--from-literal=BFF_PROXY_EMAIL=... \
--from-literal=BFF_PROXY_PASSWORD=... \
--from-literal=CORE_ADMIN_API_KEY=... \
-n default
And the mTLS certificates Secret:
kubectl create secret generic message-center-mtls-certs \
--from-file=ca.crt=certs/ca/ca.crt \
--from-file=core.crt=certs/client/core.crt \
--from-file=core.key=certs/client/core.key \
-n default
Deploy Sequence
Initial deploy
# 1. Create Secrets (once)
kubectl create secret generic message-center-secrets ...
kubectl create secret generic message-center-mtls-certs ...
# 2. Dry run — validate manifests without applying
make k8s-dry-run
# 3. Run migrations
kubectl run -it --rm migrate \
--image=<your-registry>/core-admin:latest \
--restart=Never \
-- yarn migrate
# 4. Seed the database (first time only)
kubectl run -it --rm seed \
--image=<your-registry>/core-admin:latest \
--restart=Never \
-- yarn seed
# 5. Apply all manifests
make k8s-deploy
# 6. Check status
make k8s-status
Subsequent deploys
# 1. Run migrations before the new pods start
kubectl run -it --rm migrate \
--image=<your-registry>/core-admin:latest \
--restart=Never \
-- yarn migrate
# 2. Update image tag and apply
kubectl set image deployment/core-admin \
core-admin=<your-registry>/core-admin:<new-tag>
# 3. Verify rollout
kubectl rollout status deployment/core-admin
Useful Commands
make k8s-dry-run # Validate manifests (--dry-run=client)
make k8s-deploy # Apply all manifests
make k8s-status # Show pod, service, and ingress status
kubectl logs -l app=core-admin --tail=100 # Stream recent logs
kubectl exec -it <pod> -- sh # Shell into pod
Ingress
k8s/ingress.yaml provides an nginx Ingress example. Edit the host field and TLS Secret name before applying:
spec:
rules:
- host: admin.yourcompany.com
http:
paths:
- path: /
backend:
service:
name: core-admin
port:
number: 3000
tls:
- hosts:
- admin.yourcompany.com
secretName: message-center-tls
NetworkPolicy
Restrict inbound and outbound access at the Kubernetes level:
# Allow only browser traffic in (port 3000) and MongoDB/Core/Proxy out
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: core-admin
spec:
podSelector:
matchLabels:
app: core-admin
policyTypes:
- Ingress
- Egress
ingress:
- ports:
- port: 3000
egress:
- ports:
- port: 27017 # MongoDB
- port: 8080 # Core API
- port: 8088 # Proxy login
- port: 8089 # Proxy API
- port: 8092 # Core health
Next Steps
- Environment Variables Reference — complete env var reference
- mTLS Certificates — certificate rotation procedure
- Capacity Planning — resource limit tuning