概要
Argo 並列実行
同じ steps リスト内に複数エントリを並べると並列実行。staging 3モデルを並列化し18分 → 8分に短縮。
dbt test 品質ゲート
dbt test --select staging を独立ステップとして配置。失敗時は marts へ進まず、重複データのレポート混入を防ぐ。
指数バックオフリトライ
retryStrategy で最大3回・2分〜8分のバックオフ。BigQuery 429/500 エラーを自動吸収。
タイムゾーン修正
timezone: "Asia/Tokyo" に変更するだけで JST 05:00 実行が正しく動く。
問題
毎朝5時に実行される日次販促データパイプラインで以下の問題が発生しています。
| # | 問題 | 影響 |
|---|---|---|
| 1 | staging内の3モデルが独立しているのに直列実行 | 合計約18分かかっている |
| 2 | dbt test が一切実行されていない | 先月 stg_orders に重複レコードが混入し売上数字が2倍に見えるバグが発生 |
| 3 | リトライ設定がない | BQ 429/500 エラーで手動再実行が必要 |
| 4 | タイムゾーンが UTC | JST 5:00実行を意図していたが実際はJST 14:00に実行されている |
要件
- 並列化: staging内の3モデルを並列実行し、全て完了してからmartsを実行
- データ品質ゲート: staging実行後にdbt testを実行し、テスト失敗時はmartsへ進まない
- リトライ設定: 各ステップに最大3回のリトライ(指数バックオフ: 2分〜)
- タイムゾーン修正: JST 05:00に正しく実行されるよう修正
期待する回答形式: 改善後のYAML全文 + 各変更点の説明 + 実務上の注意点
現状の YAML(問題あり)
直列実行・品質ゲートなし・リトライなし・タイムゾーン誤りの4問題が潜んでいます。
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: promo-pipeline-daily
spec:
schedule: "0 5 * * *"
timezone: "UTC" # ← 問題: UTCのためJST 14:00に実行される
workflowSpec:
entrypoint: pipeline
templates:
- name: pipeline
steps:
- - name: extract
template: bq-extract
- - name: transform-a
template: dbt-run-staging # ← 問題: staging全体を1ステップで直列
- - name: transform-b
template: dbt-run-marts # ← 問題: testなしにmartsへ進む
- - name: load-report
template: export-to-gcs
- name: bq-extract
container: # ← 問題: retryStrategyなし
image: gcr.io/project/pipeline:latest
command: [python, extract.py]
- name: dbt-run-staging
container:
image: gcr.io/project/dbt:latest
command: [dbt, run, --select, staging]
- name: dbt-run-marts
container:
image: gcr.io/project/dbt:latest
command: [dbt, run, --select, marts]
- name: export-to-gcs
container:
image: gcr.io/project/pipeline:latest
command: [python, export.py]
ヒント(段階的開示)
ヒント1 — 方向性
Argo Workflowsの
steps は各ステップが「リスト内リスト」構造になっている。同じ階層(同じ - レベル)に並べると並列実行、別の行に並べると直列実行になる。データ品質ゲートは「staging並列グループ → dbt test → marts」という順序で表現できる。
ヒント2 — 並列化の書き方
✗ 直列(各々別リスト)
steps:
- - name: step-a
- - name: step-b # 直列
- - name: step-c # 直列
✓ 並列(同じリスト内)
steps:
- - name: step-a # 同じリスト内
- name: step-b # = 並列実行
- name: step-c # = 並列実行
ヒント3 — リトライ設定とタイムゾーン
retryStrategy:
limit: "3"
retryPolicy: "Always"
backoff:
duration: "2m"
factor: "2"
maxDuration: "10m"
# タイムゾーン修正
schedule: "0 5 * * *"
timezone: "Asia/Tokyo" # JSTのまま書ける
JSTはUTC+9。timezone: "Asia/Tokyo" を指定すれば cron の時刻をJSTで直接書ける。UTCで指定したい場合は "0 20 * * *"(前日UTC 20:00)にする必要がある。
パイプライン構造図 — 改善後のDAGフロー
模範解答(改善後 YAML 全文)
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: promo-pipeline-daily
spec:
schedule: "0 5 * * *"
timezone: "Asia/Tokyo" # 修正①: UTC→Asia/Tokyo でJST 05:00実行
workflowSpec:
entrypoint: pipeline
templates:
# ── メインフロー ──────────────────────────────
- name: pipeline
steps:
# Step1: 抽出(直列)
- - name: extract
template: bq-extract
# Step2: staging 3モデルを並列実行(修正②)
- - name: stg-orders
template: dbt-stg-orders
- name: stg-customers
template: dbt-stg-customers
- name: stg-promotions
template: dbt-stg-promotions
# Step3: データ品質ゲート(修正③)- 失敗したらここで止まる
- - name: quality-gate
template: dbt-test-staging
# Step4: martsはstagingテスト通過後のみ実行
- - name: transform-marts
template: dbt-run-marts
# Step5: レポート出力
- - name: load-report
template: export-to-gcs
# ── 抽出 ─────────────────────────────────────
- name: bq-extract
retryStrategy: # 修正④: 全ステップにリトライ設定
limit: "3"
retryPolicy: "Always"
backoff:
duration: "2m"
factor: "2"
maxDuration: "10m"
container:
image: gcr.io/project/pipeline:latest
command: [python, extract.py]
# ── staging 並列ステップ ───────────────────────
- name: dbt-stg-orders
retryStrategy:
limit: "3"
retryPolicy: "Always"
backoff:
duration: "2m"
factor: "2"
maxDuration: "10m"
container:
image: gcr.io/project/dbt:latest
command: [dbt, run, --select, stg_orders]
- name: dbt-stg-customers
retryStrategy:
limit: "3"
retryPolicy: "Always"
backoff:
duration: "2m"
factor: "2"
maxDuration: "10m"
container:
image: gcr.io/project/dbt:latest
command: [dbt, run, --select, stg_customers]
- name: dbt-stg-promotions
retryStrategy:
limit: "3"
retryPolicy: "Always"
backoff:
duration: "2m"
factor: "2"
maxDuration: "10m"
container:
image: gcr.io/project/dbt:latest
command: [dbt, run, --select, stg_promotions]
# ── データ品質ゲート ──────────────────────────
- name: dbt-test-staging
retryStrategy:
limit: "3"
retryPolicy: "Always"
backoff:
duration: "2m"
factor: "2"
maxDuration: "10m"
container:
image: gcr.io/project/dbt:latest
command: [dbt, test, --select, staging]
# ── marts ─────────────────────────────────────
- name: dbt-run-marts
retryStrategy:
limit: "3"
retryPolicy: "Always"
backoff:
duration: "2m"
factor: "2"
maxDuration: "10m"
container:
image: gcr.io/project/dbt:latest
command: [dbt, run, --select, marts]
# ── レポート出力 ──────────────────────────────
- name: export-to-gcs
retryStrategy:
limit: "3"
retryPolicy: "Always"
backoff:
duration: "2m"
factor: "2"
maxDuration: "10m"
container:
image: gcr.io/project/pipeline:latest
command: [python, export.py]
各変更点の説明
1
タイムゾーン修正
timezone: "UTC" → timezone: "Asia/Tokyo" に変更。schedule: "0 5 * * *" のままで JST 05:00 に実行される。UTCで指定したい場合は "0 20 * * *" にする必要があった。
2
staging 並列化
元は直列3ステップ(約18分)→ 並列実行で最も時間のかかるモデルの時間(仮に8分)まで短縮。Argoの
元は直列3ステップ(約18分)→ 並列実行で最も時間のかかるモデルの時間(仮に8分)まで短縮。Argoの
steps リスト内に複数の - エントリを同レベルで並べることで並列になる。
3
データ品質ゲート追加
dbt test --select staging を独立ステップとして staging後・marts前に配置。dbt test が1件でも失敗するとArgoのステップが非ゼロ終了コードを返し、後続の marts ステップへ進まない。先月の売上2倍バグ(重複レコード混入)は dbt test の unique テストで検知可能だった。
4
リトライ設定
各 template に
各 template に
retryStrategy を追加。limit: "3" で最大3回リトライ、backoff で指数バックオフ(2分→4分→8分)を設定。BigQuery の 429(レートリミット)や 500(一時エラー)はこれで吸収できる。
実務上の注意点:
retryStrategyはWorkflowレベルではなく template レベルに書くことで、ステップごとに異なるポリシーを設定できる- 品質ゲートで失敗した場合、Slack アラート等の通知ステップを
onExitで追加するとインシデント対応が速くなる - dbt Mesh 導入時は
--selectのパス指定がプロジェクトをまたぐため注意
ポイント解説
1
Argo Workflowsの並列/直列制御
steps の各要素(- - で始まる)は直列、同じ - リスト内の複数エントリは並列。DAGテンプレートを使うとより複雑な依存関係をグラフで表現できるが、線形パイプラインには steps で十分。
2
データ品質ゲートの重要性
dbt test をパイプラインに組み込まないと、上流データの問題が下流レポートまで伝播する。
dbt test をパイプラインに組み込まないと、上流データの問題が下流レポートまで伝播する。
not_null / unique / accepted_values / relationships の4テストを staging 全モデルに設定するのが最低ライン。
3
タイムゾーンの罠
Cron のデフォルトは UTC が多い。
Cron のデフォルトは UTC が多い。
timezone フィールドを明示的に設定しないとJSTユーザーが想定外の時刻に実行される。特に深夜バッチでは日付跨ぎのバグにつながる。
4
指数バックオフの設計
duration(初期待機時間)・factor(倍率)・maxDuration(上限)の3パラメータで制御。BigQueryの429エラーはほぼ数分で解消するため、2m→4m→8mは実用的。maxDuration を設定しないとリトライ間隔が際限なく伸びる。
実務への応用
- 毎朝5時の販促効果集計バッチはまさにこの構成で動いている
- staging並列化により、従来18分かかっていた処理が最長ステップ(例: stg_orders 8分)まで短縮 → レポート完成がJST 5:13頃(従来5:23頃)に
- データ品質ゲートに
dbt test --select staging --store-failuresを追加すると、失敗レコードがBigQueryテーブルに保存されデバッグが容易になる - Argo Workflows の
onExitテンプレートにSlack/PagerDuty通知を追加することで、品質ゲート失敗時に即時アラートが飛ぶ
今日のまとめ
Argo Workflows の
特にデータ品質ゲートをパイプラインに組み込むことは、下流レポートへの誤データ伝播を防ぐための最重要実装である。「バグが発生した後で品質テストを追加」ではなく、最初から設計段階で組み込むことが実務の正解。
steps 並列化・dbt test による品質ゲート・リトライ戦略・タイムゾーン設定の4点がデータパイプラインの信頼性と効率性を決定する基本構成要素。特にデータ品質ゲートをパイプラインに組み込むことは、下流レポートへの誤データ伝播を防ぐための最重要実装である。「バグが発生した後で品質テストを追加」ではなく、最初から設計段階で組み込むことが実務の正解。