分散実行

ワークフローグラフは 1 つ。ワーカーはあらゆるプラットフォームに。

Dagu の分散モードは、同じシングルバイナリが 2 つの役割を担うだけです。作業をディスパッチするコーディネーターと、それをポーリングするワーカー。Linux、macOS、Windows で dagu worker を起動し、マシンをラベルで記述し、worker_selector で DAG 全体または個々のステップをルーティングします。ワーカーは mTLS で保護された gRPC で外向きに接続するため、ブローカーも共有データベースもワーカー側の受信ポートも不要です。

3 つのプラットフォームを 1 つの夜間グラフに
# nightly-close.yaml
schedule: "0 2 * * *"
max_active_runs: 1

steps:
  # Windows box exports from the line-of-business system
  - id: export_sales
    action: dag.run
    with: { dag: export-sales }
    worker_selector:
      os: windows

  # Linux worker near the data transforms it
  - id: transform
    action: dag.run
    with: { dag: transform-sales }
    worker_selector:
      os: linux
      region: us-east-1
    depends: [export_sales]

  # GPU worker scores the result
  - id: score
    action: dag.run
    with: { dag: score-models }
    worker_selector:
      gpu: "true"
    depends: [transform]

1 つのバイナリがサーバー、コーディネーター、すべてのワーカーになる

ワーカーは Linux、macOS、Windows の amd64 と arm64 で動作

worker_selector が DAG 全体も単一ステップもラベルでルーティング

ワーカーは mTLS で保護された gRPC で外向き接続。NAT やプライベートネットワークでも問題なし

一目で比較

分散 Dagu とブローカー型ワーカースタック

構成要素
Dagu

1 つのバイナリによるコーディネーターとワーカー。ブローカーも結果ストアも不要。

ブローカー型スタック

スケジューラー、ブローカー、結果ストア、ワーカーを別々にデプロイし、別々にアップグレード。

混在 OS フリート
Dagu

Linux、macOS、Windows でネイティブに動くワーカー。

ブローカー型スタック

ワーカーは Linux 前提が多く、Windows は WSL かコンテナ経由。

ルーティング
Dagu

DAG またはステップごとの宣言的な worker_selector ラベル。

ブローカー型スタック

ワーカー設定とタスクコードの両方に配線された名前付きキュー。

ワーカーのネットワーク
Dagu

ワーカーは mTLS で保護された 1 ポートへ外向き接続。

ブローカー型スタック

ワーカーから到達可能なブローカーエンドポイントと共有クレデンシャルが必要。

詳細

それぞれの強みと向き不向き

01

プラットフォームを導入せずにスケールアウトする

分散実行はデプロイ方式の選択であり、書き直しではありません。1 台で動く YAML はそのままフリートで動き、キューはディスパッチ前に並行数を制御し、メインインスタンスに留めるべき DAG は worker_selector: local で自らを固定します。

  • ワーカーはコマンド 1 つ: dagu worker --worker.coordinators=<host>:50055 --worker.labels gpu=true
  • DAG 定義はディスパッチ時に gRPC でワーカーへ送られるため、ワーカーはリポジトリのコピーを持ちません
  • default_execution_mode: distributed で全実行をフリートへ。設定しなければ worker_selector を持つ DAG だけがディスパッチされます
02

ラベルが仕事をルーティングし、マシンは交換可能のまま

ワーカーは自分が何であるかを key-value のラベルで宣言します。DAG は必要なものを worker_selector で宣言します。コーディネーターが両者をマッチングするため、キャパシティの追加は同じラベルのワーカーをもう 1 台起動することであり、ワークフローの編集ではありません。

  • 空のセレクターは任意のワーカーにマッチ。ラベル付きセレクターはすべてのキーの完全一致が必要
  • 余分なラベルを持つワーカーもマッチするため、1 台のマシンが複数のプールを兼任できます
  • dag.run ステップの worker_selector は、そのサブ DAG を親と別のワーカーへ送ります
03

OS とアーキテクチャが混在するフリート

ワーカーは同じ Go バイナリで、Linux、macOS、Windows の amd64 と arm64 向けにリリースされています。同じグラフの中で Windows ワーカーが PowerShell ステップを、Linux ワーカーが bash を実行し、ステータス、ログ、履歴は 1 か所で確認できます。

  • os=windows や arch=arm64 のような規約でラベル付けし、同じセレクターでルーティング
  • shared-nothing モードはログとステータスを gRPC でコーディネーターへストリーミングするため、NFS も共有ボリュームも不要
  • ワーカーは外向きにしか接続しないため、NAT 越し、VPN 上、別クラウドのマシンも参加できます
04

クラウドと Kubernetes に対応

公式 Helm チャートは UI、スケジューラー、コーディネーター、任意のワーカープールを Kubernetes にデプロイします。ワーカーはクラスターの外からも参加できます。VM、ベアメタル、オフィスの Windows ホストでも、境界を越えるトラフィックは mTLS が双方を認証します。

  • helm repo add dagu https://dagucloud.github.io/dagu の後、values を指定して helm install
  • コーディネーターに必要なのは到達可能な host:port 1 つ。Kubernetes Service や内部ロードバランサーで十分
  • コーディネーターはワーカー証明書を、ワーカーはコーディネーターを、mTLS で相互に検証します

FAQ

Dagu を導入する前によくある質問

メッセージブローカーや外部データベースは必要ですか?

不要です。コーディネーターが gRPC でタスクをディスパッチし、ワーカーがポーリングして、同じ接続でハートビート、ステータス、ログを返します。shared-nothing モードでは共有ストレージ自体が不要で、shared-filesystem モードではサーバーが読むボリュームにワーカーが書き込みます。

ワーカーは NAT の内側やプライベートネットワークに置けますか?

置けます。必要な経路はワーカーからコーディネーターへの TCP 1 ポートだけで、コーディネーターがワーカーへ接続を張り返すことはありません。NAT の内側、VPN 上、別クラウドのマシンも、コーディネーターのアドレスへ接続するだけで参加できます。

Windows ワーカーはどう組み込みますか?

同じバイナリをインストールし、os=windows のようなラベルを付けて dagu worker を起動し、Windows 向け DAG に一致する worker_selector を設定します。そのマシンのステップは shell: powershell -NoProfile など設定したシェルで実行され、グラフの残りは別の場所で動きます。

Dagu 全体を Kubernetes で動かせますか?

動かせます。公式 Helm チャートが UI、スケジューラー、コーディネーター、定義したワーカープールの Deployment をレンダリングし、コーディネーターの前段に ClusterIP Service を置きます。クラスター外のワーカーは、公開したイングレスやロードバランサー経由でその Service に接続します。

実行中にワーカーがオフラインになったらどうなりますか?

ワーカーは毎秒ハートビートを送ります。30 秒以上途絶えると、コーディネーターがそのワーカーの実行中タスクを失敗としてマークするため、実行が永遠にハングする代わりに失敗ハンドラーと通知が発火します。

次の一歩

まず 1 つのワークフローから。

Dagu をインストールし、不安定なスクリプトやエージェントタスクを 1 つ YAML に移して、実際の実行履歴を見て判断できます。