Apache Airflow 是一个开源的工作流编排(Workflow Orchestration)平台,由 Airbnb 于 2014 年内部开发,2016 年进入 Apache 孵化器,2019 年成为 Apache 顶级项目。它用 Python 代码把数据处理任务定义成有向无环图(DAG),由调度器(Scheduler)按时间或数据事件触发,由执行器(Executor)把任务分发到本机、Celery 集群或 Kubernetes 集群执行,并通过内置 Web UI 观察每一次运行的状态与日志。 Airflow 解决的核心问题是:cron 定时脚本难以管理任务间依赖、失败后无法自动重试与告警、跨团队的数据任务没有统一的可视化调度平台。它本身不执行数据分析,只负责“何时、按什么顺序、在哪个环境里”运行你的任务——真正的计算由任务内部调用的 Spark、SQL、Python、外部 API 等完成。 本篇攻略按“安装 → 上手 → 核心能力 → 生产部署”的顺序组织:先给出速览卡与安装命令,再用 15 分钟跑通第一个 ETL DAG,随后详解调度架构、操作符生态、数据感知调度与部署运维,最后提供同类工具对比、常见误区与面试题,帮助读者直接落地生产。
掌握 Airflow 是数据工程师与 MLOps 工程师的核心竞争力:它是企业数据管道编排的事实标准,会用它即具备生产级 ETL、模型训练与 RAG 管道调度的落地能力。
目录
速览卡是工具类内容的固定首屏模块:30 秒判断「这工具是什么、能不能商用、适不适合我」。
为什么需要 Airflow:把零散定时任务变成可依赖、可观测的管道
传统的定时任务通常用 cron 写在多台服务器上,每个脚本各跑各的。一旦上游数据没准备好,下游任务照常执行,产生脏数据;任务失败后没有自动重试,只能等人工发现;任务间的依赖关系散落在文档和人的脑子里,换个人就说不清楚。规模稍大(几十个任务、跨团队协作)就会频繁出问题。
Airflow 用“代码即管道”的方式解决:你在 Python 文件里声明 DAG,节点是任务、边是依赖,调度器负责判断“依赖是否就绪、是否到时间”,执行器决定任务在哪里运行,失败自动重试并告警,Web UI 展示每次运行的依赖图、耗时与日志。任务间不再靠“谁先启动”来隐式协调,而是显式声明依赖。
与 Dagster、Prefect 等新一代编排工具相比,Airflow 的气质更偏向“成熟稳定的大生态”:操作符(Operator,即执行特定动作的任务模板)覆盖几乎所有数据系统,社区资料与生产案例最多,是大多数企业数据平台的默认选择;代价是概念多、上手曲线比 Prefect 陡。
安装与环境配置:4 步就绪
步骤一:准备 Python 环境。 Airflow 2.10 支持 Python 3.8–3.12,建议使用独立虚拟环境,避免与系统 Python 或项目依赖互相污染。
步骤二:安装。 官方包名是 apache-airflow,务必携带官方 constraints 文件一起安装。constraints 是官方为每个版本生成的依赖锁定清单,能避免 pandas、SQLAlchemy 等底层依赖版本冲突——这是 Airflow 安装最常踩的坑。
步骤三:初始化。 设置环境变量 AIRFLOW_HOME(默认即 ~/airflow),执行 airflow db migrate 初始化元数据库(2.7 起取代旧的 airflow db init,元数据库用来存放任务实例状态、日志索引与用户账号),然后创建管理员账号。
步骤四:启动与验证。 分别启动 airflow webserver 和 airflow scheduler 两个进程,浏览器访问 http://localhost:8080,用刚创建的账号登录,看到 DAGs 列表即成功。
# 1) 创建并进入 Python 虚拟环境(Python 3.8–3.12)python -m venv airflow-venvsource airflow-venv/bin/activate # 2) 安装(必须携带 constraints,版本号需与本地 Python 版本对应)pip install "apache-airflow==2.10.5" \ --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-2.10.5/constraints-3.11.txt" # 3) 初始化元数据库并创建管理员账号export AIRFLOW_HOME=~/airflowairflow db migrateairflow users create --username admin --firstname admin --lastname admin \ --role Admin --email admin@example.com --password admin # 4) 启动 Web Server 与 Scheduler(另开终端分别执行)airflow webserver --port 8080airflow scheduler
快速上手:15 分钟跑通第一个 ETL DAG
最小可用闭环的思路是:在 dags 目录放一个 Python 文件 → 调度器周期性扫描该目录并解析出 DAG → 手动触发一次运行 → Web UI 中观察任务是否按依赖顺序执行。整个过程中你不需要写任何服务端代码,只写一个声明依赖的 Python 脚本。
分步操作:
1. 创建 DAG 目录:mkdir -p ~/airflow/dags(若 AIRFLOW_HOME 是自定义路径,则创建 $AIRFLOW_HOME/dags)。
2. 在该目录新建 etl_pipeline.py,写入下方代码。DAG 定义了一个三条任务的链式依赖:抽取 → 转换 → 加载。
3. 验证解析:执行 airflow dags list,看到 etl_pipeline 即表示文件被正确解析;也可在 Web UI 的 DAGs 页面刷新确认。
4. 触发运行:在 DAGs 页面打开该 DAG,把开关置为开启(Pause 状态解除),点击“播放”按钮手动触发一次;或命令行执行 airflow dags trigger etl_pipeline。
5. 查看结果:进入该 DAG 的 Grid/Graph 视图,点击任意任务节点可查看运行日志、耗时与重试记录。
进阶技巧:单个任务调试用 airflow tasks test etl_pipeline transform 2025-01-01,它只运行指定任务不触发上下游;批量生成相似任务用 TaskGroup(任务组)与参数化模板,避免复制粘贴整套 DAG。
from datetime import datetime from airflow import DAGfrom airflow.operators.python import PythonOperator def extract(): print("从源系统抽取数据") def transform(): print("清洗与转换数据") def load(): print("写入目标数据仓库") with DAG( dag_id="etl_pipeline", start_date=datetime(2025, 1, 1), schedule="@daily", catchup=False, tags=["etl", "example"],) as dag: t_extract = PythonOperator(task_id="extract", python_callable=extract) t_transform = PythonOperator(task_id="transform", python_callable=transform) t_load = PythonOperator(task_id="load", python_callable=load) t_extract >> t_transform >> t_load
核心能力详解:4 大支柱
支柱一:DAG 编程模型。 DAG(Directed Acyclic Graph,有向无环图)指节点是任务、边是依赖、数据只能向前流动且不允许成环的图结构。Airflow 用普通 Python 文件描述这种结构,因此 DAG 可以进 Git 做版本管理、可以在 CI 里做单测、可以复用公共函数——这是 cron 脚本完全不具备的可维护性。
支柱二:Scheduler 与 Executor 分层调度架构。 Scheduler(调度器)不执行任务,只负责遍历 DAG、判断依赖与时间条件、把任务实例置为可运行状态;Executor(执行器)决定任务“在哪里跑”:LocalExecutor 在本机进程跑,CeleryExecutor 分发到分布式 Worker 队列,KubernetesExecutor 为每个任务拉起独立 Pod。分层设计让“调度逻辑”和“执行资源”解耦,同一套 DAG 可以在单机到集群之间平滑迁移。
支柱三:Operator / Sensor / Hook 三件套与 Provider 生态。 Operator(操作符)是任务的模板,如 PythonOperator 执行函数、BashOperator 执行命令、SnowflakeOperator 执行 SQL;Sensor(传感器)是等待外部条件的特殊任务,如等待文件到达、等待 SQL 查询有返回;Hook(连接钩子)封装外部系统的连接管理,供 Operator 复用。官方与社区维护 80+ 个 Provider 包(AWS、GCP、Spark、Snowflake、Flink 等),基本覆盖主流数据系统,接入新系统通常不需要自己写客户端代码。
支柱四:数据感知调度与可观测性。 除了 cron 时间触发,Airflow 2.4+ 支持 Datasets(数据集)触发:上游任务产出数据集后,依赖该数据集的下游 DAG 自动运行,实现“数据就绪才跑”而非“到点就跑”。可观测性方面,内置 Web UI 提供 DAG 列表、运行历史、依赖图、Gantt 图与任务日志;对外提供稳定的 REST API(/api/v1)和 statsd 指标输出,便于接入企业监控体系。
生产部署与监控:从上线到运维
部署方式一:Docker Compose 官方编排。 官方提供生产可用的 docker-compose 文件,包含 PostgreSQL(元数据库)、Redis(Celery Broker)、webserver、scheduler、worker、triggerer 等 8 个服务,适合中小团队快速搭建标准环境。先下载与版本匹配的 docker-compose.yaml,创建 ./dags ./logs ./plugins ./config 目录并写入 AIRFLOW_UID=$(id -u) 到 .env,然后 docker compose up -d,初始化完成后访问 8080 端口即可。这是官方推荐的本地生产模拟环境。
部署方式二:Celery / Kubernetes 分布式集群。 生产主力方案是 CeleryExecutor:PostgreSQL 存元数据、Redis/RabbitMQ 做消息队列、多台 Worker 机消费任务,2.2+ 可同时运行多个 Scheduler 实现高可用(多个调度器实例通过元数据库协调,避免重复调度)。需要弹性伸缩时改用 KubernetesExecutor,按任务粒度拉起 Pod。关键运维点是 DAG 文件必须同步到所有 scheduler/webserver 节点(共享存储或打入镜像),否则会出现“任务在执行却找不到 DAG 定义”的问题。
可观测性。 三件套组合:任务运行状态看 Airflow UI(Grid 视图 + SLA 统计);Celery 队列状态用 Flower 监控;指标接入 Prometheus/Grafana 需要配置 statsd 输出(官方 Helm Chart 提供 statsd-exporter 选项)。日志建议统一收集到 ELK/Loki,便于跨节点检索;失败告警可用内置邮件通知,或通过自定义 on_failure_callback 接入钉钉/企业微信/Slack。
<p class="para-label">避坑清单:</p>
<ul class="dash-list"><li>包名陷阱:PyPI 上存在名为 airflow 的第三方包,安装它不会得到官方 Airflow;正确命令是 pip install apache-airflow。</li><li>时区与 start_date:默认采用 UTC,start_date 设为未来日期会导致 DAG 一直不触发;生产应显式配置 default_timezone,并按业务时区核对调度时间。</li><li>多节点文件同步:DAG 文件必须同步到所有 scheduler/webserver 节点(共享存储或镜像打包),否则任务执行时报 DAG missing。</li><li>大数据慎用 XCom:默认 XCom 存数据库,传大对象会撑爆元数据库;大数据应写入对象存储并在 XCom 中传路径。</li><li>安装/升级不用 constraints:Airflow 依赖面大,直接 pip install 极易版本冲突,官方强烈建议用约束文件锁定版本。</li></ul>
| 维度 | Airflow | Dagster | Prefect | Luigi |
|---|---|---|---|---|
| 定位 | 通用批处理工作流编排事实标准 | 数据资产为中心的编排引擎 | 现代轻量云优先工作流编排 | 历史悠久的轻量管道库 |
| 编排范式 | Python 定义 DAG,面向任务调度 | 面向数据资产(Assets),任务与产出物绑定 | 动态流程 Flow,支持运行时动态任务 | Python 依赖图,偏脚本化 |
| 类型约束 | 弱约束,任务经 XCom/外部存储传数据 | 强类型资产依赖,自动追踪血缘 | 中等约束,状态由 Prefect 托管 | 弱约束,以文件传递为主 |
| 学习曲线 | 中高(概念多:Executor/Sensor/Triggerer) | 中(资产模型需转变思维) | 低(几分钟可上手) | 低 |
| 生态集成 | 80+ Provider 包,覆盖主流数据系统 | 集成广泛,对 dbt/Spark 支持好 | SaaS 集成丰富,云服务优先 | 偏 Hadoop/批处理时代,维护缓慢 |
| 生产部署 | 自部署:Celery/K8s/官方 Helm Chart | 自部署为主(Dagster Cloud 收费) | 自托管或 Prefect Cloud | 单进程,无高可用设计 |
| License | Apache 2.0 | Apache 2.0 | Apache 2.0 | Apache 2.0 |
| 适合谁 | 企业数据团队,需要稳定成熟大生态 | 重视数据治理与血缘的团队 | 小团队快速搭建、云原生环境 | 老项目维护、最小依赖场景 |
选型建议:已有 Hadoop/数仓体系、需要稳定调度大量批处理任务的组织首选 Airflow,生态与社区最成熟;对数据血缘、资产治理要求高选 Dagster;追求快速上手、业务在云上的小团队选 Prefect;Luigi 不建议新项目采用,仅适合维护存量。
版本迭代
Airflow 从 2.0 起全面重写调度器,主线是“稳定性优先 + 渐进式现代化”。2.6 引入多时区调度,2.7 将多 Scheduler 高可用变为默认行为,2.8–2.9 强化数据感知调度(Datasets 与 Object Storage),2.10 将新版 UI 设为默认并引入 DAG 版本化,整体向声明式与云原生演进,为 3.0 铺路(截至训练数据,可能已有更新版本)。
| 版本 | 时间 | 变化 | 提升 |
|---|---|---|---|
| 2.6.0 | 2023-04 | 调度时区从固定 UTC 扩展为可配置 | 支持业务本地时区调度,解决跨国定时偏移 |
| 2.7.0 | 2023-08 | 多 Scheduler 高可用成为默认行为 | 移除 standalone 开关,多调度器协同开箱即用 |
| 2.8.0 | 2024-01 | 引入 Object Storage 抽象;Datasets 支持别名 | 统一 S3/GCS/本地文件操作接口 |
| 2.9.0 | 2024-04 | 推出 Airflow Configs(Pydantic 配置模型) | 配置可校验与自动补全;Datasets 支持条件表达式 |
| 2.10.0 | 2024-08 | 新版 UI 默认启用;DAG 版本化;Datasets 有效期 | DAG 版本历史可追溯,数据集过期自动停止触发 |
| 2.10.5 | 2025-02 | 2.x 系列收尾维护版 | 安全与稳定性修复,生产环境锁定版本推荐 |
Airflow 无 MMLU 类公开评测基准,各版本差异体现在功能与稳定性而非跑分。2.10.x 是 2.x 系列终点,生产建议锁定该系列并关注官方 3.0 预览版;若计划长期运维,应在 3.0 正式发布并出 1–2 个补丁版后再规划迁移。
AI 应用场景
RAG 知识库的定时增量更新管道
阶段:RAG 管道构建 / 文档智能
解决的问题:企业知识库需要定时抓取文档源、清洗、分块、向量化并写入向量数据库,人工跑脚本容易漏跑且失败无感知。Airflow 用 DAG 声明“检测新文档 → 去重清洗 → 分块 embedding → 写入向量库 → 发送通知”的依赖链,任何一步失败自动按配置重试并告警。
具体案例:客服机器人团队用 Airflow 调度每日凌晨的知识库更新:用 Sensor 等待上游文档落盘,用 PythonOperator 调用 embedding 服务,用专用 Provider 写入向量库。相比人工定时跑脚本,失败重试与告警自动完成,运维从每天人工盯守变为只看异常通知。
LLM 批量推理与模型再训练编排
阶段:模型训练与推理编排(MLOps)
解决的问题:模型训练链路包含数据校验、训练、评估、注册、部署多个阶段,阶段间有条件分支与人工审批。Airflow 用 BranchPythonOperator 做条件分支(评估不达标走告警分支),用 TriggerDagRunOperator 跨 DAG 串联“训练”与“部署”两条管道。
具体案例:某推荐团队每周模型重训管道:数据版本校验失败自动触发告警分支,训练成功且评估通过才注册模型并部署到推理服务。管道化后每周训练流程的人工介入次数从 3-4 次降到 0-1 次,训练产物与运行日志全程留痕可回溯。
特征工程与批式特征服务更新
阶段:特征平台建设 / 批式特征计算
解决的问题:在线推理依赖离线特征表,特征计算任务数量多、依赖关系复杂(上游表产出后才能算下游特征)。Airflow 按业务时区每日定时运行特征管道,产出后自动登记到特征仓库并用 Datasets 触发下游训练集拼接。
具体案例:特征管道按依赖关系分层定义:基础表加工 → 特征聚合 → 特征质量校验 → 发布到在线存储。任一上游失败时下游自动等待,杜绝“上游未完成下游先跑”导致的脏特征;配合 SLA 设置,超出预期时长自动告警。
常见误区
误区Airflow 不是自带数据分析引擎吗?把 DAG 写好它就能帮我做聚合、跑机器学习?
正解Airflow 是“编排”层而非“计算”层,官方定位是 programmatically author, schedule, and monitor workflows(用代码编写、调度并监控工作流)。实际计算由任务内部调用的 Spark、SQL、Pandas、外部服务完成;Airflow 只负责触发顺序、重试、告警与可视化。你的 Python 函数跑得慢,换成 Airflow 也不会变快。
为何常见:教程里常在 PythonOperator 中直接写 pandas 处理,看起来像“Airflow 在算”,实际是 Airflow 启了一个 Python 进程执行你的函数。
误区任务 A 算出一个 DataFrame,直接把整个对象塞进 XCom 传给任务 B,很省事。
正解XCom 默认存储在 Airflow 元数据库中,设计用途是传递小体积元数据(文件路径、状态值、临时 ID)。传大对象会撑爆数据库、拖慢调度器。官方最佳实践是:大数据写入对象存储/共享文件系统,XCom 只传路径或引用。
为何常见:初学者看到 xcom_push 接口什么都能传,就把它当成任务间共享内存;没意识到底层是数据库存储。
误区用元数据驱动批量生成几百个相似 DAG,代码省了,效率高。
正解官方 Best Practices 明确反对过度动态化。DAG 文件会被调度器反复解析,动态生成导致解析变慢、UI 上出现大量重复 DAG、出错时难以排查。正确做法是:结构相似的任务收敛到一个 DAG 中,用 TaskGroup、动态 Task Mapping(2.3+)或参数化模板处理差异。
为何常见:想消灭重复代码是本能,但 DAG 是“配置与代码的混合体”,过度抽象会牺牲可观测性与可调试性。
误区Datasets 数据触发看起来像事件驱动,那 Kafka 消息来了 Airflow 也能实时处理吧?
正解Airflow 面向批处理与准实时编排:调度器周期性轮询 DAG 目录与数据状态,分钟级是常见精度,不适合毫秒/秒级流式响应。流式场景应使用 Flink、Kafka Streams、Spark Streaming 做实时计算,Airflow 负责周期性的批处理部分。
为何常见:Datasets 触发机制让“上游产出数据在下游立即运行”看起来很实时,但底层仍是轮询扫描,而非流式推送。
误区把修改后的 DAG 文件传上去,马上刷新页面就能看到新逻辑在跑。
正解调度器周期性扫描 dags 目录(默认分钟级),新文件或修改需要等到下个扫描周期才被重新解析;在分布式部署中,文件还必须同步到所有 scheduler/webserver 节点。排查“改了没生效”时,先确认文件已同步、再确认解析周期,必要时重启 scheduler 强制加载。
为何常见:本地开发时文件在本地路径下即时生效,容易忽略“多节点同步 + 周期扫描”这两个生产环节。
面试题
Q1. Airflow 中被调度器解析、用于描述任务依赖关系的基本结构是?
- A.单个任务 Task
- B.被安排的任务队列
- C.描述依赖图的 DAG← 正确答案
- D.执行任务的 Worker
答案:C。DAG(有向无环图)是 Airflow 调度的基本结构,包含任务节点与依赖边;Task 只是 DAG 内部的单个执行单元,队列和 Worker 属于执行层概念。
Q2. 通过 pip 安装 Airflow 的正确命令是?
- A.pip install airflow
- B.pip install apache-airflow← 正确答案
- C.pip install apache_airflow
- D.pip install air-flow
答案:B。PyPI 上名为 airflow 的包是第三方同名包,不是官方产物;官方包名固定为 apache-airflow。装错包是 Airflow 入门最常见的坑。
Q3. 关于 Airflow 的核心组件,下列说法正确的是?
- A.Scheduler 负责任务调度与状态管理← 正确答案
- B.Web Server 提供操作界面← 正确答案
- C.Executor 决定任务在哪里执行← 正确答案
- D.Triggerer 负责所有任务的实际运行
答案:ABC。调度器负责依赖判断与状态推进,Web Server 提供 UI 与 REST API,执行器决定执行位置。Triggerer 只服务于 Deferred Task 的异步等待,不负责常规任务运行。
Q4. Airflow 中任务间交换小规模数据(如下游要用的文件路径)的官方机制是?
- A.Variable 全局变量配置
- B.XCom 任务间数据交换← 正确答案
- C.Hook 外部系统连接
- D.Connection 数据库连接配置
答案:B。XCom 专用于任务间交换数据,默认存在元数据库中,适合小体积元数据;Variable 是全局配置项,不适合任务间通信;Hook 与 Connection 管理外部系统连接。
Q5. DAG 参数 catchup=False 的含义是?
- A.禁止任务手动触发
- B.跳过历史积压调度← 正确答案
- C.停止系统的定时调度
- D.忽略未完成任务状态
答案:B。catchup=False 表示不执行 start_date 到当前时间之间积压的调度实例,避免 DAG 上线时一次性补跑大量历史任务;它不影响定时调度与手动触发。
Q6. 某任务失败后希望自动重试 3 次、每次间隔 5 分钟,正确的配置是?
- A.retries=3、retry_delay 设为 5 分钟← 正确答案
- B.retry=3、delay=5 分钟
- C.attempts=3、interval 5 分钟
- D.max_retry=3、间隔 5 分钟
答案:A。Airflow 的 BaseOperator 参数为 retries(重试次数)与 retry_delay(重试间隔,timedelta 类型)。其余选项参数名不存在,属于杜撰。
Q7. 下列属于 Airflow 官方 Executor 的是?
- A.Celery 分布式执行器← 正确答案
- B.Kubernetes 执行器← 正确答案
- C.Spark 专用执行器
- D.Local 本地执行器← 正确答案
答案:ABD。LocalExecutor 本机运行、CeleryExecutor 走分布式队列、KubernetesExecutor 按任务拉起 Pod,均为官方内置。Spark 任务通过 SparkSubmitOperator 触发,不存在 SparkExecutor。
Q8. 同一 DAG 内任务 A 产出 2GB 文件需交给任务 B 消费,最佳实践是?
- A.直接塞进 XCom 传递
- B.写入共享存储后传路径← 正确答案
- C.存到元数据库字段
- D.通过 Hook 直接传输
答案:B。XCom 默认落数据库,传 2GB 对象会严重拖慢甚至撑爆元数据库。正确做法是写入 S3/共享文件系统,XCom 只传路径,任务 B 按路径读取。
Q9. 关于 Airflow 2.6+ 的时区与调度,下列说法正确的是?
- A.默认调度时区是 UTC← 正确答案
- B.DAG 可单独设置时区← 正确答案
- C.建议 start_date 设为过去← 正确答案
- D.schedule 仅支持 @daily
答案:ABC。默认时区为 UTC;2.6 起 DAG 可通过 schedule_timezone 单独指定时区;start_date 必须是过去时间,否则 DAG 永远不会触发。schedule 同时支持 cron 表达式与预设别名,D 错误。
Q10. Airflow 2.2+ 引入 Deferred Task 与 Triggerer 组件的主要收益是?
- A.用异步事件代替长轮询,减少空转← 正确答案
- B.替代 Executor 执行所有任务
- C.实现多个 Scheduler 高可用
- D.负责存储 XCom 数据
答案:A。Deferred Task 让传感器任务挂起后释放 Worker 资源,由 Triggerer 等待外部事件,事件满足后再唤醒任务。它优化的是“等待型任务”的资源占用,与多调度器高可用、执行器职责、XCom 存储无关。
参考来源
- webpageApache Airflow 官网项目首页、教程与版本发布入口