Validate KubernetesExecutor launches with external executor IDs#69782
Validate KubernetesExecutor launches with external executor IDs#69782wolvery wants to merge 10 commits into
Conversation
|
@wolvery This PR has been converted to draft because it does not yet meet our Pull Request quality criteria. Issues found:
What to do next:
Converting a PR to draft is not a rejection — it is an invitation to bring the PR up to the project's standards so that maintainer review time is spent productively. There is no rush — take your time and work at your own pace. We appreciate your contribution and are happy to wait for updates. If you have questions, feel free to ask on the Airflow Slack. Note: This comment was drafted by an AI-assisted triage tool and may contain mistakes. Once you have addressed the points above, an Apache Airflow maintainer — a real person — will take the next look at your PR. We use this two-stage triage process so that our maintainers' limited time is spent where it matters most: the conversation with you. |
db75770 to
6bff389
Compare
|
Ok, fixes done! |
2bfc36b to
697eeb3
Compare
9ae2e2b to
9784637
Compare
Only reject a task-instance /run when the worker actually presents an external_executor_id. Older Task SDK workers (mid rolling-upgrade, before the field existed) omit it entirely; fencing them would 409 every launch for pre-assigning executors (KubernetesExecutor, CeleryExecutor) until all workers are upgraded. Absent tokens now fall back to state-based validation. Also document that dropping a stale Kubernetes workload intentionally leaves the task instance in place (owned by the newer launch / reclaimed by queued-task timeout or adoption) rather than failing it. Tests: - API: matching token accepted; missing token accepted for old clients. - KubernetesExecutor: matching token creates the pod (positive counterpart to the stale-drop test). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
17b60ef to
43d4e84
Compare

What
Fixes #69760.
This adds DB-backed launch-token validation for KubernetesExecutor task launches using Airflow's existing
external_executor_idfield:external_executor_idlaunch tokensExecuteTaskworkloads and worker/runrequests/execution/task-instances/{id}/runrequests when the current DB token no longer matches the worker/pod tokenThis prevents a stale Kubernetes workload from validly transitioning an obsolete task-instance launch to
RUNNINGafter a newer queued launch has superseded it.Token semantics
This is equality-based launch-token validation, not a classic monotonic fencing token.
Airflow already has a scheduler path for executors that set
pre_assigns_external_executor_id = True. When such a task instance is queued, the scheduler writes a freshexternal_executor_idUUID to thetask_instancerow. This PR makes KubernetesExecutor use that existing capability and preserve that token through the Kubernetes workload lifecycle.The intended invariant is:
So this is a per-launch ownership token / capability token. It is rotated when Airflow queues a new launch by assigning a new
external_executor_id; it is not ordered, and it should not be interpreted as a monotonic distributed-systems fencing counter.Behavior notes
/runstill returns404 not_found; the worker should treat that as a stale launch and exit without running user code./runreturns409 stale_executor_launchand the worker should treat it as stale.ExecuteTaskworkloads. Otherwise the scheduler interprets the event info asexternal_executor_idand can overwrite the UUID launch token with the numeric scheduler job id.external_executor_id. Rows without a token keep the existing state-based validation so rolling upgrades and legacy queued work are not rejected solely because an older worker omitted the new field.Tests
python3 -m compileall ...on modified source and test filesuv run ruff check ...uv run ruff format --check ...git diff --checkairflow-core/.../execution_api/versions/head/test_task_instances.py -k ti_run— 25 passed, 1 skipped (postgres-only)providers/cncf/kubernetes/.../executors/test_kubernetes_executor.py -k "sync or run_next or stale or external_executor"— all passedGen-AI disclosure
Generated-by: GPT following the guidelines: https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions
Important
🛠️ Maintainer triage note for @wolvery · by
@potiuk· 2026-07-15 16:00 UTCHelpful heads-up from the maintainers — please address before this PR can be reviewed (see our Pull Request quality criteria):
The ball is in your court — you've been assigned to this PR. Fix the above, then mark it Ready for review.
Automated triage — may be imperfect; a maintainer takes the next look.