Orchestrating GPU-hungry ML Pipelines with Airflow and Kubernetes

ML pipelines have a split personality: they need the choreography of a classical conductor (data collection, preprocessing, training, evaluation), and the brute force of a rock band on tour (GPU-backed training, bursty loads, multi-tenant stages). Over the last two years the tooling on both sides has matured: Apache Airflow made a major leap toward ML-friendly workflows, and Kubernetes + NVIDIA tooling unlocked new ways to share and time-slice scarce GPU capacity. This article walks through the practical architecture and trade-offs when managing ML pipelines with Airflow running on Kubernetes—focusing on how Airflow 3 and modern GPU tooling change the calculus for multi-tenant ML workloads. (airflow.apache.org)

Why this is timely

Two shifts are especially relevant:

Combined, these let platform teams treat ML workloads more like elastic, orchestrated services instead of monolithic training jobs—but the new flexibility requires careful design.

The fundamental tension

Three forces collide in ML orchestration:

The result: naive designs either underutilize GPUs (wasting budget) or overload control plane components (causing flakiness). There are documented cases of Airflow 3 deployments hitting API server pressure and connection-pooling limits when concurrency grows—highlighting the need to design both orchestration and infra in tandem. (github.com)

A practical architecture pattern (conceptual)

Think of the cluster as a campus with specialized buildings:

Airflow on Kubernetes typically uses either the KubernetesExecutor or the KubernetesPodOperator. Both offload heavy compute into ephemeral Kubernetes pods rather than making the Airflow scheduler run work directly—this is central to keeping the control plane responsive. (airflow.apache.org)

Key placement controls are used to steer pods:

How modern GPU features change trade-offs

Two capabilities matter a lot:

Together, you get more flexible sharing (time-slicing) and stronger placement guarantees (taints/affinity). But the extra flexibility also requires awareness in orchestration—task sizing, retry budgets, and admission control are more important than ever.

Practical considerations and patterns

Below are operational patterns and the reasons behind them.

Example: a KubernetesPodOperator snippet (conceptual)

Below is a compact DAG task that runs a training job in a pod and requests one GPU (note: adapt images/registry and environment for your environment):

from airflow import DAG
from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
from datetime import datetime

with DAG("train_example", start_date=datetime(2025,1,1), schedule_interval=None) as dag:
    train = KubernetesPodOperator(
        task_id="train",
        name="train-job",
        image="my-registry/ml-train:latest",
        cmds=["python","train.py"],
        resources={
            "limit_gpu": 1,  # platform convention; actual key: "nvidia.com/gpu" in pod spec
            "request_memory": "16Gi",
            "request_cpu": "4"
        },
        # nodeSelector / tolerations example (real pod spec uses nodeSelector/affinity/tolerations fields)
        # full_pod_spec or pod_template_file are recommended for advanced configs
    )

A corresponding Pod YAML would include a toleration for the GPU node taint and an explicit nvidia.com/gpu resource request; adapting these is a common integration point between Airflow DAG code and platform node pool labels.

Trade-offs and “gotchas”

A balanced closing note

Airflow and Kubernetes together offer a powerful control plane + execution plane for ML pipelines—especially now that Airflow 3 brings more ML-friendly workflow primitives and the Kubernetes GPU ecosystem supports fractional sharing and robust device management. The combination unlocks better GPU utilization and more elastic ML pipelines, but it also converts resource contention into a cross-system problem. Treat orchestration design like sound mixing: a few well-placed filters and buffers (node pools, taints, autoscalers, PgBouncer) can keep the signal clean; too many instruments without a conductor can quickly muddy the performance.

For teams moving from ETL-first workloads into heavy ML usage, the pragmatic takeaway is to view Airflow as the conductor and Kubernetes as the stage crew—design placement and sharing policies at the infra level, keep heavy compute in ephemeral pods, and monitor both orchestration and device layers closely. The recent releases and device-plugin advances give more options than before; choosing the right mix depends on whether your workloads need exclusivity, predictability, or raw throughput. (airflow.apache.org)

References (selected)