Airflow手动触发正常 定时调度时SubDag任务全被跳过的原因
问题现象
DAG手动通过Web UI触发时可正常运行;每日定时调度执行时,所有SubDag都会在60秒后被标记为成功,SubDag内部的所有任务均被跳过。
相关代码片段
主DAG定义
with models.DAG( "MainDag", schedule_interval='@daily', start_date=dates.days_ago(0), user_defined_macros=TEMPLATE_ENV, ) as dag: prepare_factory = SubDagOperator( task_id="prepare_factory ", trigger_rule="one_success", subdag=subdag_prepare_factory.sub_dag( dag.dag_id, "prepare_factory", dag.start_date, dag.schedule_interval ), )
SubDag定义
def sub_dag(parent_dag_name, child_dag_name, start_date, schedule_interval): with models.DAG( "{0}.{1}".format(parent_dag_name, child_dag_name), schedule_interval=schedule_interval, start_date=start_date, user_defined_macros=TEMPLATE_ENV, ) as dag: # 初始化SSH连接钩子 hook = _sshHook.getSshHook() # 定义任务节点 step_1 = ssh_operator.SSHOperator( task_id="step_1", ssh_hook=hook, command="script.sh" )
问题根因
该场景是Airflow SubDag的典型调度冲突问题,触发逻辑如下:
- 你定义的SubDag直接复用了父DAG的
@daily定时调度规则,且和父DAG使用完全一致的start_date,导致SubDag本身也会被Airflow Scheduler独立调度,生成独立的DagRun实例 - 当父DAG按每日定时规则触发执行时,SubDagOperator会等待同execution_date的SubDag实例运行完成。但此时Scheduler已经因为SubDag自身的独立调度,把这个execution_date的SubDag实例标记为成功结束了
- SubDagOperator默认的执行超时时间为60秒,超时后它会判断当前没有运行中、没有失败的SubDag实例,就直接把自身标记为成功,而对应SubDag内部的所有任务因为所属的DagRun已经是完成状态,全部被标记为跳过。
手动从Web UI触发父DAG时,会直接指定唯一的execution_date,不会和SubDag独立调度生成的实例产生冲突,所以手动触发时可以正常运行。
修复方案
- 将SubDag的
schedule_interval设置为None:SubDag不需要独立调度,完全由父DAG的SubDagOperator触发执行,避免独立调度产生的实例冲突 - 独立设置SubDag的
start_date:不要直接复用父DAG的start_date,避免Scheduler计算出的DagRun时间完全重合 - 按实际子任务运行时长,调大SubDagOperator的
execution_timeout参数,避免超时误判 - 长期优化方向:Airflow官方已将SubDagOperator标记为废弃组件,后续可使用TaskGroup替代SubDag实现任务分组,从根源上规避这类调度冲突问题
内容的提问来源于stack exchange,提问作者Double Sept
相关产品推荐
相关产品推荐

