Skip to content

infra(k8s): add Kubernetes manifests for api, app, processing, and postgres#286

Merged
Xhristin3 merged 1 commit into
XStreamRollz:mainfrom
MicD746:infra/k8s-manifests-issue-217
Jun 17, 2026
Merged

infra(k8s): add Kubernetes manifests for api, app, processing, and postgres#286
Xhristin3 merged 1 commit into
XStreamRollz:mainfrom
MicD746:infra/k8s-manifests-issue-217

Conversation

@MicD746

@MicD746 MicD746 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Resolves #217 by adding a complete k8s/ deployment for the XStreamRoll platform (api, app, processing, postgres) with liveness/readiness probes, ConfigMap/Secret separation, resource requests+limits, and runtime images pulled from ghcr.io/xstreamrollz/xstreamroll-{api,app,processing}.

Files added

  • k8s/00-namespace.yaml — Namespace + ResourceQuota
  • k8s/10-postgres.yaml — StatefulSet, headless Service, PVC, Secret template, init-script ConfigMap mount
  • k8s/20-api.yaml — Deployment, Service, ConfigMap, Secret template, probes
  • k8s/30-app.yaml — Deployment, Service, ConfigMap, probes
  • k8s/40-processing.yaml — Deployment, Service, ConfigMap, probes
  • k8s/60-ingress.yaml — Ingress routing rules
  • k8s/kustomization.yaml — Kustomize entrypoint with disableNameSuffixHash for stable ConfigMap names
  • k8s/README.md — Deploy + secret-substitution + verification commands

Files modified

  • api/src/health/health.controller.ts — new GET /health/livez (DB-free liveness probe)
  • xstreamroll-processing/src/metrics.ts — new /livez and /healthz routes
  • xstreamroll-processing/src/worker.ts — metrics server wired into startup + GracefulShutdown
  • xstreamroll-processing/__tests__/metrics.test.ts — 3 new tests for the health endpoints

Files created

  • app/src/app/api/health/route.ts — Next.js /api/health route handler

Acceptance criteria coverage

  • ✅ Deployments reference published Docker images (imagePullPolicy: Always on the GHCR-published images)
  • ✅ Health-check endpoints implemented and gated correctly (/livez for liveness → restart-free, /health or /healthz for readiness → traffic-aware)
  • ✅ ConfigMaps hold non-sensitive values (NODE_ENV, CORS_ORIGIN, PORT, POLL_INTERVAL_MS, etc.); Secrets hold sensitive values only (POSTGRES_PASSWORD, JWT_SECRET, STREAM_API_KEY, DATABASE_URL)
  • ✅ Resource requests + limits defined per container
  • ✅ Database credentials not hardcoded — sourced via secretKeyRef, only CHANGEME-* placeholders committed

How to verify locally

(cd api && npx tsc --noEmit) && \
(cd app && npx tsc --noEmit) && \
(cd xstreamroll-processing && npx tsc --noEmit && npm test)

Notes for reviewers

  • k8s/10-postgres.yaml and k8s/20-api.yaml ship secret templates with CHANGEME-* placeholders. Real credentials must be substituted per environment using kubectl create secret generic … --dry-run=client -o yaml | kubectl apply -f - (commands documented in k8s/README.md).
  • app/Dockerfile and xstreamroll-processing/Dockerfile declare non-root users (appuser/appgroup); k8s/30-app.yaml and k8s/40-processing.yaml match with runAsUser: 1000.
  • api/Dockerfile does not yet drop privileges, so k8s/20-api.yaml carries runAsNonRoot: false with an inline comment — flagged as follow-up hardening.

Closes #217

…stgres

Adds a new `k8s/` directory containing deployable manifests for every
runtime component of the platform:

- Namespace + ResourceQuota (`00-namespace.yaml`)
- Postgres StatefulSet with PVC and a ConfigMap-loaded init script
  from `database/schema.sql` (`10-postgres.yaml`)
- API Deployment, Service, ConfigMap and Secret template
  (`20-api.yaml`)
- Next.js App Deployment, Service and ConfigMap (`30-app.yaml`)
- Stream-processing worker Deployment, Service and ConfigMap
  (`40-processing.yaml`)
- Ingress routing external traffic to app + api (`60-ingress.yaml`)
- Kustomize entrypoint (`kustomization.yaml`) and a deployment README
  (`README.md`).

To support kubelet liveness/readiness probes the API gains a /livez
route that does not touch the database (liveness must never trigger a
restart loop on a transient DB outage). The processing worker exposes
/livez (always 200) and /healthz (503 once shutdown begins) on the
existing metrics server, and that server is now wired into the worker
startup and GracefulShutdown so the listening socket is closed
promptly on SIGTERM. The Next.js app gains a lightweight /api/health
route that bypasses the project middleware.

Probes, resource requests/limits, and ConfigMap vs Secret separation
all map to issue XStreamRollz#217's acceptance criteria.

Closes XStreamRollz#217

@Xhristin3 Xhristin3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big +1 from me. Decoupling liveness (/livez) from readiness (/healthz) is exactly right — prevents restart loops on transient DB blips. GracefulShutdown drain + 503 in healthz is nice. README walkthrough is helpful. README clearly documents the CHANGEME-* secrets — please remember to replace them before any non-dev apply 🚢

@Xhristin3 Xhristin3 merged commit 5f1bd74 into XStreamRollz:main Jun 17, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

infra: Add Kubernetes manifests for deployment

2 participants