Databricksでの本番運用では、ノートブック・ジョブ・パイプラインのCI/CDパイプラインによるデプロイ自動化が不可欠です。2024年以降、DatabricksはDatabricks Asset Bundles(DABs)を推奨デプロイ方式として位置づけており、Data Engineer Professional試験でもDABsの構成・GitHub Actions連携・環境分離が出題されます。この記事ではDABsを中心に、DatabricksのCI/CDパイプラインを構築する具体的な手順を解説します。
DatabricksのCI/CDパイプラインは、以下のフローで構成されます。
┌──────────┐ PR/Merge ┌─────────────┐ databricks ┌──────────────┐
│ Git Repo │ ─────────────► │ CI/CD Tool │ ─── CLI ────► │ Databricks │
│ (GitHub) │ │ (GH Actions)│ bundle │ Workspace │
│ │ ◄───────────── │ │ deploy │ │
│ - src/ │ テスト結果 │ - validate │ │ - dev │
│ - tests/ │ │ - pytest │ │ - staging │
│ - bundle │ │ - deploy │ │ - prod │
└──────────┘ └─────────────┘ └──────────────┘databricks bundle deployで環境別にデプロイDABsはDatabricksリソース(ジョブ・DLTパイプライン・MLモデル等)をdatabricks.ymlファイルで宣言的に定義し、CLI一つでデプロイする仕組みです。環境ごとにターゲットを定義し、変数のオーバーライドでdev/staging/prodを切り替えます。
bundle:
name: sales-etl-pipeline
workspace:
host: https://adb-xxxx.azuredatabricks.net
variables:
catalog:
default: dev_catalog
warehouse_id:
default: abc123def456
resources:
jobs:
daily_etl:
name: "daily-sales-etl-${bundle.target}"
schedule:
quartz_cron_expression: "0 0 6 * * ?"
timezone_id: "Asia/Tokyo"
tasks:
- task_key: ingest
notebook_task:
notebook_path: ./src/01_ingest.py
existing_cluster_id: ${var.cluster_id}
- task_key: transform
depends_on:
- task_key: ingest
notebook_task:
notebook_path: ./src/02_transform.py
existing_cluster_id: ${var.cluster_id}
- task_key: publish
depends_on:
- task_key: transform
notebook_task:
notebook_path: ./src/03_publish.py
existing_cluster_id: ${var.cluster_id}
pipelines:
dlt_pipeline:
name: "sales-dlt-${bundle.target}"
target: "${var.catalog}.sales"
libraries:
- notebook:
path: ./src/dlt_definitions.py
targets:
dev:
mode: development
default: true
variables:
catalog: dev_catalog
cluster_id: "0123-dev-cluster"
staging:
mode: development
variables:
catalog: staging_catalog
cluster_id: "0456-staging-cluster"
prod:
mode: production
variables:
catalog: prod_catalog
cluster_id: "0789-prod-cluster"
run_as:
service_principal_name: "sp-production-deployer"| コマンド | 目的 |
|---|---|
databricks bundle init | テンプレートからプロジェクト初期化 |
databricks bundle validate | databricks.ymlの構文・参照チェック |
databricks bundle deploy -t dev | 指定ターゲットにリソースをデプロイ |
databricks bundle run -t dev daily_etl | デプロイ済みジョブを即時実行 |
databricks bundle destroy -t dev | デプロイ済みリソースを削除 |
GitHub ActionsでDABsのCI/CDパイプラインを構築するワークフロー例です。
# .github/workflows/databricks-cicd.yml
name: Databricks CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
DATABRICKS_HOST: ${{ secrets.DATABRICKS_HOST }}
DATABRICKS_TOKEN: ${{ secrets.DATABRICKS_TOKEN }}
jobs:
validate-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
pip install databricks-cli pytest databricks-connect==15.4.*
pip install -r requirements.txt
- name: Validate bundle
run: databricks bundle validate -t staging
- name: Run unit tests
run: pytest tests/unit/ -v --junitxml=test-results.xml
- name: Run integration tests (staging)
if: github.event_name == 'pull_request'
run: |
databricks bundle deploy -t staging
databricks bundle run -t staging integration_test_job
databricks bundle destroy -t staging
deploy-production:
needs: validate-and-test
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Install Databricks CLI
run: pip install databricks-cli
- name: Deploy to production
run: databricks bundle deploy -t prod# tests/unit/test_transform.py
from pyspark.sql import SparkSession
from src.transforms import clean_sales_data
def test_clean_sales_data(spark: SparkSession):
"""null値を含む行が除外されることを検証"""
input_df = spark.createDataFrame([
(1, "ProductA", 100.0),
(2, None, 200.0),
(3, "ProductC", None),
], ["id", "product_name", "amount"])
result = clean_sales_data(input_df)
assert result.count() == 1
assert result.first()["product_name"] == "ProductA"
# conftest.py
import pytest
from pyspark.sql import SparkSession
@pytest.fixture(scope="session")
def spark():
return SparkSession.builder \
.master("local[2]") \
.appName("unit-tests") \
.getOrCreate()# テストランナーノートブック
test_notebooks = [
"/Repos/main/project/tests/test_ingest",
"/Repos/main/project/tests/test_transform",
]
results = []
for nb in test_notebooks:
try:
result = dbutils.notebook.run(nb, timeout_seconds=600)
results.append({"notebook": nb, "status": "PASS", "result": result})
except Exception as e:
results.append({"notebook": nb, "status": "FAIL", "error": str(e)})
failed = [r for r in results if r["status"] == "FAIL"]
if failed:
raise Exception(f"{len(failed)} test(s) failed: {failed}")| 項目 | dev | staging | prod |
|---|---|---|---|
| カタログ | dev_catalog | staging_catalog | prod_catalog |
| デプロイ方法 | 手動 / ブランチプッシュ | PRマージ時に自動 | main マージ後に自動 |
| DABs mode | development | development | production |
| 実行ユーザー | 開発者個人 | サービスプリンシパル | サービスプリンシパル |
| データ | サンプルデータ | 本番データのサブセット | 本番データ |
| スケジュール | 手動実行のみ | テスト用スケジュール | 本番スケジュール |
DABsのmode: productionを設定すると、リソースにプレフィックスが付かず、run_asでサービスプリンシパルとして実行されます。mode: developmentではリソース名に[dev ユーザー名]プレフィックスが付き、スケジュールは無効化されます。
Databricks Reposは、ワークスペース内でGitリポジトリのクローン・ブランチ切替・プル・コミットを行う機能です。開発者はRepos上でノートブックを編集し、変更をGitにプッシュしてPRを作成します。
| 項目 | Databricks Asset Bundles | Terraform (databricks provider) |
|---|---|---|
| 管理対象 | ジョブ・DLTパイプライン・ノートブック | ワークスペース・クラスタ・IAM・ジョブ等すべて |
| 定義言語 | YAML(databricks.yml) | HCL(.tf) |
| 状態管理 | ワークスペース側で管理 | terraform.tfstate(S3 / GCS等) |
| 環境切替 | targetsセクションで定義 | workspaces / var files |
| 学習コスト | 低い(YAML + Databricks CLI) | 高い(HCL + Terraform概念) |
| インフラ管理 | 非対応(Databricksリソースのみ) | 対応(VPC・IAM・ストレージ等) |
| 推奨シナリオ | データエンジニア主導のワークロード管理 | プラットフォームチーム主導のインフラ+ワークロード管理 |
CI/CD - Databricks Asset Bundles
問題 1
データエンジニアリングチームがDatabricks Asset Bundlesを使用してCI/CDパイプラインを構築しています。本番環境(prod)へのデプロイで、ジョブをサービスプリンシパルとして実行し、リソース名にプレフィックスを付けないようにするためのdatabricks.ymlの設定として正しいものはどれですか?
正解: B
DABsのtargetsセクションでmode: productionを設定すると、リソース名にプレフィックスが付かず、ジョブスケジュールが有効化されます。さらにrun_asでサービスプリンシパルを指定すると、そのサービスプリンシパルの権限でジョブが実行されます。mode: developmentではリソース名にユーザー名プレフィックスが付き、スケジュールが無効化されるため本番には不適切です。modeはtargetsセクション内で指定します。
Databricks Asset Bundles(DABs)とTerraformのどちらを使うべきですか?
DABsはDatabricksリソース(ジョブ・パイプライン・ノートブック)のデプロイに特化したツールで、databricks.ymlの宣言的構文でリソースを定義し、databricks bundle deployコマンドで環境別にデプロイできます。TerraformはDatabricksに限らずクラウドインフラ全体(VPC・IAM・ストレージ等)を管理するIaCツールです。Databricksのジョブやノートブックだけを管理する場合はDABsが簡潔で学習コストも低く、インフラを含むエンドツーエンドの管理が必要な場合はTerraformが適しています。両者を併用し、インフラはTerraform・ワークロードはDABsという構成も一般的です。
Databricks Repos(Git統合)とDABsの関係は何ですか?
Databricks Reposはワークスペース内でGitリポジトリをクローンし、ノートブックやPythonファイルをブランチ単位で同期する機能です。一方DABsはCI/CDパイプラインからdatabricks CLIを使ってリソースをデプロイする仕組みです。Reposはインタラクティブな開発フロー(ブランチ切替・プルリクエストレビュー)に適し、DABsは自動化されたデプロイパイプラインに適しています。開発時はReposでブランチ上のノートブックを編集し、マージ後にDABsでプロダクションにデプロイする組み合わせが推奨パターンです。
CI/CDパイプラインでノートブックのテストはどう実行しますか?
3つのアプローチがあります。(1) dbutils.notebook.run()で対象ノートブックを実行し、戻り値やウィジェットパラメータで結果を検証する方法。(2) ノートブックのロジックをPythonモジュールとして抽出し、GitHub Actions上でpytest実行する方法(SparkSessionのモックまたはDatabricks Connect経由で実行)。(3) Databricks Asset Bundlesのバリデーション機能(databricks bundle validate)でYAMLの構文チェックを行い、その後ステージング環境でジョブを実行してE2Eテストを行う方法です。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Databricks資格一覧|全7試験・難易度・勉強法
Databricks認定資格全7試験の一覧・難易度・出題範囲・合格ラインを徹底解説。2026年最新版の公式試験ガイドに準...
Databricks試験の難易度ランキング|全7資格を徹底比較
Databricks認定全7試験の難易度をランキング形式で徹底比較。合格率・学習時間・出題傾向から難易度を分析。...
Databricks資格の勉強方法|最短合格ルートと学習時間の目安
Databricks認定資格に最短で合格するための勉強方法を完全ガイド。公式リソース・問題集・学習スケジュールを徹底解説...
Databricks Data Engineer Associate完全解説|出題範囲・問題例・合格戦略
Databricks Certified Data Engineer Associate試験を徹底解説。5つの出題ドメイ...
Databricks Data Engineer Professional完全解説|上級試験の攻略法
Databricks Certified Data Engineer Professional試験を徹底解説。10の出題...