In the fluid monorepo this chart lives under code/charts/fluid-controlplane/; standalone Git (fluid-pub/chart-controlplane) uses the same layout at the repository root.
Release (standalone repo) — helm lint runs on PRs and main / develop; pushing a semver tag without v runs helm push … oci://ghcr.io/<GitHub-owner>/fluid-controlplane when the tag equals version in Chart.yaml.
Install / pull from GHCR — Helm OCI on GitHub stores the chart under a path that repeats the chart name: (see the package page fluid-controlplane/fluid-controlplane). Use --version with the full OCI prefix, for example:
helm pull oci://ghcr.io/fluid-pub/fluid-controlplane/fluid-controlplane --version 0.4.0
or the equivalent tag form oci://ghcr.io/fluid-pub/fluid-controlplane/fluid-controlplane:0.4.0. The shorter reference oci://ghcr.io/fluid-pub/fluid-controlplane (without the second fluid-controlplane) does not resolve with helm pull / helm install against this registry layout.
Application-only chart: no bundled PostgreSQL and no Secret management in the chart.
Provide credentials via pre-existing Kubernetes Secret(s), referenced in envFromSecrets.
By default, traffic exposure uses Gateway API (gatewayApi.enabled: true, HTTPRoute).
When replicaCount is greater than 1 and gatewayApi.enabled is true, the chart creates a dedicated HTTPRoute for /v1/agents/websocket and a BackendTrafficPolicy (Envoy Gateway) with consistent hash on the authorization request header.
Execution agents must send Authorization: Bearer <connection_token> on every WebSocket upgrade (in addition to organization_uuid and token in the query string for Phoenix auth). The same Bearer routes to the same control plane pod while that pod is healthy; after a pod failure, the agent reconnects and may land on another replica.
Opt out: gatewayApi.agentAffinity.enabled: false. Force on with a single replica: gatewayApi.agentAffinity.enabled: true.
Verify after deploy:
kubectl get httproute,backendtrafficpolicy -n <namespace>Do not rely on Service sessionAffinity: ClientIP alone for agent tunnels (unreliable behind proxies).
When replicaCount is greater than 1 and gatewayApi.enabled is true, the chart attaches a BackendTrafficPolicy to the main HTTPRoute (path: /). Envoy Gateway uses consistent hash on a routing-only cookie (default name fluid_controlplane_liveview, configurable under gatewayApi.liveViewAffinity).
Envoy sends Set-Cookie on the first browser response when the cookie is absent; the browser attaches it on later requests, including /live/websocket upgrades, so HTTP and Phoenix LiveView land on the same control plane pod while that pod stays healthy.
By default the chart sets cookie attribute Path=/ (gatewayApi.liveViewAffinity.cookiePath) so the browser keeps a single affinity cookie for the whole app. Without it, Envoy Gateway may emit one cookie per request path (e.g. /dashboard vs /live), which breaks stickiness across HTML and the LiveView WebSocket (envoyproxy/gateway#8580). Confirm your Envoy Gateway version honours cookie.attributes.Path in BackendTrafficPolicy.
This cookie is not the Phoenix session cookie (COOKIE_SIGNING_SALT / _controlplane_key are unrelated).
Opt out: gatewayApi.liveViewAffinity.enabled: false. Force on with a single replica: gatewayApi.liveViewAffinity.enabled: true.
Verify after deploy (same resource check as agents):
kubectl get httproute,backendtrafficpolicy -n <namespace>See also Envoy Gateway — consistent hash cookie.
Install helm-unittest and run from this directory:
helm plugin install https://github.com/helm-unittest/helm-unittest --version v0.6.3 --verify=false
helm unittest .See tests/README.md for suite coverage. CI runs helm lint and helm unittest . on pull requests.
| Helm hook | Container command |
|---|---|
pre-install |
/app/bin/setup (ecto.create + migrate + seeds) |
pre-upgrade |
/app/bin/migrate (migrations only) |
Use the same image tag as the Deployment (values.yaml → image.repository / image.tag).
Create one or more Secrets in the release namespace, then list them in envFromSecrets.
Minimum keys consumed by runtime.exs:
DATABASE_URLSECRET_KEY_BASECOOKIE_SIGNING_SALTCONTROLPLANE_VAULT_SECRETENROLLMENT_TOKEN_FINGERPRINT_SECRETPHX_HOSTPORT(typically4000)
Optional keys depend on enabled features (LLM, RAG, enrollment, etc.) — see code/controlplane/config/runtime.exs.
Defaults:
- Liveness —
GET /health/live(no database check). - Readiness —
GET /health/ready(checks database connectivity).
Override paths under livenessProbe / readinessProbe in values if needed.