<@ULVA73B9P> When deploying Prefect OSS to Kuberne...
# ask-marvin
r
@Marvin When deploying Prefect OSS to Kubernetes, is it possible to deploy the prefect ui and the prefect api in two separated services?
m
thought for 404.3 seconds
Short answer: yes. You can run the Prefect API and the Prefect UI as separate Kubernetes Services. Common patterns in Prefect 3.x OSS: - API-only service: Run Prefect Server with the UI disabled. - UI service: Serve the UI and point it at the API service URL. You can either - run a Prefect Server instance with the UI enabled and block its /api route at the Ingress, or - serve the UI’s static files with a generic web server (e.g., Nginx) and set the UI’s API URL. Key settings/env vars: - Disable UI on the API pods:
PREFECT_UI_ENABLED=false
(alias for server ui enabled) - Point the UI at your API service:
PREFECT_UI_API_URL=<https://your-api.example.com/api>
- If serving UI at a sub-path:
PREFECT_UI_SERVE_BASE=/
- If the UI and API are on different origins, CORS is typically already permissive: - API CORS defaults to
*
, but can be tightened via
PREFECT_SERVER_API_CORS_ALLOWED_ORIGINS
CLI flags (verified): - API only:
prefect server start --no-ui
- Full server (web + services):
prefect server start
- Only the webserver without background services:
prefect server start --no-services
You can confirm with:
Copy code
prefect server start --help
Kubernetes sketch - API Deployment/Service - Container command:
prefect server start --no-ui
- Optionally keep services on one replica (and use
--no-services
on additional replicas) if you run multiple API instances. - Expose as Service (ClusterIP) and Ingress at
/api
(or your desired host/path). - UI Deployment/Service, option A (Prefect serves the UI) - Container command:
prefect server start --ui
- Env:
PREFECT_UI_API_URL=<https://your-api.example.com/api>
- Ingress: expose only
/
to this service and block/omit
/api
so all API calls go to the API Service. - UI Deployment/Service, option B (static web server) - Build a tiny image that serves the Prefect UI static assets. - Env in the UI container (if you use Prefect’s UI server):
PREFECT_UI_API_URL=<https://your-api.example.com/api>
- Ingress: expose
/
from this static UI service. Minimal env examples - API pods:
Copy code
- name: PREFECT_UI_ENABLED
  value: "false"
- UI pods:
Copy code
- name: PREFECT_UI_ENABLED
  value: "true"
- name: PREFECT_UI_API_URL
  value: "<https://prefect-api.example.com/api>"
Notes on the Helm chart - The official chart deploys a single Prefect Server by default. It does not ship a predefined “UI-only” vs “API-only” split, but you can: - Install two releases (one with UI disabled, one acting as UI), and route via Ingress as described; or - Use custom manifests to run separate Deployments/Services. Docs: - Server Helm guide: Prefect Server Helm docs - Settings reference: Prefect settings reference - Security/CORS: Security &amp; CORS Would you like a concrete example with Kubernetes manifests or Helm values for your setup (Ingress hostnames/paths, single or multiple replicas, etc.)? Are you using the official Helm chart or custom YAML?
🙌 1
r
Yes @Marvin I could use an example using the official helm chart
m
thought for 254.1 seconds
Awesome — here’s a concrete way to do it with the official Helm chart by installing two releases: one “API-only” and one “UI-serving” release, then routing with a single Ingress. Assumptions - Prefect 3.x OSS - You’re using the official chart: prefect-helm - You want a single host (e.g., prefect.example.com) with: - /api -> API service - / -> UI service (the UI will call /api on the same host) Step 1) Add the repo and create a namespace
Copy code
helm repo add prefect <https://prefecthq.github.io/prefect-helm>
helm repo update
kubectl create namespace prefect
Step 2) API-only release values (values-api.yaml) - Disables the UI on these pods - Exposes the API on port 4200 Note: Many chart versions expose env and args as env/extraArgs or similar keys. If your chart uses different keys (e.g., server.env, server.extraArgs), adjust accordingly. See the chart README for your version: prefect-helm repo.
Copy code
fullnameOverride: prefect-api
replicaCount: 2

env:
  - name: PREFECT_UI_ENABLED
    value: "false"
  - name: PREFECT_SERVER_API_HOST
    value: "0.0.0.0"
  - name: PREFECT_SERVER_API_PORT
    value: "4200"

# If supported by your chart version, keep the API-only process explicit
extraArgs:
  - server
  - start
  - --no-ui

service:
  type: ClusterIP
  port: 4200
Install:
Copy code
helm upgrade --install prefect-api prefect/prefect-server -n prefect -f values-api.yaml
Step 3) UI-serving release values (values-ui.yaml) - Serves the UI and points it at the API path that the Ingress will route to - Avoids running background services here to prevent duplicate schedulers/etc Option A (preferred): disable services with CLI flags (if extraArgs supported)
Copy code
fullnameOverride: prefect-ui
replicaCount: 1

env:
  - name: PREFECT_UI_ENABLED
    value: "true"
  - name: PREFECT_UI_API_URL
    value: "<https://prefect.example.com/api>"
  - name: PREFECT_SERVER_API_HOST
    value: "0.0.0.0"
  - name: PREFECT_SERVER_API_PORT
    value: "4200"

extraArgs:
  - server
  - start
  - --ui
  - --no-services

service:
  type: ClusterIP
  port: 4200
Option B (fallback if your chart doesn’t allow extraArgs): disable services via env vars
Copy code
fullnameOverride: prefect-ui
replicaCount: 1

env:
  - name: PREFECT_UI_ENABLED
    value: "true"
  - name: PREFECT_UI_API_URL
    value: "<https://prefect.example.com/api>"
  # Turn off background services on the UI pods
  - name: PREFECT_API_SERVICES_SCHEDULER_ENABLED
    value: "false"
  - name: PREFECT_API_SERVICES_LATE_RUNS_ENABLED
    value: "false"
  - name: PREFECT_API_SERVICES_REPOSSESSOR_ENABLED
    value: "false"
  - name: PREFECT_API_SERVICES_PAUSE_EXPIRATIONS_ENABLED
    value: "false"
  - name: PREFECT_API_SERVICES_TASK_RUN_RECORDER_ENABLED
    value: "false"
  - name: PREFECT_API_SERVICES_TRIGGERS_ENABLED
    value: "false"
  - name: PREFECT_API_SERVICES_EVENT_LOGGER_ENABLED
    value: "false"
  - name: PREFECT_API_SERVICES_EVENT_PERSISTER_ENABLED
    value: "false"
  - name: PREFECT_API_SERVICES_FOREMAN_ENABLED
    value: "false"

service:
  type: ClusterIP
  port: 4200
Install:
Copy code
helm upgrade --install prefect-ui prefect/prefect-server -n prefect -f values-ui.yaml
Step 4) Ingress that routes / to the UI release and /api to the API release - This keeps the UI and API separate at the Service level and makes sure all API requests go to the API service (the UI service won’t be used for /api) - Adjust host, TLS, and annotations for your environment ``` apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: prefect-ingress namespace: prefect annotations: kubernetes.io/ingress.class: nginx spec: rules: - host: prefect.example.com http: paths: - path: /api pathType: Prefix backend: service: name: prefect-api port: number: 4200 - path: /
pathType: Prefix backend: service: name: prefect-ui port: number: 4200 ``` Notes - CORS/CSRF: With a single host and path-based routing, you typically don’t need to change CORS. If you use separate hosts for UI and API, set CORS on the API (e.g.,
PREFECT_SERVER_API_CORS_ALLOWED_ORIGINS=<https://ui.example.com>
). See Security &amp; CORS docs. - If you need a single static UI without a Prefect server process, you can serve the UI assets with Nginx and still set
PREFECT_UI_API_URL
— but that’s outside the scope of the official server chart. - Settings reference: Prefect settings reference - Helm chart docs: Server Helm guide and prefect-helm repo If you share your chart version (and whether it exposes env vs extraEnv vs extraArgs), I can tailor the values.yaml to match your chart exactly and include TLS annotations for your ingress controller.