This is an automated email from the ASF dual-hosted git repository.
onikolas pushed a commit to branch v2-10-stable
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v2-10-stable by this push:
new 12a124af3d0 Mark the hardcoded hybrid executors as deprecate and
multi-exec as stable (#46944)
12a124af3d0 is described below
commit 12a124af3d0483ae85c01874bcb45effa6834e26
Author: Niko Oliveira <[email protected]>
AuthorDate: Mon Feb 24 14:04:40 2025 -0800
Mark the hardcoded hybrid executors as deprecate and multi-exec as stable
(#46944)
* Mark Multiple Executor Configuration as stable
Multiple Executor Configuration (aka hybrid executors) has been released
for over half a year and can be marked stable. This gives users an
option to migrate to from the old hardcoded hybrid executors (e.g
CeleryKubernetesExecutor)
* Mark the statically-coded hybrid executors as deprecated
These executors will be removed in Airflow 3.0. Mark them as deprecated
so users are aware and have time to migrate.
- A deprecation warning will be printed when the executors are loaded
- Documentation has been updated to note that they are deprecated
- A news fragment added as well.
Co-authored-by: Jed Cunningham
<[email protected]>
---
airflow/executors/executor_loader.py | 20 +++++++++++++++++++-
docs/apache-airflow/core-concepts/executor/index.rst | 17 +++++++++++------
newsfragments/46944.significant.rst | 3 +++
tests/executors/test_executor_loader.py | 10 ++++++++--
tests/utils/test_log_handlers.py | 12 +++++++++---
5 files changed, 50 insertions(+), 12 deletions(-)
diff --git a/airflow/executors/executor_loader.py
b/airflow/executors/executor_loader.py
index 7ad42a2fb1b..c306d8f0004 100644
--- a/airflow/executors/executor_loader.py
+++ b/airflow/executors/executor_loader.py
@@ -21,11 +21,12 @@ from __future__ import annotations
import functools
import logging
import os
+import warnings
from contextlib import suppress
from typing import TYPE_CHECKING
from airflow.api_internal.internal_api_call import InternalApiConfig
-from airflow.exceptions import AirflowConfigException, UnknownExecutorException
+from airflow.exceptions import AirflowConfigException,
RemovedInAirflow3Warning, UnknownExecutorException
from airflow.executors.executor_constants import (
CELERY_EXECUTOR,
CELERY_KUBERNETES_EXECUTOR,
@@ -344,8 +345,24 @@ class ExecutorLoader:
if engine and engine.dialect.name == "sqlite":
raise AirflowConfigException(f"error: cannot use SQLite with the
{executor.__name__}")
+ @classmethod
+ def _warn_of_deprecated_executor(cls, executor_name: str) -> None:
+ """
+ Warn of deprecated executor.
+
+ :param executor_name: Name of the executor
+ """
+ warnings.warn(
+ f"\nThe use and support of the {executor_name} is deprecated and
will be removed in Airflow 3.0.\n"
+ "Please migrate to using Multiple Executor Configuration
instead:\n"
+
"https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/executor/#using-multiple-executors-concurrently",
+ RemovedInAirflow3Warning,
+ stacklevel=2,
+ )
+
@classmethod
def __load_celery_kubernetes_executor(cls) -> BaseExecutor:
+ cls._warn_of_deprecated_executor(CELERY_KUBERNETES_EXECUTOR)
celery_executor = import_string(cls.executors[CELERY_EXECUTOR])()
kubernetes_executor =
import_string(cls.executors[KUBERNETES_EXECUTOR])()
@@ -354,6 +371,7 @@ class ExecutorLoader:
@classmethod
def __load_local_kubernetes_executor(cls) -> BaseExecutor:
+ cls._warn_of_deprecated_executor(LOCAL_KUBERNETES_EXECUTOR)
local_executor = import_string(cls.executors[LOCAL_EXECUTOR])()
kubernetes_executor =
import_string(cls.executors[KUBERNETES_EXECUTOR])()
diff --git a/docs/apache-airflow/core-concepts/executor/index.rst
b/docs/apache-airflow/core-concepts/executor/index.rst
index 1bb11f2335a..2aa976ab86f 100644
--- a/docs/apache-airflow/core-concepts/executor/index.rst
+++ b/docs/apache-airflow/core-concepts/executor/index.rst
@@ -115,9 +115,6 @@ Airflow tasks are executed ad hoc inside containers/pods.
Each task is isolated
Using Multiple Executors Concurrently
-------------------------------------
-.. warning::
- Multiple executor configuration is an alpha/experimental feature at the
moment and may be subject to change without warning.
-
Starting with version 2.10.0, Airflow can now operate with a multi-executor
configuration. Each executor has its own set of pros and cons, often they are
trade-offs between latency, isolation and compute efficiency among other
properties (see :ref:`here <executor-types-comparison>` for comparisons of
executors). Running multiple executors allows you to make better use of the
strengths of all the available executors and avoid their weaknesses. In other
words, you can use a specific execut [...]
Configuration
@@ -208,15 +205,23 @@ When using a single executor, Airflow metrics will behave
as they were <2.9. But
Logging works the same as the single executor use case.
-Statically-coded Hybrid Executors
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Statically-coded Hybrid Executors (Deprecated)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There are currently two "statically coded" executors, these executors are
hybrids of two different executors: the :doc:`LocalKubernetesExecutor
<apache-airflow-providers-cncf-kubernetes:local_kubernetes_executor>` and the
:doc:`CeleryKubernetesExecutor
<apache-airflow-providers-celery:celery_kubernetes_executor>`. Their
implementation is not native or intrinsic to core Airflow. These hybrid
executors instead make use of the ``queue`` field on Task Instances to indicate
and persist which [...]
Executors such as these also require hand crafting new "concrete" classes to
create each permutation of possible combinations of executors. This is
untenable as more executors are created and leads to more maintenance overhead.
Bespoke coding effort should not be required to use any combination of
executors.
-Therefore using these types of executors is no longer recommended.
+Therefore these types of executors are deprecated and using them is no longer
recommended.
+
+Migrating from Statically-Coded Hybrid Executors to Multi-Executor
Configuration
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+Here are some steps to migrate from statically-coded hybrid executors to the
new multi-executor configuration:
+1. **Update Airflow**: Ensure you are using Airflow 2.10.0 or later.
+2. **Update executor configuration**: Update the ``[core] executor``
configuration to replace the use of the statically-coded hybrid executor with
the new multi-executor configuration (i.e. a list of the executors you'd like
to use). For example, replace ``LocalKubernetesExecutor`` with
``LocalExecutor,KubernetesExecutor``.
+3. **Update Dags**: Update your dags to use the new multi-executor
configuration. This involves replacing the use of the ``queue`` field on your
tasks with the ``executor`` field to specify which executor you'd like to use.
Writing Your Own Executor
-------------------------
diff --git a/newsfragments/46944.significant.rst
b/newsfragments/46944.significant.rst
new file mode 100644
index 00000000000..8dabb9a3546
--- /dev/null
+++ b/newsfragments/46944.significant.rst
@@ -0,0 +1,3 @@
+Statically-coded executors are now deprecated; use Multiple Executor
Configuration
+
+The Statically-coded executors ``LocalKubernetesExecutor`` and
``CeleryKubernetesExecutor`` are now deprecated in favor of Multiple Executor
Configuration, which is now marked as stable. They will be removed in Airflow
3.0
diff --git a/tests/executors/test_executor_loader.py
b/tests/executors/test_executor_loader.py
index dc60b9cc507..7c9d21fb9e3 100644
--- a/tests/executors/test_executor_loader.py
+++ b/tests/executors/test_executor_loader.py
@@ -22,7 +22,7 @@ from unittest import mock
import pytest
from airflow import plugins_manager
-from airflow.exceptions import AirflowConfigException
+from airflow.exceptions import AirflowConfigException, RemovedInAirflow3Warning
from airflow.executors import executor_loader
from airflow.executors.executor_loader import ConnectorSource, ExecutorName
from airflow.executors.local_executor import LocalExecutor
@@ -68,7 +68,13 @@ class TestExecutorLoader:
)
def test_should_support_executor_from_core(self, executor_name):
with conf_vars({("core", "executor"): executor_name}):
- executor = executor_loader.ExecutorLoader.get_default_executor()
+ # These executors are deprecated and will be removed in Airflow
3.0 but we still need to support
+ # them in Airflow 2.10.X
+ if executor_name == "CeleryKubernetesExecutor":
+ with pytest.warns(RemovedInAirflow3Warning):
+ executor =
executor_loader.ExecutorLoader.get_default_executor()
+ else:
+ executor =
executor_loader.ExecutorLoader.get_default_executor()
assert executor is not None
assert executor_name == executor.__class__.__name__
assert executor.name is not None
diff --git a/tests/utils/test_log_handlers.py b/tests/utils/test_log_handlers.py
index 95483f2285f..2c1e2db1f49 100644
--- a/tests/utils/test_log_handlers.py
+++ b/tests/utils/test_log_handlers.py
@@ -206,7 +206,6 @@ class TestFileTaskLogHandler:
"executor_name",
[
(executor_constants.LOCAL_KUBERNETES_EXECUTOR),
- (executor_constants.CELERY_KUBERNETES_EXECUTOR),
(executor_constants.KUBERNETES_EXECUTOR),
(None),
],
@@ -216,7 +215,6 @@ class TestFileTaskLogHandler:
("core", "EXECUTOR"): ",".join(
[
executor_constants.LOCAL_KUBERNETES_EXECUTOR,
- executor_constants.CELERY_KUBERNETES_EXECUTOR,
executor_constants.KUBERNETES_EXECUTOR,
]
),
@@ -279,7 +277,15 @@ class TestFileTaskLogHandler:
file_handler.close()
assert hasattr(file_handler, "read")
- file_handler.read(ti)
+ # These executors are deprecated and will be removed in Airflow
3.0 but we still need to support
+ # them in Airflow 2.10.X
+ if executor_name in [
+ executor_constants.LOCAL_KUBERNETES_EXECUTOR,
+ ]:
+ with pytest.warns(RemovedInAirflow3Warning):
+ file_handler.read(ti)
+ else:
+ file_handler.read(ti)
os.remove(log_filename)
mock_get_task_log.assert_called_once()