Airflow KubernetesExecutor: запуск каждой задачи в отдельном поде
Настройка KubernetesExecutor в Airflow. pod_template_file, namespace, service account, image. Отладка когда под не запус
Запуск каждой задачи Airflow в отдельном поде через KubernetesExecutor — это переход от «кошек в одной коробке» к строгой изоляции процессов. Если вы устали от конфликтов зависимостей между DAG’ами или вам нужна гибкость в выборе образа и ресурсов под конкретную задачу, то это ваш путь. Гайд для тех, кто уже пережил боль shared-окружения и хочет сделать по-уму.
Базовая конфигурация executor
В airflow.cfg или через переменные окружения (AIFLOW__KUBERNETESES__…) задаём ключевые параметры. Основное — указать executor и настроить подключение к кластеру. In-cluster конфигурация обычно работает сама, если под Airflow запущен в Kubernetes.
[core]
executor = KubernetesExecutor
[kubernetes_executor]
namespace = airflow-tasks
pod_template_file = /opt/airflow/pod_templates/pod_template.yaml
worker_container_repository = apache/airflow
worker_container_tag = 2.7.3
delete_worker_pods = true
delete_worker_pods_on_failure = true
Сервисный аккаунт и RBAC
Поду задачи будут запускаться под определённым ServiceAccount. Ему нужны права на создание/удаление подов в целевом namespace. Создаём аккаунт и минимальную роль:
apiVersion: v1
kind: ServiceAccount
metadata:
name: airflow-task-runner
namespace: airflow-tasks
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: airflow-tasks
name: pod-creator
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "get", "list", "watch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: airflow-task-runner-binding
namespace: airflow-tasks
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-creator
subjects:
- kind: ServiceAccount
name: airflow-task-runner
namespace: airflow-tasks
Укажите этот аккаунт в pod_template_file.
Сердце системы: pod_template_file
Это YAML-манифест, шаблон для всех рабочих подов. Определите здесь базовый образ, serviceAccountName, volumeMounts и переменные окружения, общие для всех задач. Критически важно задать AIRFLOW__CORE__EXECUTOR=KubernetesExecutor, иначе под попытается использовать LocalExecutor.
apiVersion: v1
kind: Pod
metadata:
labels:
app: airflow-task
spec:
serviceAccountName: airflow-task-runner
restartPolicy: Never
containers:
- name: base
image: apache/airflow:2.7.3
imagePullPolicy: IfNotPresent
env:
- name: AIRFLOW__CORE__EXECUTOR
value: KubernetesExecutor
- name: AIRFLOW__DATABASE__SQL_ALCHEMY_CONN
valueFrom:
secretKeyRef:
name: airflow-metadata
key: connection
resources:
requests:
memory: "256Mi"
cpu: "100m"
Динамическое управление ресурсами через executor_config
Шаблон — это основа, но конкретную задачу можно донастроить прямо в DAG. Через параметр executor_config в операторе задаются требования к CPU, память, или даже целый другой образ.
from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime
import json
def process_data():
import pandas as pd
print("Processing with pandas")
with DAG('k8s_example', start_date=datetime(2023, 1, 1)) as dag:
heavy_task = PythonOperator(
task_id='heavy_data_processing',
python_callable=process_data,
executor_config={
"pod_override": {
"spec": {
"containers": [{
"name": "base",
"resources": {
"requests": {"memory": "2Gi", "cpu": "1000m"},
"limits": {"memory": "4Gi", "cpu": "2000m"}
}
}]
}
}
}
)
Когда под не запускается: чек-лист для отладки
- Проверьте логи scheduler. Там будут ошибки, если не удалось создать под. Частая причина — неверное имя service account или недостаток прав RBAC.
- Убедитесь, что
pod_template_fileвалиден. Проверьте черезkubectl apply --dry-run=client -f pod_template.yaml. - Образ. Указанный в шаблоне образ должен существовать и быть доступен из кластера. Ошибка
ImagePullBackOff— явный признак. - Контекст запуска. Scheduler должен работать внутри кластера и иметь доступ к Kubernetes API. Для внешнего кластера нужно настроить
kube_configиin_cluster=False. - Лимиты ресурсов. Если запрашиваете больше ресурсов, чем доступно в namespace, под будет в статусе
Pending. Смотритеkubectl describe pod.
Подводные камни
Главный — увеличение нагрузки на etcd и API Kubernetes при высокой частоте запуска коротких задач (тысячи подов в час). Планируйте ресурсы нод с запасом на быструю диспетчеризацию. Второй — наследование конфигурации. Переменные из pod_template_file и executor_config мержатся, при конфликте побеждает executor_config. Всегда тестируйте итоговый манифест.
KubernetesExecutor даёт чистую изоляцию и невероятную гибкость, ценой некоторой сложности отладки. Потратьте время на настройку шаблона и RBAC один раз, и вы получите мощный и предсказуемый оркестратор задач.