手動デプロイから脱却!Databricks Asset Bundlesでdbt + Autoloaderジョブをコード管理する

今回の記事は、Databricks Asset Bundles(以下DAB)を用いたデータパイプラインのデプロイ管理についてご紹介します。DABは、Databricks上のジョブやNotebookなどのリソースをYAMLファイルで定義し、コマンド一つでデプロイできる仕組みです。私たちのチームでは、dbtによるデータモデリングとAutoLoaderによるCSV取り込みを組み合わせたパイプラインの管理にDABを活用しています。

導入の背景

Databricks上でデータパイプラインを構築していると、ジョブの設定やNotebookのデプロイが手作業になりがちです。開発環境で動作確認したジョブ設定を本番環境に反映するたびに、UIで同じ操作を繰り返す。設定の差分が把握できず、意図しない変更が混入する。こうした課題を抱えているチームは少なくないのではないでしょうか。

私たちのチームでも同様の課題がありました。DABを導入することで、ジョブの定義から環境ごとの設定、権限管理までをすべてコードで管理できるようになり、手動デプロイから脱却することができました。

前提条件

DABを利用するには、Databricks CLI(v0.200以上)が必要です。インストール後、~/.databrickscfg に認証情報を設定します。

; 個人の開発用プロファイル
[DEFAULT]
host = https://xxx.cloud.databricks.com 
token = dapi_xxxxx

; CI/CD用のサービスプリンシパル
[cicd_sp] 
host = https://xxx.cloud.databricks.com 
client_id = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 
client_secret = dosexxxxxxxxxx

個人開発時は DEFAULT プロファイル、GitHub ActionsなどのCI/CDではサービスプリンシパルのプロファイルを使い分けることで、権限を適切に分離できます。

プロジェクト構成

全体のディレクトリ構成は以下のとおりです。

project-root/
├── databricks.yml           # DABのメイン設定ファイル
├── databricks/
│   ├── resources/            # ジョブ定義YAML
│   │   ├── schedule-job.yml
│   │   └── file-arrival-job.yml
│   └── src/                  # AutoLoader用Notebook
│       └── main.ipynb
└── dbt/                      # dbtプロジェクト
    ├── dbt_project.yml
    └── models/

DABの設定ファイル(databricks.yml)を頂点に、ジョブ定義・Notebook・dbtプロジェクトが一つのリポジトリにまとまっています。これにより、インフラ定義とロジックをセットでバージョン管理できます。

databricks.ymlの設定

databricks.yml はDABの中核となる設定ファイルです。主に以下の要素を定義します。

同期対象の制御sync ブロックでワークスペースに同期するファイルを制御します。.git やログなど不要なファイルを除外し、必要なソースだけをデプロイ対象にできます。また include でジョブ定義YAMLを明示的に読み込みます。

変数定義:Notebookのパスやdbtプロジェクトのディレクトリ、SQLウェアハウスのIDなどを変数として定義します。環境ごとに値を切り替えたい項目(ウェアハウスID、通知先メールアドレスなど)は、後述のターゲットでオーバーライドします。

ターゲット(環境定義)targets で dev / stg / prd の各環境を定義します。ターゲットごとに mode(development / production)、デプロイ先のワークスペース、ジョブの実行者(サービスプリンシパル)、アクセス権限、環境固有の変数値を設定できます。

たとえば権限設定では、devではCAN_MANAGE、stgではCAN_RUN、prdではCAN_VIEWと段階的に制限をかけることで、「開発環境では自由に操作でき、本番環境では閲覧のみ」というガバナンスをコードで表現できます。

ジョブ定義YAMLの設定

ジョブの定義は databricks/resources/ 配下のYAMLファイルに記述します。以下は、AutoLoaderでCSVを取り込み、先行ジョブの完了を確認した上でdbtを実行するジョブの例です。

resources:
  jobs:
    daily_batch:
      name: "daily_batch_${bundle.target}"
      description: "日次バッチ: Raw取込 → 依存チェック → dbt変換"
      timeout_seconds: 3600
      schedule:
        quartz_cron_expression: "0 0 9 * * ?"
        timezone_id: "Asia/Tokyo"
        pause_status: ${var.pause_status}
      queue:
        enabled: true
      environments:
        - environment_key: dbt_env
          spec:
            client: "1"
            dependencies:
              - "dbt-databricks>=1.0.0"
      email_notifications:
        on_failure: ${var.notification_emails}

      tasks:
        # ---- 1. AutoLoaderによるRaw取込(並列実行) ----
        - task_key: raw_import
          for_each_task:
            concurrency: 4
            inputs: "[table_a, table_b, table_c, table_d]"
            task:
              task_key: raw_import_each
              notebook_task:
                notebook_path: ${var.autoloader_notebook_path}
                source: WORKSPACE
                base_parameters:
                  table_name: "{{input}}"
                  env: ${var.env}

        # ---- 2. 先行ジョブの完了チェック ----
        - task_key: check_dependency
          depends_on:
            - task_key: raw_import
          notebook_task:
            notebook_path: ${var.dependency_check_notebook_path}
            source: WORKSPACE
            base_parameters:
              job_names: "prior_batch_${bundle.target}"

        # ---- 3. dbtによるデータ変換・テスト ----
        - task_key: transform_dbt
          depends_on:
            - task_key: check_dependency
          environment_key: dbt_env
          dbt_task:
            project_directory: ${var.dbt_project_dir}
            commands:
              - "dbt deps"
              - "dbt build --select tag:daily"
            warehouse_id: ${var.dbt_warehouse_id}
            catalog: "my_catalog_${var.env}"
            schema: "default"

このジョブは3つのタスクで構成されています。

1つ目はAutoLoaderによるRaw取込です。for_each_task を使い、テーブル名のリストを inputs に渡して同じNotebookを並列で実行します。concurrency で並列実行数を制御でき、取り込み対象が増えてもYAMLにテーブル名を追加するだけで対応できます。

2つ目は先行ジョブの完了チェックです。depends_on でRaw取込の完了を待ってから実行されます。異なるジョブ間の依存関係が必要な場合は、先行ジョブの実行ステータスを確認するNotebookをタスクとして挟むことで対応しています。

3つ目はdbtによるデータ変換・テストです。dbt_task でdbtのコマンドを宣言的に記述します。--select tag:daily のようにタグで実行対象を絞ることで、ジョブのスケジュールに合わせたモデルだけを効率的に実行できます。

デプロイの流れ

ABのデプロイは2つのコマンドで完結します。

# 設定の検証(構文エラーや参照の不整合をチェック)
databricks bundle validate -t dev -p cicd_sp

# デプロイ(ワークスペースにリソースを反映)
databricks bundle deploy -t dev -p cicd_sp

t でターゲット(環境)、p で .databrickscfg のプロファイルを指定します。個人開発時は p を省略すれば DEFAULT プロファイルが使われ、CI/CDではサービスプリンシパルのプロファイルを指定する、という使い分けが可能です。環境ごとの変数・権限・実行者が自動的に切り替わるため、UIでの手作業が一切不要になり、デプロイの再現性が確保されます。

まとめ

DABを導入したことで、以下の効果を実感しています。

ジョブの設定変更がYAMLの差分として可視化されるため、Pull Requestでレビューできるようになりました。各環境の構成がコードで管理されることで「本番だけ設定が違う」という事故もなくなります。デプロイは validate → deploy の2コマンドで完結し、手順書も不要になりました。

DABはまだ日本語の情報が多くありませんが、Databricksでデータパイプラインを運用しているチームにとっては、導入を検討する価値のあるツールだと思います。本記事が参考になれば幸いです。

CTA
  • URLをコピーしました!
  • URLをコピーしました!
この記事を書いた人

データドリブンに関するお悩みはまずはSiNCEにご相談ください

目次