Kubernetes Deployment

📦v1.0.0📅2026-04-28🔄Updated 2026-04-28👤Admin Team
administrationdeploymentkubernetesk8s

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