Kurt Sys (Vintecc)
12/15/2025, 11:26 AM- |
helm repo add prefect <https://prefecthq.github.io/prefect-helm/>
helm repo update
kubectl create namespace prefect
helm install prefect-server prefect/prefect-server -n prefect -f manifests-dependencies/values-prefect.yaml
Now, this is an issues, since I'm using traefik for routing, so localhost:4200 does not work. It should connect to prefect.localhost:8080/api . I suppose I can configure this in values-prefect.yaml?
nameOverride: "prefect-server"
fullnameOverride: "prefect-server"
namespaceOverride: "prefect"
postgresql:
auth:
database: prefect-server
username: prefect-default-user
password: prefect-default-password
serviceAccount:
name: "prefect-server"Marvin
12/15/2025, 11:26 AMKurt Sys (Vintecc)
12/15/2025, 11:28 AMMarvin
12/15/2025, 11:28 AMMarvin
12/15/2025, 11:31 AMkubectl apply the output
- Hand-written raw manifests: only if you truly need full object-level control that the chart cannot express
What to use where
- Workers: use the official prefect-worker chart; point it at your work pool and server URL
- Server: use the prefect-server chart if you want to run Prefect Server in-cluster. Note: the server chart uses Postgres; SQLite is for local dev and not supported in the Helm chart
Minimal worker values example for your self-hosted Server
(adjust the API URL and work pool name)
worker:
apiConfig: selfHostedServer
selfHostedServerApiConfig:
apiUrl: http://<your-server-host>:4200/api
config:
workPool: <your-k8s-work-pool-name>
Install/upgrade with Helm (keep using your values-prefect.yaml)
helm repo add prefect <https://prefecthq.github.io/prefect-helm>
helm repo update
helm upgrade --install prefect-worker prefect/prefect-worker \
-n prefect -f values-prefect.yaml
If you need raw manifests but still want chart features (render-only)
helm template prefect-worker prefect/prefect-worker \
-n prefect -f values-prefect.yaml > rendered.yaml
kubectl apply -n prefect -f rendered.yaml
Optional: server chart basic values (uses Postgres)
postgresql:
enabled: true
auth:
password: "change-me"
backgroundServices:
runAsSeparateDeployment: true
redis:
enabled: true
Install:
helm upgrade --install prefect-server prefect/prefect-server \
-n prefect -f server-values.yaml
Tip: you don’t need raw manifests to control the flow-run Pods. Use the Kubernetes work pool’s “base job template” to set things like resources, node selectors, tolerations, volumes, sidecars, etc.; the worker chart just deploys the worker Deployment.
Links
- Prefect Helm charts (prefect-worker, prefect-server)
- Kubernetes how-to guide
- Work pools concept
If you share your current values-prefect.yaml and your Server URL (in/out of cluster), I’m happy to sanity-check it and suggest the exact keys to set.Marvin
12/15/2025, 11:31 AMvalues-prefect.yaml like this:
nameOverride: "prefect-server"
fullnameOverride: "prefect-server"
namespaceOverride: "prefect"
# Expose Prefect through Traefik
ingress:
enabled: true
className: "traefik" # adjust if your IngressClass is named differently
host:
hostname: "prefect.localhost"
path: "/"
pathType: "Prefix"
annotations:
# If your Traefik entrypoint for HTTP is named "web" (default)
<http://traefik.ingress.kubernetes.io/router.entrypoints|traefik.ingress.kubernetes.io/router.entrypoints>: "web"
# If you really terminate on :8080, ensure Traefik is listening there or your NodePort maps to 8080
service:
type: ClusterIP
port: 4200
targetPort: 4200
portName: "server-svc-port"
# Tell the UI which URL to use for API calls (critical)
server:
uiConfig:
# Use your external URL (Traefik) with /api
prefectUiApiUrl: "<http://prefect.localhost:8080/api>"
postgresql:
auth:
database: prefect-server
username: prefect-default-user
password: prefect-default-password
serviceAccount:
name: "prefect-server"
Notes:
- If Traefik serves HTTP on :80 (common), change prefectUiApiUrl to <http://prefect.localhost/api> (no port) and drop the 8080. If you’re actually terminating on :8080 locally, keep it as you proposed.
- If you enable TLS on Traefik, change to <https://prefect.localhost/api> and add the appropriate TLS config/annotations to the ingress.
- If any workers/clients run outside the cluster and need to reach the API through Traefik, set PREFECT_API_URL in those environments to <http://prefect.localhost:8080/api>. In-cluster workers can use the cluster DNS, e.g. <http://prefect-server.prefect.svc.cluster.local:4200/api>.
References:
- prefect-helm: prefect-server chart
- values.yaml
- chart README (server)
Quick check:
- Is your Traefik IngressClass actually named traefik?
- Do you really want to expose on :8080 rather than :80? If not, I can adjust the snippet accordingly.Kurt Sys (Vintecc)
12/15/2025, 11:55 AMvalues-prefect.yaml, I can't have variable auth here, right? So how would that work properly? Meaning, how to set the auth of the prefect db the same as configured in apiVersion: <http://postgresql.cnpg.io/v1|postgresql.cnpg.io/v1>Marvin
12/15/2025, 11:55 AMMarvin
12/15/2025, 11:57 AMconnection-string with the full SQLAlchemy URL
- Point the chart to that Secret
Two ways to supply the Secret:
Option A — Let the Prefect chart create the Secret from fields
(useful for static values or when you can template them in your values file)
postgresql:
enabled: false
secret:
create: true
# name: "" # optional; if omitted, chart will name it for you
username: "prefect"
password: "your-password"
host: "my-cnpg-rw.default.svc.cluster.local"
port: "5432"
database: "prefect"
The chart will generate and store:
connection-string: <postgresql+asyncpg://prefect:your-password@my-cnpg-rw.default.svc.cluster.local:5432/prefect>
Option B — Use the Secret created by CNPG (recommended)
CNPG usually creates a Secret with individual fields (host, port, user, password, dbname) rather than a single connection string. Prefect expects a single connection-string key. You have two sub-options:
- Create a small “wrapper” Secret from the CNPG Secret values:
# Example: construct Secret once (or via your GitOps pipeline)
kubectl create secret generic prefect-db-connection \
-n prefect \
--from-literal=connection-string="postgresql+asyncpg://<user>:<pass>@<host>:<port>/<dbname>"
Then in your values:
postgresql:
enabled: false
secret:
create: false
name: "prefect-db-connection"
- Or template a Helm helper to build the string from the CNPG secret’s keys (if you control the Helm release that also knows the CNPG Secret name). In practice, most teams prefer the wrapper Secret for clarity.
A few tips:
- Don’t put host: host:port in the values; host and port are separate fields if you use secret.create: true.
- If you want TLS to Postgres, include params in the connection string (e.g., ?ssl=verify-ca) and mount your CA at /home/prefect/.postgresql/root.crt via `server.extraVolumes`/`server.extraVolumeMounts`.
- Keep postgresql.enabled: false whenever you’re using CNPG.
If you can share your CNPG Secret name and its keys, I can show the exact kubectl command to generate the Prefect-compatible wrapper Secret, or convert it in-place with a short script.Kurt Sys (Vintecc)
12/15/2025, 2:13 PMprefect-db-connection look like. That's just a secret type, I suppose, what which data does it need?Marvin
12/15/2025, 2:13 PMMarvin
12/15/2025, 2:13 PMconnection-string. The value is the full SQLAlchemy URL Prefect needs.
Format of the connection string:
postgresql+asyncpg://<user>:<password>@<host>:<port>/<database>
YAML manifest (using stringData for convenience):
apiVersion: v1
kind: Secret
metadata:
name: prefect-db-connection
namespace: prefect
type: Opaque
stringData:
connection-string: <postgresql+asyncpg://prefect:your-password@my-cnpg-rw.default.svc.cluster.local:5432/prefect>
Or create it via kubectl (auto base64-encodes):
kubectl create secret generic prefect-db-connection \
-n prefect \
--from-literal=connection-string="<postgresql+asyncpg://prefect:your-password@my-cnpg-rw.default.svc.cluster.local:5432/prefect>"
Then in your Helm values:
postgresql:
enabled: false
secret:
create: false
name: "prefect-db-connection"
If you want to build it from a CNPG secret’s fields:
HOST=$(kubectl get secret my-cnpg-app -n <ns> -o jsonpath='{.data.host}' | base64 -d)
PORT=$(kubectl get secret my-cnpg-app -n <ns> -o jsonpath='{.data.port}' | base64 -d)
USER=$(kubectl get secret my-cnpg-app -n <ns> -o jsonpath='{.data.user}' | base64 -d)
PASS=$(kubectl get secret my-cnpg-app -n <ns> -o jsonpath='{.data.password}' | base64 -d)
DB=$(kubectl get secret my-cnpg-app -n <ns> -o jsonpath='{.data.dbname}' | base64 -d)
kubectl create secret generic prefect-db-connection -n prefect \
--from-literal=connection-string="postgresql+asyncpg://${USER}:${PASS}@${HOST}:${PORT}/${DB}"
Notes:
- Only the connection-string key is required; no separate `user`/`password` keys.
- If your password has special characters, URL‑encode it in the connection string.
- For TLS, append parameters like ?ssl=verify-ca and mount your CA at /home/prefect/.postgresql/root.crt via `server.extraVolumes`/`server.extraVolumeMounts`.
Chart refs:
- prefect-server chart
- values.yamlKurt Sys (Vintecc)
12/15/2025, 2:14 PMMarvin
12/15/2025, 2:15 PMMarvin
12/15/2025, 2:15 PMPREFECT_API_DATABASE_CONNECTION_URL from a Secret key named connection-string
- There are no separate host/user/password/dbname keys consumed by the chart
From the chart’s Deployment:
- name: PREFECT_API_DATABASE_CONNECTION_URL
valueFrom:
secretKeyRef:
name: <your-secret-name>
key: connection-string
So your options are:
- Provide that one Secret with data.connection-string (or stringData.connection-string), e.g.
postgresql:
enabled: false
secret:
create: false
name: prefect-db-connection
and the Secret:
apiVersion: v1
kind: Secret
metadata:
name: prefect-db-connection
namespace: prefect
type: Opaque
stringData:
connection-string: <postgresql+asyncpg://user:pass@host:5432/dbname>
- Or let the chart build that connection string for you if you can specify the fields in values:
postgresql:
enabled: false
secret:
create: true
username: "user"
password: "pass"
host: "host.example.svc.cluster.local"
port: "5432"
database: "dbname"
If your CNPG secret exposes separate keys (host, port, user, password, dbname), you’ll need to either:
- Create a wrapper Secret that assembles those into one connection-string, or
- Template a Helm helper in your GitOps to generate connection-string from the CNPG secret at deploy time
Happy to help craft the wrapper Secret from your CNPG secret if you share its name/namespace.