KubernetesPodOperator
Any Container, As a Task
The KubernetesExecutor (covered earlier) changes how Airflow itself schedules work - every task gets its own pod, no matter what operator it uses. KubernetesPodOperator is different: it's a specific operator you choose deliberately, for one task, when the work is "run this exact container image," regardless of which executor the rest of your DAG uses.
Same honest note as the EMR, Redshift, Glue, and ECS/Batch pages: running this for real needs an actual Kubernetes cluster, which isn't available in this local sandbox. The code below is correct, real provider code.
The Core Pattern
from airflow.providers.cncf.kubernetes.operators.pod import KubernetesPodOperator
run_report_container = KubernetesPodOperator(
task_id="run_report_generator",
name="report-generator",
namespace="airflow-tasks",
image="my-registry/report-generator:v1.2.0",
cmds=["python", "generate_report.py"],
arguments=["--date", "{{ ds }}"],
get_logs=True,
is_delete_operator_pod=True, # clean up the pod after the task finishes
)
Every parameter maps directly to something you'd otherwise write in a Kubernetes pod spec YAML — image, cmds/arguments, resource requests, environment variables, volume mounts — except it's expressed as plain Python arguments, and Airflow handles pod creation, log streaming, and cleanup.
Resource Requests and Limits
from kubernetes.client import models as k8s
run_with_resources = KubernetesPodOperator(
task_id="run_memory_heavy_job",
name="memory-heavy-job",
namespace="airflow-tasks",
image="my-registry/data-processor:latest",
container_resources=k8s.V1ResourceRequirements(
requests={"cpu": "1", "memory": "2Gi"},
limits={"cpu": "2", "memory": "4Gi"},
),
is_delete_operator_pod=True,
)
This is the same idea shown for the KubernetesExecutor's per-pod resource sizing — but here it's set explicitly per task, because different KubernetesPodOperator tasks in the same DAG can each request completely different resources.
When to Choose This Over Other Options
| If... | Use |
|---|---|
| The whole Airflow deployment already runs on Kubernetes, and you want per-task resource isolation for every task by default | KubernetesExecutor |
| One specific task needs a container image the rest of the DAG doesn't (different language, different dependency set, a legacy tool) | KubernetesPodOperator |
| The work is small, fast, stateless, and doesn't need a custom image | PythonOperator / Lambda (see the AWS Lambda page) |
| The team is AWS-native and doesn't run Kubernetes at all | ECS/Batch (see that page) |
is_delete_operator_pod=True is worth setting explicitly and deliberately - without it, completed pods accumulate in the cluster. Set it to False only temporarily, while actively debugging a failing task, so you can inspect the pod's final state before it disappears.