Skip to content

Fence KubernetesExecutor launches with external executor IDs#69782

Open
wolvery wants to merge 1 commit into
apache:mainfrom
wolvery:fix-kubernetes-launch-token-fencing
Open

Fence KubernetesExecutor launches with external executor IDs#69782
wolvery wants to merge 1 commit into
apache:mainfrom
wolvery:fix-kubernetes-launch-token-fencing

Conversation

@wolvery

@wolvery wolvery commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

What

Fixes #69760.

This adds DB-backed launch-token fencing for KubernetesExecutor task launches:

  • opt KubernetesExecutor into scheduler pre-assigned external_executor_id tokens
  • serialize the token into Airflow 3 ExecuteTask workloads and worker /run requests
  • annotate Kubernetes pods with the executor launch token
  • reject stale /execution/task-instances/{id}/run requests when the DB token no longer matches
  • revalidate queued Kubernetes jobs against the current DB row/token immediately before pod creation

This prevents stale Kubernetes workloads from validly transitioning an obsolete task instance launch to RUNNING after a newer queued launch has replaced it.

Behavior notes

  • Stale-drop recovery: When a stale Kubernetes workload is dropped before pod creation, its task instance is left in place (typically still QUEUED under the newer launch that superseded it) rather than failed. The newer launch's own workload creates the pod, or the scheduler's queued-task timeout / task-instance adoption reclaims the row. Failing it here would clobber the newer launch.
  • Rolling upgrades: The /run launch-token fence only applies when the worker actually presents a token. Older Task SDK workers (before this field existed) omit it entirely, and are not rejected mid-upgrade — they fall back to state-based validation. This keeps zero-downtime upgrades working for both KubernetesExecutor and CeleryExecutor, which share this pre-assigning /run path.

Tests

  • python3 -m compileall ... on modified source and test files
  • uv run ruff check ...
  • uv run ruff format --check ...
  • git diff --check
  • pytest (isolated sqlite backend):
    • airflow-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 passed
    • Covers stale-token rejection, matching-token acceptance, missing-token acceptance (old clients), and matching-token pod creation.

Gen-AI disclosure

  • Yes: GPT was used to assist in authoring this PR. The changes were reviewed and validated by the contributor before submission.

Generated-by: GPT following the guidelines: https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

@boring-cyborg boring-cyborg Bot added area:API Airflow's REST/HTTP API area:Executors-core LocalExecutor & SequentialExecutor area:providers area:task-sdk provider:cncf-kubernetes Kubernetes (k8s) provider related issues labels Jul 12, 2026
@wolvery wolvery marked this pull request as draft July 12, 2026 17:48
@wolvery wolvery marked this pull request as ready for review July 13, 2026 09:46
@wolvery

wolvery commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Hey! I've tested it locally and it seems to have no other race condition happening

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:API Airflow's REST/HTTP API area:Executors-core LocalExecutor & SequentialExecutor area:providers area:task-sdk provider:cncf-kubernetes Kubernetes (k8s) provider related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KubernetesExecutor can start stale worker pods for obsolete TaskInstance UUIDs under HA schedulers

1 participant