Apache Airflow 插件开发实战:从零编写一个自定义 Plugin 视图
【免费下载链接】airflowApache Airflow - A platform to programmatically author, schedule, and monitor workflows项目地址: https://gitcode.com/GitHub_Trending/ai/airflow
导读
Apache Airflow 提供了强大的插件(Plugin)机制,允许开发者在不修改核心代码的前提下,为 Web UI 添加自定义视图、Blueprint、宏、监听器等能力。本文以当前仓库 airflow-core/docs/empty_plugin 中的官方示例插件(empty plugin)为骨架,从零讲解如何编写、安装并在 Airflow UI 中注册一个属于自己的自定义视图:包括 Flask-AppBuilder 视图的写法、Blueprint 与模板的组织方式、AirflowPlugin子类的属性约定,以及插件目录的配置与加载机制。读完本文,你将能够复制该示例到自己的 Airflow 环境中运行,并以此为模板扩展出带业务功能的插件页面。
示例插件概览:一个最小可运行的 Airflow 插件
官方文档 empty_plugin/README.md 给出了一个非常精简的示例插件,其作用是在 Airflow Web UI 中显示一个空视图(empty view)。整个插件目录包含三个文件:
airflow-core/docs/empty_plugin/ ├── README.md # 安装说明 ├── empty_plugin.py # 插件主代码 └── templates/ └── empty_plugin/ └── index.html # 视图模板这是一个刻意保持"最小"的示例:它不包含任何业务逻辑、后端数据或复杂交互,而是专注于演示一个插件要能够被 Airflow 识别并挂载到 Web UI 上所必须拥有的全部要素。理解了它,就理解了 Airflow 插件体系的最小闭环。
插件代码逐行解析
插件主文件 empty_plugin.py 中依次定义了三类关键对象,它们共同构成了一个可被 Airflow 加载的插件。
1. Flask-AppBuilder 视图:EmptyPluginView
from flask_appbuilder import BaseView, expose class EmptyPluginView(BaseView): """Creating a Flask-AppBuilder View""" default_view = "index" @expose("/") @has_access_view(AccessView.PLUGINS) def index(self): """Create default view""" return self.render_template("empty_plugin/index.html", name="Empty Plugin")要点说明:
- 继承
BaseView:Airflow 3 的 Web UI 基于 Flask-AppBuilder(FAB)构建,自定义视图需要继承 FAB 的BaseView(在 providers/fab/src/airflow/providers/fab/www/auth.py 等 FAB 集成代码中可以看到这一体系的实际应用)。 default_view = "index":指定视图的默认入口方法名,访问该视图的根路径时自动路由到index。@expose("/"):FAB 装饰器,把index方法暴露为可访问的 HTTP 端点。@has_access_view(AccessView.PLUGINS):权限控制装饰器,来自airflow.providers.fab.www.auth,将视图访问限定为PLUGINS权限域。这意味着用户需要具备访问 Plugins 视图的权限才能看到该页面;这也是新版 Airflow 对插件视图进行细粒度权限管控的体现。render_template("empty_plugin/index.html", name="Empty Plugin"):渲染模板并传入上下文变量name。
2. Flask Blueprint:静态资源与模板的载体
from flask import Blueprint bp = Blueprint( "Empty Plugin", __name__, template_folder="templates", static_folder="static", static_url_path="/static/empty_plugin", )Blueprint 的作用是让插件拥有独立的模板目录与静态资源命名空间:
template_folder="templates":声明插件自身携带的模板目录,Airflow 在渲染时会找到templates/empty_plugin/index.html;static_folder="static"、static_url_path="/static/empty_plugin":为插件的静态文件(如 CSS/JS)预留挂载路径,避免与其他插件资源冲突(当前示例未放置静态文件,但保留了完整的挂载声明)。
3. 插件入口类:继承 AirflowPlugin
from airflow.plugins_manager import AirflowPlugin class EmptyPlugin(AirflowPlugin): """Defining the plugin class""" name = "Empty Plugin" flask_blueprints = [bp] appbuilder_views = [{"name": "Empty Plugin", "category": "Extra Views", "view": EmptyPluginView()}]这是整个插件的注册入口,核心约定如下:
- 插件类必须继承
airflow.plugins_manager.AirflowPlugin(见 airflow-core/src/airflow/plugins_manager.py),Airflow 通过扫描并实例化该基类的子类来完成插件发现; name:插件唯一名称,会显示在 Web UI 中;flask_blueprints:把前面定义的 Blueprint 挂到插件上;appbuilder_views:以字典列表形式注册 FAB 视图,其中category指定 UI 导航菜单中的分组(这里为 "Extra Views"),name为菜单项名称,view为视图实例。通过该配置,用户即可在 Airflow UI 左侧导航的 "Extra Views" 分组下看到 "Empty Plugin" 入口。
视图模板:与 Airflow 主题融合
模板文件 templates/empty_plugin/index.html 展示了插件页面与 Airflow 主 UI 无缝集成的方式:
{% extends base_template %} {% block head %} {{ super() }} {% endblock %} {% block body %} <div> <h3 style="float: left"> {% block page_header %}{{ name }}{% endblock%} </h3> <div id="object" class="select2-drop-mask" style="margin-top: 25px; width: 400px;float: right"></div> <div style="clear: both"></div> </div> {% block plugin_content %}{% endblock %} {% endblock %} {% block tail %} {{ super() }} {% endblock %}关键点:
{% extends base_template %}:base_template是 Airflow 在执行插件视图时注入的全局变量,指向 Airflow 自身的主页面模板。插件页面因此自动继承 Airflow 的布局、样式与导航外壳,视觉上与原生页面完全一致;{{ name }}:即EmptyPluginView.index中通过render_template(..., name="Empty Plugin")传入的上下文变量,演示了控制器如何向模板传值;{% block plugin_content %}{% endblock %}:预留的扩展点,后续开发者可以基于该模板派生更多页面内容。
安装与配置:让 Airflow 发现你的插件
官方文档给出的安装方式非常直接:将整个插件目录(empty_plugin.py与templates/)拷贝到 Airflow 的插件目录即可。
插件目录的路径由配置文件[core]小节中的plugins_folder选项指定,其默认值为{AIRFLOW_HOME}/plugins。在 airflow-core/src/airflow/settings.py 中可以看到该配置项的解析逻辑:
PLUGINS_FOLDER = conf.get("core", "plugins_folder", fallback=os.path.join(AIRFLOW_HOME, "plugins"))在配置文件模板 airflow-core/src/airflow/config_templates/config.yml 中,该选项的正式说明为:"Path to the folder containing Airflow plugins",即存放 Airflow 插件的文件夹路径。
完整的安装步骤如下:
- 确定你的
AIRFLOW_HOME(默认~/airflow),插件目录即{AIRFLOW_HOME}/plugins,目录不存在则创建它; - 将示例目录中的
empty_plugin.py和templates/子目录整体复制到插件目录,最终结构为:
{AIRFLOW_HOME}/plugins/ ├── empty_plugin.py └── templates/ └── empty_plugin/ └── index.html- 如需自定义插件目录位置,可通过环境变量覆盖:
export AIRFLOW__CORE__PLUGINS_FOLDER=/path/to/my/plugins- 重启 Airflow Webserver(或调度器等进程)使插件生效。
插件加载时,Airflow 会扫描plugins_folder下的所有 Python 模块,收集其中AirflowPlugin的子类,并注册其声明的 Blueprint 与 FAB 视图(对应 airflow-core/src/airflow/plugins_manager.py 中ensure_plugins_loaded与_get_plugins的加载流程)。重启完成后,在 Airflow Web UI 左侧导航的Extra Views → Empty Plugin即可看到渲染出的自定义页面。
源码佐证:插件加载与视图挂载的底层机制
从源码结构看,插件机制的核心调度都集中在 airflow-core/src/airflow/plugins_manager.py:
ensure_plugins_loaded()/_get_plugins():负责从插件目录和 entry points 加载插件,且仅加载一次(结果带缓存);get_flask_plugins()(第 302 行附近):将插件的flask_blueprints逐一声明为{"name": plugin.name, "blueprint": bp},把appbuilder_views汇总为flask_appbuilder_views列表,供 FAB 注册到 Web UI(见 plugins_manager.py);get_plugin_info():可以输出插件的元信息(包括flask_blueprints、appbuilder_views等属性),便于调试确认插件是否被正确识别。
这意味着示例插件中声明的flask_blueprints = [bp]与appbuilder_views = [...]最终会被 Airflow 汇总并挂载到 Web 应用上——这就是"拷贝目录即可生效"背后的完整链路。
另外,在 airflow-core/src/airflow/cli/commands/info_command.py 中,airflow info命令也会输出plugins_folder的值,你可以用它快速确认当前环境实际使用的插件目录,排查"插件不生效"类问题。
从示例到生产:扩展建议
掌握了示例的最小闭环后,可以按以下方向扩展出真实可用的插件页面:
- 增加后端逻辑:在
index方法中查询 Airflow 的模型(如 DAG、TaskInstance),把数据传入模板展示; - 扩展模板:在
block plugin_content中填充业务内容,或添加自己的 CSS/JS 到static/目录; - 细分权限:调整
has_access_view的权限域参数,控制不同角色的可见性; - 更多插件能力:Airflow 插件体系还支持宏(macros)、操作符链接(operator extra links)、监听器(listeners)、时间表(timetables)等扩展点,同样只需在
AirflowPlugin子类中声明对应属性即可被框架识别。
总结
本文基于 Apache Airflow 官方示例插件 empty_plugin,完整梳理了一个最小插件的三大组成:Flask-AppBuilder 视图(页面与路由)、Flask Blueprint(模板与静态资源)、AirflowPlugin子类(注册入口),并说明了plugins_folder配置(默认{AIRFLOW_HOME}/plugins)与插件加载机制。照此实践,你可以快速验证 Airflow 插件开发全流程,并以此为骨架搭建属于自己的 Airflow UI 扩展页面。
【免费下载链接】airflowApache Airflow - A platform to programmatically author, schedule, and monitor workflows项目地址: https://gitcode.com/GitHub_Trending/ai/airflow
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考