Airflowのsubdagは注意点多いよ

# 言いたいこと
subdag使うなら注意点多いよ
[Cloud Composer](https://cloud.google.com/composer/docs/how-to/using/writing-dags?hl=ja#creating_dags)とか[Astronomer](https://www.astronomer.io/guides/subdags/)もオススメしないと言っているよ

# subdagとは
複数のタスクをDAGとして切り出して、別のDAGから使える機能です。
公式ドキュメントでいうと、[ここらへんに説明](http://airflow.apache.org/concepts.html?highlight=subdag#subdags)があります。


# いいじゃん

Airlfowサービス提供者いわく「やめとけ」らしいです

* Cloud Composerいわく[「SubDagOperator の使用はおすすめしません」](https://cloud.google.com/composer/docs/how-to/using/writing-dags?hl=ja#creating_dags)
* Astonomerいわく[「Astronomer highly recommends staying away from SubDags」](https://www.astronomer.io/guides/subdags/)

（Airflowを使っているWePayさんも[「We have shied away from using some of Airflow’s more exotic features, such as backfill, subdags」](https://wecode.wepay.com/posts/airflow-wepay)と言っています）


## なんで悪いのか
いろいろ面倒な点があるっぽいです。各々の問題は対処出来るかもしれませんが…

## Executorの問題
（Executor全般については[Astronomerさんの記事](https://www.astronomer.io/guides/airflow-executors-explained/)がわかりやすいです）

SubDagOperatorではExecutorを指定する事が出来ます。
が、SequentialExecutor以外（CeleryExecutorやLocalExecutor）を使うのは危険らしく、公式ドキュメントには
[「it is possible to specify an executor for the SubDAG. It is common to use the SequentialExecutor if you want to run the SubDAG in-process and effectively limit its parallelism to one. Using LocalExecutor can be problematic as it may over-subscribe your worker, running multiple tasks in a single slot」](http://airflow.apache.org/concepts.html?highlight=subdag#subdags)
とあったり、[CeleryExecutorで問題が生じる](https://issues.apache.org/jira/browse/AIRFLOW-74)らしいです。

が、SequentialExecutorだと並列して実行出来ない…
  

## SubDag「Operator」が単一障害点
subdagを使うとSubDagOperator自体のタスクインスタンスも作られます。
Composerはこの点を問題視しており、[「SubDag タスクを実行しているワーカーが終了すると、SubDag 内のすべてのタスクが失敗し、ワークフローの信頼性が低下します」](https://cloud.google.com/composer/docs/how-to/using/writing-dags?hl=ja#creating_dags)と説明しています。

実際、(1)SubDagOperatorを実行、(2)workerに入ってSubDagOperatorのタスクのプロセスを殺すと、下図のように

1. subdag中のタスクインスタンスは成功
2. SubDagOperatorタスクインスタンスは失敗した状態になります。
3. SubDagOperatorのdownstreamのタスクがupstream_failedで未実行

![スクリーンショット 2019-10-22 10.19.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311203/52ec28a4-dbaf-ac28-edba-cd9c685b5c94.png)

![スクリーンショット 2019-10-22 10.19.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311203/e2f59ac2-ae31-eac2-0b6a-d148fa4d8a95.png)



## プール
（この部分は自信ないです…）
SubDagOperatorの[ソースコード](https://github.com/apache/airflow/blob/1.10.2/airflow/operators/subdag_operator.py)に「 Airflow pool is not honored by SubDagOperator」とあるように、subdag+プールの挙動は怪しいです。

例えば、下図はsubdag中でたくさんタスク実行した時のプール状況ですが、Slotsよりも多くのタスクインスタンスが実行(Used Slots)されています。
![スクリーンショット 2019-10-22 9.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311203/8728605e-cc60-719a-ceb0-9c548d447f8d.png)

ソースコード眺めた感じ、

* SubDagOperatorは[BackfillJob](https://github.com/apache/airflow/blob/cb8b2a1dc64c3ea6ba445893c65c6c953dfb476a/airflow/jobs.py#L1774)でタスクインスタンスをキック
* 普通のDAGは[SchedulerJob](https://github.com/apache/airflow/blob/cb8b2a1dc64c3ea6ba445893c65c6c953dfb476a/airflow/jobs.py#L526)でタスクインスタンスをキック
* タスクインスタンスがプールが実行出来るかのチェックは、SchedulerJobでやっており、BackfillJob中ではやっていない？

のが原因ぽいです。


# 補足
この話は2019年10月の時点（Airflow1.10.2以前）の話ですが、少しずつ良くなっていくようです。

例えば、[1.10.2ではSubDagOperatorは単にsubdagを実行するだけ](https://github.com/apache/airflow/blob/1.10.2/airflow/operators/subdag_operator.py)ですが、[masterのコードでは](https://github.com/apache/airflow/blob/master/airflow/operators/subdag_operator.py)subdagが無ければ作り、すでにあればその終了を待ちます。
＝SubDagOperator自体のリトライ時にsubdag内がリトライされず、SubDagOperatorが単一障害点であることの問題が起きにくい