P2: Reference deployment manifests — k8s + prod Compose (#179) - #196
P2: Reference deployment manifests — k8s + prod Compose (#179)#196dkijania wants to merge 2 commits into
Conversation
There were no production deployment artifacts — operators had npm/Docker/Compose for dev but no opinionated manifest with probes, resource limits, and a hardened runtime. Add deploy/: - kubernetes.yaml — Deployment + Service + HPA (+ placeholder Secret) with liveness (/healthcheck) and readiness (/readiness) probes, resource requests/limits, a 2→6 CPU autoscaler, Prometheus scrape annotations for /metrics, a hardened pod securityContext (non-root, readOnlyRootFilesystem, no privilege escalation, all caps dropped, RuntimeDefault seccomp), and a 30s termination grace period matching the graceful-shutdown drain. - docker-compose.prod.yml — the published image against an external read-only Postgres, with CPU/memory caps. - README.md — usage and how this maps to the security deployment contract. Linked from the root README. References the probe/metrics endpoints delivered by the sibling P1 PRs. Closes #179. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QSuak9smCHbp4N17xjjLF6
|
Really glad to see opinionated production manifests land — the hardened pod securityContext, HPA, and Secret-based 1. CORS will silently block the mina-explorer once #184 merges. The Explorer is a cross-origin browser app ( - name: CORS_ORIGIN
# The mina-explorer (and any browser UI) is cross-origin and CANNOT reach this
# API unless its origin is allowlisted here. Comma-separate multiple origins.
# NB: the server currently defaults to '*' when unset; #184 changes that to deny.
value: 'https://explorer.example.com'(same note applies to 2. The readiness probe targets Everything else looks solid to me. |
The readiness probe targets /readiness, which only exists from 1.0.0, but the manifests pulled :latest — today that resolves to 0.0.6. Applied as-is the probe would 404 forever, no pod would reach Ready, and the Service would be left with zero endpoints: a total outage from a manifest offered as the copy-paste reference. Both manifests now pin 1.0.0 and state the requirement up front. The /metrics scrape annotations had the same dependency. CORS_ORIGIN shipped commented out, described as "leave unset for same-origin only". Unset blocks every cross-origin browser client — the mina-explorer included — and does so silently, with nothing in the server logs. Since the primary consumers are browsers, it now ships set, with the trade-off spelled out. deploy/README.md repeated the root README's claim that pointing PG_CONN at replicas buys throughput. It buys failover: postgres.js scopes hostIndex per Connection, so every pooled connection starts at host[0] and only advances on failure. Real read scaling needs a balancer in front of Postgres. Also sets TRUST_PROXY=1 in the k8s manifest (an ingress adds a hop, and the default of 0 would bucket every client together) and corrects terminationGracePeriodSeconds from "matches" to "exceeds" SHUTDOWN_TIMEOUT_MS, which is the property that actually matters. Verified with kubectl apply --dry-run=client and docker compose config. Addresses review feedback on #196. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks @SanabriaRusso — both fixed in The CORS. Agreed and done — it now ships set rather than commented out, since the primary consumers are cross-origin browsers. I used Three more found while in here:
Verified with One thing to confirm: if #191 adopts the |
What & why
Part of the production-readiness epic (#163). Closes #179.
There were no production deployment artifacts — operators had npm/Docker/Compose for dev but no opinionated manifest with probes, resource limits, and a hardened runtime.
Adds
deploy/kubernetes.yaml—Deployment+Service+HorizontalPodAutoscaler(+ placeholderSecret) with production defaults:/healthcheck, readiness on/readinessreadOnlyRootFilesystem, no privilege escalation, all caps dropped,RuntimeDefaultseccomp)/metricsterminationGracePeriodSeconds: 30matching the graceful-shutdown draindocker-compose.prod.yml— the published image against an external read-only Postgres, with CPU/memory caps.README.md— usage + how it maps to the security deployment contract.Linked from the root README. References the probe/metrics endpoints delivered by the sibling P1 PRs (#169/#173).
Testing
Docs/manifests only.
prettier --debug-check .clean; YAML structure validated. No application code changed.🤖 Generated with Claude Code