Skip to content

Deployment: Kubernetes Helm chart + admin docs - #1712

Draft
Mtze wants to merge 9 commits into
mainfrom
feature/helm-deployment
Draft

Deployment: Kubernetes Helm chart + admin docs#1712
Mtze wants to merge 9 commits into
mainfrom
feature/helm-deployment

Conversation

@Mtze

@Mtze Mtze commented Jun 22, 2026

Copy link
Copy Markdown
Member

✨ What is the change?

Adds a reusable Helm chart (charts/prompt) to deploy PROMPT 2.0 on Kubernetes, plus a comprehensive admin guide under docs/admin/kubernetes/.

Chart structure:

  • Umbrella + one subchart per phase, sharing a prompt-common library chart (Deployment/Service/HTTPRoute + helpers) so the ~14 near-identical components stay DRY.
  • infrastructure subchart: CloudNativePG Cluster (one logical database per phase, managed roles, PgBouncer pooler, optional WAL + scheduled backups), SeaweedFS object storage, Gateway API + Envoy Gateway with per-listener cert-manager TLS, and optional in-cluster Keycloak (operator + realm import).
  • Shared app ConfigMap + Secret (envFrom) and per-phase DB Secrets mirror the existing .env contract, so no application code changes are needed.

Every stateful dependency is pluggable between an in-cluster bundle (self-contained installs) and an external managed service (production): postgresql.mode, objectStorage.mode, keycloak.mode.

📌 Reason for the change

Enables institutions running Kubernetes to deploy PROMPT alongside the existing Docker Compose path. Defaults favour TUM AET but the chart is built to be reusable by other chairs.

Design hardening folded in from review: Helm lookup so DB passwords survive upgrades, roles declared on the CNPG cluster, connection pooling, per-listener TLS (no multi-SAN blast radius), Envoy rate-limit gated behind a toggle, S3 CORS + Host-header preservation for presigned URLs, DB-wait init containers.

🧪 How to Test

  1. helm lint charts/prompt (passes).
  2. helm template prompt charts/prompt renders cleanly; verify counts (15 Deployments, 6 Databases, 3 SeaweedFS StatefulSets, per-listener Gateway).
  3. Render mode combinations: --set global.postgresql.mode=external, --set global.objectStorage.mode=external, --set global.keycloak.mode=in-cluster, and --set <phase>.enabled=false.
  4. cd docs && yarn build succeeds with the new admin pages.
  5. On-cluster (not yet performed): install the prerequisite operators on kind/minikube, helm install, then verify TLS issuance, login, and a presigned upload (see docs/admin/kubernetes).

✅ PR Checklist

  • Tested locally (helm lint / helm template / docs yarn build)
  • Code is clean, readable, and documented
  • Tests added or updated (if needed)
  • Screenshots attached for UI changes (if any) — n/a
  • Documentation updated (admin Kubernetes guide)

Draft: validated statically only. A runtime apply against a cluster with the prerequisite operators (CloudNativePG, Envoy Gateway, cert-manager, Keycloak) is still pending.

🤖 Generated with Claude Code

Add a reusable Helm chart (charts/prompt) to deploy PROMPT on Kubernetes:
umbrella + one subchart per phase sharing a prompt-common library chart, and
an infrastructure subchart for CloudNativePG, SeaweedFS, Gateway API + cert-manager
TLS, and optional in-cluster Keycloak. Every stateful dependency is pluggable
between in-cluster and external. Adds a comprehensive admin guide under docs/admin/kubernetes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7d290027-bf60-4e79-b48f-d594619f8341

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/helm-deployment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

A review of the Helm chart found that a `helm install` could not reach a
running state, plus a cluster of credential, data-retention and parity
defects. Nothing in CI rendered the chart, so none of it surfaced.

Install blockers:

- Backends set `runAsNonRoot: true`, but the Go images build on distroless
  static (the root variant, no `USER`), so the kubelet refused every one of
  them. The chart now supplies UID/GID 65532 via `global.podSecurity`.
- Frontends dropped all capabilities while running stock `nginx` as root on
  port 80, which crash-loops. Capabilities are now dropped for backends only;
  the chart targets the `baseline` Pod Security Standard.
- `infrastructure.realmConfigMap` was only a boolean gate: the ConfigMap was
  never read, so the rendered `KeycloakRealmImport` shipped an empty realm and
  every login would fail with `invalid_client`. Its spec takes a full inline
  realm representation, which cannot come from values, so the resource is gone
  and the procedure is documented instead.
- `S3_SECRET_KEY` defaulted to empty while `S3_ENDPOINT` pointed at SeaweedFS,
  which fatals core-server. It is now required, as is `S3_ACCESS_KEY` in
  external mode.
- The default `template` phase pulled an image no workflow builds. Replaced
  with the `example` phase, which Compose does serve.

Credentials and state:

- External PostgreSQL fell through to `randAlphaNum` when no password was set,
  rewriting the secret on every render without restarting pods, and ignored
  the configured user. Host, user and password are now required, and `lookup`
  runs only in in-cluster mode.
- `helm uninstall` deleted the CloudNativePG cluster and with it the Postgres
  PVCs, which the docs promised persist. The cluster and role secrets now
  carry `helm.sh/resource-policy: keep`.
- In-cluster Keycloak with external PostgreSQL referenced a secret that is
  never created; it now fails at render time with an explanation.
- `wait-for-db` ran `nc -z` against the pooler, which succeeds long before the
  database and role exist, so migrations ran against a missing database. It
  now authenticates with `psql`.
- Config and secret changes never reached running pods. Pod templates carry
  `checksum/appconfig`, `checksum/appsecrets` and, for backends,
  `checksum/db`; the S3 gateway carries the secret checksum.
- `SSL_MODE` was unsettable, so external managed PostgreSQL was dialled with
  `sslmode=disable`. Added `global.postgresql.sslMode`, defaulting to
  `require` off-cluster.

Parity and hardening:

- S3 CORS was gated on the rate-limiting toggle, so disabling the rate limit
  silently broke every browser upload. Split into `gateway.provider` and
  `gateway.rateLimiting.enabled`, and dropped the never-rendered `burst`.
- Added a NetworkPolicy for the unauthenticated SeaweedFS master, volume and
  filer, which were reachable from every namespace.
- `INTRO_COURSE_HOST` and `DEVOPS_CHALLENGE_HOST` pointed at the apex host
  although those remotes come from separate deployments; they are now
  configurable and empty by default.

CI now lints the chart, renders every mode combination through kubeconform,
and runs `charts/prompt/ci/assert-render.sh`, which asserts the properties
above including the negative cases. This is render-time only: it cannot cover
what the kubelet decides at container start, so a manual install check on a
real cluster is still required before the PR ships.

The pre-commit `check-yaml` hook now skips `charts/*/templates/`: Go templates
are not YAML, so any chart template edit failed the hook.
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.

2 participants