<@ULVA73B9P> What's the best way to dispatch flow ...
# ask-marvin
r
@Marvin What's the best way to dispatch flow runs across multiple kubernetes pods?
m
thought for 550.1 seconds
Great question. In Prefect 3.x, the best way to ensure each flow run executes in its own Kubernetes pod is to use a Kubernetes work pool with one or more workers polling it. Each flow run becomes a Kubernetes Job/Pod launched by the worker, giving you clean isolation and native K8s scheduling. Here’s a concise, battle-tested setup: 1) Create a Kubernetes work pool - One pool per cluster is a common pattern.
Copy code
prefect work-pool create "k8s-pool" --type kubernetes
Optionally cap total concurrent flow runs at the pool:
Copy code
prefect work-pool set-concurrency-limit "k8s-pool" 50
2) Customize the base job template (resources, SA, namespace, env, node selection) - Export the default template, edit, then apply:
Copy code
prefect work-pool get-default-base-job-template --type kubernetes --file base-job-template.json
# Edit containers[].resources, serviceAccountName, namespace, env, tolerations, nodeSelector, etc.
prefect work-pool update "k8s-pool" --base-job-template base-job-template.json
Tip: Keep the template generic, then override per-deployment with job_variables when needed. 3) Create work queues to shard traffic and set queue-level caps - Use queues per priority, team, or region. Workers can subscribe to one or more queues.
Copy code
prefect work-queue create high-priority --pool k8s-pool --limit 10 --priority 1
prefect work-queue create default        --pool k8s-pool
4) Run workers in-cluster (recommended) - Deploy a lightweight Prefect worker Deployment in your K8s cluster with RBAC permissions to create Jobs/Pods. Example container command:
Copy code
prefect worker start --pool k8s-pool --work-queue high-priority --work-queue default
Notes: - Make sure the image includes kubernetes extras (e.g., install
prefect[kubernetes]
) and your flow’s dependencies. - Scale the worker Deployment replicas for resiliency/throughput of job submissions. Flow run concurrency is governed by pool/queue limits and cluster capacity, not worker count. 5) Deploy flows to the pool/queue and set per-run resources - From your project root:
Copy code
prefect deploy
# Select your flow entrypoint, choose work pool "k8s-pool", and optionally a work queue
- To pin resources per deployment, pass job_variables (they map onto the base job template variables). This is great for sizing memory/CPU or changing images by deployment. 6) Control parallelism and protect shared systems - Work pool cap: caps total concurrent flow runs from this pool. - Work queue cap: caps concurrent runs from that queue (great for priorities).
Copy code
prefect work-queue set-concurrency-limit --pool k8s-pool high-priority 10
- Tag-based task concurrency: throttle specific operations across all runs.
Copy code
prefect concurrency-limit create my-shared-system 5
Then tag relevant tasks/flows with
my-shared-system
. How this dispatches across multiple pods - Each scheduled flow run is picked up by a worker and executed as a new K8s Job/Pod using your base job template + job_variables. - To shard across multiple pods/paths, create multiple queues and point different deployments (or workers) at them. You can also create multiple pools (e.g., one per cluster) and run a worker set in each cluster. Best practices - Keep the worker in-cluster so it talks directly to the API server and can create Jobs quickly. - Use a custom image that includes your code +
prefect[kubernetes]
for faster cold starts. - Keep the base job template close to K8s best practices: define resource requests/limits, serviceAccountName, imagePullSecrets, tolerations/nodeSelector if needed, and labels/annotations for observability. - Use pool/queue concurrency caps to prevent overload; use tag concurrency limits to protect external systems (DBs, APIs). - If you need subflows in separate pods, call other deployments (Run Deployment) instead of regular subflows, which execute in the same pod by default. Docs and references
- Kubernetes on Prefect 3.x: How to: Kubernetes - Work pools and workers overview: Concepts: Work Pools and Workers - Blog background: Work Pools and Workers If you share a bit more about your setup (Cloud or self-hosted, cluster details, desired concurrency, and whether you want a sample worker Deployment YAML), I can tailor a minimal manifest and a base job template snippet for your use case.
r
@Marvin Is it possible to run kubernetes jobs instead?
m
thought for 103.1 seconds
Short answer: yes. Two common meanings here: 1) Run each flow run as a Kubernetes Job - That’s exactly what Prefect’s Kubernetes work pool/worker already does. Each flow run is submitted as a Kubernetes Job/Pod using your pool’s base job template. If you’re using a Kubernetes work pool, you’re already running Jobs under the hood. - Docs: How to: Kubernetes, Concepts: Work Pools and Workers 2) Launch arbitrary Kubernetes Jobs from a Prefect flow (i.e., a container that doesn’t run Prefect) - Use the prefect-kubernetes collection. You can submit a Job manifest directly from a flow:
Copy code
from prefect import flow
from prefect_kubernetes.credentials import KubernetesCredentials
from <http://prefect_kubernetes.jobs|prefect_kubernetes.jobs> import create_namespaced_job, read_namespaced_job_status

@flow
def launch_k8s_job():
    creds = KubernetesCredentials(in_cluster=True)  # or load_kube_config=True for out-of-cluster

    manifest = {
        "apiVersion": "batch/v1",
        "kind": "Job",
        "metadata": {"name": "hello-job"},
        "spec": {
            "template": {
                "spec": {
                    "restartPolicy": "Never",
                    "containers": [
                        {
                            "name": "hello",
                            "image": "busybox",
                            "command": ["sh", "-c", "echo hello && sleep 2 && echo done"]
                        }
                    ],
                }
            }
        }
    }

    create_namespaced_job(
        kubernetes_credentials=creds,
        new_job=manifest,
        namespace="default",
    )

    # Optional: poll until completion
    # status = read_namespaced_job_status(kubernetes_credentials=creds, name="hello-job", namespace="default")
    # ...check status.status.succeeded/failed and loop...

if __name__ == "__main__":
    launch_k8s_job()
Quick check: Which of these are you after? - “I want my Prefect flow runs to be Jobs” (already the case with a Kubernetes work pool) - “I want to trigger my own Kubernetes Jobs from a Prefect flow” If you share which path you want, I can tailor an example (including a base job template or a worker Deployment YAML) for your cluster.