Namsang Labs
Radar · #airflow #ai-agent #workflow #open-source

Airflow 3.4.0の主な変更点

· Sangkyoon Nam

青と青緑のグラデーション背景に、字間を広げたRelease Announcement、2つのAirflowロゴ、Apache Airflowの見出し、大きなバージョン番号3.4.0を配置した画像

Apache Airflow & Apache Magpie Meetupでの発表を準備している間に、Airflow 3.4.0のリリースを知った。商品カタログの情報を補うパイプラインにLLMを組み込んでいるところだったので、繰り返し実行とモデル呼び出しの記録に関する変更がまず目に留まった。

今回のバージョンでは、ワークフローの書き方と運用の両方が変わった。タスクグループを条件に応じて繰り返すTask Loopsが加わり、Python以外にもTypeScript、Java、GoでDAG全体を書けるようになった。YAMLによるDAGの宣言やフォルダ単位の一覧表示も追加された一方で、Assetイベントの処理など、既存の実行に影響するデフォルト値も変わっている。公式発表とバージョン別のドキュメントをもとに、主な変更点を整理してみた。

#主な変更点の一覧

分野3.4.0の変更変わる作業
繰り返し実行Task Loops前回の結果を渡しながらタスクグループを繰り返し、反復ごとの実行履歴を確認する。
DAG作成Dag ImporterとSDKスケジュール、タスク、依存関係を含むDAG全体をTypeScript、Java、Goで書く。YAMLによる宣言にも対応する。
一覧と実行画面Foldersと反復別の画面バンドルのフォルダ構造からDAGを探し、ループの各反復を確認する。
AIの実行記録AI ModelタブCommon AI providerが記録したモデル名、トークン使用量、推定コストを確認する。
イベント処理Assetイベント別の実行単一のAssetとOR条件では、デフォルトでイベントごとにDAG実行を一つ作る。
実行の一時停止draining状態新たな自動実行を止め、既存の実行が終わってから一時停止する。

表のAI実行記録は、Airflow本体とは別にリリースされるCommon AI providerに関わる機能だ。@task.llmやエージェントのツール呼び出し、人による承認はすでに提供されており、3.4ではTask Loopsと組み合わせて繰り返し処理を構成できる。providerが提供するAI Modelタブも3.4以降で利用できるため、モデルの呼び出し情報をUIで確認しやすくなった。

#Task Loopsで繰り返しを管理する

APIレスポンスに含まれる次のページのURLをたどったり、検証結果を反映して生成物を修正したりする場合、実行前に繰り返し回数を決めるのは難しい。Task Loopsを使うと、こうした処理を@task_groupにまとめ、.loop()で繰り返せる。上限回数のmax_iterationsは必須だが、until条件も指定すれば、上限に達する前でも条件が真になった時点で停止する。

生成とレビューを繰り返す処理なら、次の図のようになる。最初のレビュー結果を次の生成の入力に反映し、2回目のレビューで終了条件を満たす例だ。Airflowには反復ごとにタスクの状態とログが残るので、各段階で何が起きたのかを個別に確認できる。

1回目の反復 生成 レビュー 終了判定 修正が必要 渡す 判定 1回目のタスク状態、ログ、終了判定の理由を記録する。 継続: レビュー結果を次の入力に渡す。 2回目の反復 修正して生成 レビュー 終了判定 条件を満たす 渡す 判定 終了 後続の処理 2回目のタスク状態、ログ、終了判定の理由を記録する。 2回目で終了条件を満たす例。反復回数の上限は別途指定する。
Task Loopsは前回の結果を次の反復に渡し、反復ごとの実行履歴を残す。

ループ本体を実行してから終了条件を調べるため、処理は必ず1回以上実行される。2回目以降は、タスク内でloop.previousから前回の結果を読み、終了条件ではloop.resultで今回の結果を確認する。Airflowは、この判断で次の反復が必要になったときだけタスクインスタンスを作る。DAGの依存関係に循環を加えず、実行時に繰り返しを管理する仕組みだ。

条件で停止するループと回数だけを指定したループでは、上限に達したときの扱いも異なる。until条件を満たせなければ、最後の終了判定タスクは失敗する。回数だけを指定した場合は、その回数の実行を終えて正常に完了する。終了条件からLoopDecisionを返すと判断理由も記録でき、実行画面で継続や停止の理由を確認できる。

前回の結果を次の処理に反映する繰り返しは、リトライや動的タスクマッピングとは目的が異なる。必要な動作に応じて、次のように使い分けられる。

必要な動作使用する機能
一時的に失敗したAPI呼び出しをやり直す。タスクのリトライ
すでに取得した商品リストの各項目を処理する。動的タスクマッピング
レビュー結果を次の入力に反映して処理を続ける。Task Loops

各反復は順番に進むが、一つの反復内にある独立したタスクは並列実行や動的マッピングができる。ただし、ループの入れ子、マッピングされたタスクグループ内のループ、ループ全体の動的マッピングには対応していない。たとえば、商品リストの各項目に生成とレビューのループを一つずつ割り当てる構成は、まだ作れない。

#TypeScript、Java、GoでDAG全体を書く

Airflow 3.3で導入されたJavaとGoのSDKは、Pythonで宣言したDAGの個々のタスクを別の言語で実装するためのものだった。3.4では対象がDAG全体に広がり、実行スケジュール、タスク定義、タスク間の依存関係をTypeScript、Java、Goで書けるようになった。この構成では、DAGを宣言するためのPythonファイルを別途書く必要がない。

たとえば、Javaでデータを読み込み、加工して保存するパイプラインなら、各処理の実装だけでなく、毎日いつ実行するか、どの順番でつなぐかもJavaコードで定義する。タスクグループや条件分岐もSDKで表現できる。既存のサービスとワークフローを同じ言語で管理したいチームには便利な変更だ。Airflow Beyond Pythonの発表でも、チームごとに異なる言語で書いたDAGを一つのAirflowで運用する構成が紹介されていた。

こうして書いたDAGをAirflowにつなぐ基盤がDag Importerだ。Pythonファイル以外の形式も読み込めるようにする拡張ポイントで、各言語のSDKやYAML importerがこの仕組みを使う。

DAGバンドル内の定義 DAGプロセッサが読み込む Python .pyファイル TypeScript, Java, Go 言語SDKの成果物 YAML スキーマ指定の.yamlファイル Python importer PythonファイルからDAGを収集 言語別importerと実行環境 成果物を実行しDAG定義を取得 YAML importer 別途登録し、検証して変換 読み込む 読み込む 読み込む DAGを登録する Airflow スケジュールと依存関係 UIで実行状態を確認 DAG定義を読み込む流れ。タスク実行には言語別の実行環境とキュー設定も必要。
Dag Importerは異なる形式の定義を読み込み、Airflowで管理するDAGにする。

デプロイ時には、各SDKで作った成果物をDAGバンドルに配置する。DAGプロセッサは成果物を実行してDAG定義を読み取り、スケジューラとUIはPythonのDAGと同様に管理する。配置するファイルと必要な実行環境は言語によって異なる。

言語DAGバンドルに配置するファイルDAGプロセッサとワーカーに必要な環境
TypeScript依存関係をまとめた.min.mjsファイルNode.js 22以降
Java依存関係を含むJARファイルJavaランタイム
Go対象のOSとCPU向けにビルドした実行ファイル別途Goランタイムは不要

ファイルを配置した後は、言語ごとの実行を担当するコーディネータを登録し、DAGのタスクキューをそのコーディネータに関連付ける。この設定はDAGプロセッサとワーカーの両方に必要だ。記述言語が変わってもスケジュールや状態はAirflowが管理し、コードの読み込みとタスク実行に必要な環境は別途用意する構成になる。

コードの代わりに設定ファイルでDAGを宣言したい場合は、YAMLを選べる。スケジュールと依存関係をYAMLに書き、Pythonのオペレータを指定したり、コードタスクをつないだりする方式だ。YAML定義自体にビルドは不要だが、importerは別途登録する必要がある。Dag Importerと各言語のSDKは3.4.0のリリースノートで実験的機能とされているため、導入時にはAPIが変わる可能性も考慮したい。

#DAGの一覧と実行画面が変わる

DAGの記述方法が増えたのに合わせて、画面からもソースや実行の流れをたどりやすくなった。DAG一覧に加わったFoldersパネルは、バンドル内のディレクトリ構造を表示する。フォルダを選ぶと、そのパスにあるDAGだけに一覧が絞り込まれるため、DAGが多くてもフォルダをたどって探せる。

Airflow 3.4.0のDAG Foldersパネル。左側のフォルダツリーでパスを選び、DAG一覧を絞り込む。

画面の出典: Apache Airflow 3.4.0公式発表。

個々のDAGを開くと、コード画面でその言語のソースを確認できる。Task Loopsには反復ごとの実行履歴とタスク履歴を見る画面が加わり、何回目の反復で失敗したのかを調べやすくなった。終了条件に判断理由を記録していれば、次の反復に進んだ理由も確認できる。

Common AI providerのLLMタスクとエージェントタスクには、AI Modelタブが用意されている。Airflow 3.4以降で使えるこのタブには、モデル名、トークン使用量、推定コストが表示される。値はXComに残っている直近の試行の使用量であり、すべてのリトライや反復のコストを合算したものではない。個々のモデル呼び出しやツール実行まで追跡したければ、providerのOpenTelemetry連携を使える。この計測機能は実験的機能だ。

進行中の処理を終えてからDAGを一時停止するdraining状態も追加された。この状態では、新たな定期実行やAssetを契機とする実行は作らず、すでにキューに入っている実行や実行中のDAGは処理を続ける。残りの実行が終わると自動的にpausedになるが、draining中もユーザーが明示的に要求した実行は許可される。

#Assetの処理とアップグレードへの影響

運用中のDAGをアップグレードするときは、まずAssetイベントの処理単位を確認したい。AssetはDAGが生成したり待ち受けたりするデータリソースを表し、その更新イベントを別のDAGの実行条件に使える。3.4では、単一のAssetやOR条件で蓄積したイベントをまとめて処理するデフォルト動作が、イベントごとにDAG実行を作る方式に変わった。一つのAssetにイベントが三つたまれば、デフォルトでは実行も三つ作られる。

従来どおりまとめて処理したい場合は、timetableまたはスケジューラの設定でbatch_asset_events=Trueを指定し、DAGを再パースする必要がある。複数のAssetをすべて待つAND条件などはバッチ処理のデフォルトを維持するため、使用中のスケジュール条件によって影響が異なる。

実行環境や保存方式にも変更があるので、アップグレード前に自分たちの構成と照合しておきたい。3.4.0のリリースノートから、主な互換性の変更を抜き出した。

項目変更点アップグレード時に確認すること
Python3.10のサポート終了、3.11〜3.14に対応実行環境と依存パッケージ
PostgreSQLメタデータDBのデフォルトドライバをpsycopg3に変更接続文字列とドライバ固有の設定
コンテナDebian 13とDocker Hardened Imagesをベースに使用システムパッケージを追加したカスタムイメージ
タスクのクリア個々のタスクをclearすると、デフォルトでは状態ストアの記録も削除状態を残すならkeep_task_state=Trueを指定する。自動リトライは従来どおり状態を保持する。
XComバックエンドループの反復を区別する保存インターフェースを追加カスタムバックエンドのstore_value対応。common.ioのオブジェクトストレージバックエンドは1.11.0以降が必要。
ダウングレード新しいXComはxcom_v2に保存3.4より前に戻す際はデータのコピーが必要なため、復旧にかかる時間を検証する。

今回の更新で、準備中の商品カタログ補強の実験にも、追加で確認したい点が増えた。実験環境を3.4.0に上げて細かな動作を一つずつ確認し、発表で扱うパイプラインに影響する変更もテストするつもりだ。検証結果を次の反復に渡す部分はTask Loopsで構成し、現在の方式と実行記録がどう変わるかを比較したい。

Astronomerでも12月10日にWhat’s New in Apache Airflow 3.4のウェビナーが予定されている。実際に使って確かめた結果と、その後のウェビナーで得た内容は、別の記事にまとめるつもりだ。

#参考資料

Share this post