Best Practices for KEDA with Airflow - Rafay Product Documentation

Setup

In this exercise, you will provision an Airflow Helm chart and test the autoscaling of Airflow with KEDA.

This tutorial describes the steps using the Rafay Web Console. The entire workflow can also be fully automated and embedded into an automation pipeline.

Assumptions

You have already provisioned or imported a Kubernetes cluster into your Rafay Org and created a blueprint with KEDA.

Step 1: Create Namespace

Step 2: Create Airflow Add-on

# Airflow Worker Config
workers:
  # Number of airflow celery workers in StatefulSet
  replicas: 1
  # Allow KEDA autoscaling.
  keda:
    enabled: true
dags:
  persistence:
    enabled: true
    storageClassName: openebs-hostpath
    subPath: ""
  mountPath: /opt/airflow/dags
config:
  core:
    parallelism: 128

The parallelism setting in the values file of 128 will limit the max scaling of Airflow workers to 8. This scaling will only occur when the number of Airflow Running and Queued tasks reaches 128. This may require multiple DAGs to reach this level of scaling.

Step 3: Update Blueprint

Step 4: Apply Blueprint

After a few seconds, the blueprint with the KEDA and Airflow add-ons will be published on the cluster.

Step 5: Verify deployment

kubectl get all -n airflow
kubectl get scaledobjects -n airflow

Step 6: Test Scaling

Create Airflow DAG

from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime
import time

def simulate_task(task_number):
    print(f"Task {task_number} is running")
    time.sleep(60)  # simulate a heavy task
    print(f"Task {task_number} is done")

default_args = {
    'start_date': datetime(2023, 1, 1),
}

with DAG(
    dag_id='keda_scaling_test',
    default_args=default_args,
    schedule_interval=None,
    catchup=False,
    concurrency=20,
    max_active_runs=10,
    tags=['keda', 'scaling', 'test']
) as dag:
    for i in range(20):  # 20 parallel tasks
        PythonOperator(
            task_id=f'simulated_task_{i}',
            python_callable=simulate_task,
            op_args=[i]
        )
kubectl cp ./keda_test_dag.py airflow-scheduler-fd795f55b-hmpqj:/opt/airflow/dags -n airflow

Login to Airflow

kubectl port-forward svc/airflow-webserver 8080:8080 -n airflow

You will see the previously loaded DAG. If you do not, refresh the screen as it can take up to a few minutes for the DAG to load.

Trigger DAG

watch kubectl get pods -n airflow

You will see that KEDA scales the needed Airflow worker pods

Every 2.0s: kubectl get pods -n airflow                                                                                                       keeda-cluster-tim: Wed May 28 20:29:25 2025

NAME                                 READY   STATUS    RESTARTS   AGE
airflow-postgresql-0                 1/1     Running   0          23m
airflow-redis-0                      1/1     Running   0          23m
airflow-scheduler-85cf6f8d47-zbcqf   2/2     Running   0          23m
airflow-statsd-8b64dd664-5qn5b       1/1     Running   0          23m
airflow-triggerer-0                  2/2     Running   0          23m
airflow-webserver-66bff8568c-x5lj9   1/1     Running   0          23m
airflow-worker-0                     2/2     Running   0          18s

After a few minutes, the DAG tasks will have completed and KEDA will scale down the worker pods.

If the dag is triggered multiple times in a short time period, the number of queued tasks will increase causing KEDA to scale up additional pods.