Pulumi Databricks リソース プロバイダー
注意
この記事では、Databricks によって提供もサポートもされていない Pulumi について説明します。 プロバイダーに問い合わせるには、Pulumi のサポートをご覧ください。
この記事では、Python と Pulumi を使用する方法について説明します。後者は、使い慣れたプログラミング言語、ツール、エンジニアリング プラクティスを使用して Azure Databricks リソースを作成、デプロイ、管理できる、サードパーティによるコードとしてのインフラストラクチャ (IaC) プラットフォームです。 この記事では、Python と Pulumi Databricks リソース プロバイダーの使用方法について説明しますが、Pulumi では Azure Databricks 用の Python に加えて TypeScript、JavaScript、Go、C# などの他の言語もサポートされています。
Pulumi Databricks リソース プロバイダーは、Databricks Terraform プロバイダーに基づいています。 詳細については、Terraform Cloud のページを参照してください。
必要条件
Pulumi アカウント。 Pulumi アカウントをまだ持っていない場合は、Pulumi にサインアップしてください。 個人向けの Pulumi は無料です。また、チーム向けの無料レベルが用意されています。
Python 3.6 以上。 Python がインストールされているかどうかを確認するには、ターミナルから、または PowerShell を使用してコマンド
python --version
を実行します。 Python をまだインストールしていない場合はインストールします。注意
Python の一部のインストールでは、
python
ではなくpython3
を使用する必要があります。 その場合は、この記事全体を通して、python
をpython3
に置き換えてください。Azure Databricks ワークスペース単位の URL (例:
https://adb-1234567890123456.7.azuredatabricks.net
)Azure Databricks のアクセス資格情報。 Pulumi Databricks プロジェクトは、次の Azure Databricks 認証の種類をサポートしています。
- Azure Databricks 個人用アクセス トークン認証 (
databricks:authType pat
) - Azure マネージド ID 認証 (
databricks:authType azure-msi
) - MS Entra サービス プリンシパルの認証 (
databricks:authType azure-client-secret
) - Azure CLI 認証 (
databricks:authType azure-cli
)
- Azure Databricks 個人用アクセス トークン認証 (
次の手順では、Python を使用して Pulumi Databricks プロジェクトを作成する方法を示します。 それの代わりに、完全にクラウド プロバイダー優先の観点からのチュートリアルについては、Pulumi ドキュメントの「Azure の概要」を参照してください。 または、プログラミング言語優先の観点からのチュートリアルについては、Pulumi ドキュメントの「Python」、「Node.js (JavaScript、TypeScript)」、「Go」、「.NET (C#、VB、F#)」を参照してください。
手順 1: Pulumi プロジェクトを作成する
この手順では、Pulumi プロジェクトに必要なディレクトリ構造をローカル開発マシン上に設定します。 次に、このディレクトリ構造内に Pulumi プロジェクトを作成します。
ターミナルまたは PowerShell で空のディレクトリを作成し、次のようにしてそれに切り替えます。
Unix、Linux、macOS
mkdir pulumi-demo cd pulumi-demo
Windows
md pulumi-demo cd pulumi-demo
オペレーティング システムに応じた次のコマンドを実行して、Pulumi をインストールします。
Unix、Linux
Unix または Linux に Pulumi をインストールするには、curl を使用します。
curl -fsSL https://get.pulumi.com | sh
MacOS
macOS に Pulumi をインストールするには、Homebrew を使用します。
brew install pulumi/tap/pulumi
Windows
Windows に Pulumi をインストールするには、Chocolatey パッケージ マネージャーで、管理者特権のアクセス許可を持つ PowerShell を使用します。
choco install pulumi
Pulumi インストールの代替オプションについては、Pulumi ドキュメントの「ダウンロードとインストール」を参照してください。
次のコマンドを実行して、基本的な Python Pulumi プロジェクトを作成します。
pulumi new python
ヒント
オンラインで Pulumi アカウントから Pulumi プロジェクトを作成することもできます ([プロジェクト] > [プロジェクトの作成])。 ただし、Azure Databricks 用のプロジェクト テンプレートはありません。
メッセージが表示されたら、Enter キーを押し、Web ブラウザーを使用して、まだサインインしていない場合は Pulumi アカウントにオンラインでサインインします。 サインインしたら、ターミナルまたは PowerShell に戻ります。
プロジェクト名の入力を求められたら、Enter キーを押して既定のプロジェクト名である
pulumi-demo
をそのまま使用します。プロジェクトの説明の入力を求められたら、「
A demo Python Pulumi Databricks project
」と入力して Enter キーを押します。スタック名の入力を求められたら、Enter キーを押して既定のスタック名である
dev
をそのまま使用します。 Pulumi で次のファイルとサブディレクトリがpulumi-demo
ディレクトリに作成されます。Pulumi.yaml
は、Pulumi プロジェクトの設定の一覧です。__main__.py
には、Pulumi プロジェクト用に記述する Python コードが含まれます。requirements.txt
は、プロジェクトに対して Pulumi によってインストールされる、サポート対象 Python コード パッケージの一覧です。.gitignore
は、このプロジェクトをリモート Git リポジトリにプッシュする場合に Git で無視されるファイルとディレクトリの一覧です。venv
サブディレクトリには、Pulumi でプロジェクト用に使用されるサポート対象の Python 仮想環境コードが含まれています。
次のコマンドを実行して、プロジェクトの
dev
スタックの最初のデプロイを実行します。pulumi up
この更新の実行を求められたら、上方向キーを押して [yes] (はい) に移動し、Enter キーを押します。
表示された [View Live] (ライブ表示) のリンクをコピーし、Web ブラウザーのアドレス バーに貼り付けると、オンラインで Pulumi アカウントに移動します。
pulumi-demo
プロジェクトについて、dev
スタックのアクティビティ詳細が表示されます。 スタックにはリソースがまだないため、現時点では表示されるものは多くありません。 次の手順でこれらのリソースを作成します。
手順 2: Databricks リソースを作成する
この手順では、Pulumi Databricks リソース プロバイダーを使用して、既存の Azure Databricks ワークスペースにノートブックとそのノートブックを実行するジョブを作成します。
Pulumi で生成された
__main.py__
ファイルで、好みのテキスト エディターまたは統合開発環境 (IDE) を使って次のコードを入力します。 このコードで、Pulumi Databricks の Notebook および Job リソースとその設定を宣言します。"""A Python Pulumi program""" import pulumi from pulumi_databricks import * from base64 import b64encode # Get the authenticated user's workspace home directory path and email address. # See https://www.pulumi.com/registry/packages/databricks/api-docs/getcurrentuser user_home_path = get_current_user().home user_email_address = get_current_user().user_name # Define the name prefix to prepend to the resource names that are created # for the Notebook and Job resources. To do this, you can use a Pulumi # configuration value instead of hard-coding the name prefix in this file. # # To set a Pulumi configuration value, run the following command, which sets # a "resource-prefix" configuration value to "pulumi-demo" in the # associated "Pulumi.<stack-name>.yaml" configuration file: # # pulumi config set resource-prefix "pulumi-demo" # # For more information about defining and retrieving hard-coded values, see # https://www.pulumi.com/docs/intro/concepts/config config = pulumi.config.Config() resource_prefix = config.require('resource-prefix') # Define cluster resource settings. node_type = config.require('node-type') # Create a Notebook resource. # See https://www.pulumi.com/registry/packages/databricks/api-docs/notebook # This example adds a single cell to the notebook, which is constructed from # a single base64-encoded string. In practice, you would replace this: # # language = "PYTHON", # content_base64 = b64encode(b"display(spark.range(10))").decode("UTF-8") # # With this: # # source = "path/to/local/my-notebook.py" # # To provide more notebook content easier and faster. Also, the notebook's language # is automatically detected. If you specify a notebook path, be sure that it does # not end in .ipynb, as Pulumi relies on the workspace import API, which doesn't # rely on any specific extensions such as .ipynb in the notebook path. notebook = Notebook( resource_name = f"{resource_prefix}-notebook", path = f"{user_home_path}/Pulumi/{resource_prefix}-notebook.py", language = 'PYTHON', content_base64 = b64encode(b"display(spark.range(10))").decode("UTF-8") ) # Export the URL of the Notebook, so that you can easily browse to it later. # See https://www.pulumi.com/docs/intro/concepts/stack/#outputs pulumi.export('Notebook URL', notebook.url) # Create a Job resource. # See https://www.pulumi.com/registry/packages/databricks/api-docs/job # This job uses the most recent Databricks Runtime long-term support (LTS) # runtime programmatic version ID at the time this article was first published, # which is 14.3.x-scala2.12. You can replace this with a later version. job = Job( resource_name = f"{resource_prefix}-job", name = f"{resource_prefix}-job", tasks = [ JobTaskArgs( task_key = f"{resource_prefix}-task", new_cluster = JobNewClusterArgs( num_workers = 1, spark_version = "14.3.x-scala2.12", node_type_id = node_type ), notebook_task = JobNotebookTaskArgs( notebook_path = f"{user_home_path}/Pulumi/{resource_prefix}-notebook.py" ) ) ], email_notifications = JobEmailNotificationsArgs( on_successes = [ user_email_address ], on_failures = [ user_email_address ] ) ) # Export the URL of the Job, so that you can easily browse to it later. # See https://www.pulumi.com/docs/intro/concepts/stack/#outputs pulumi.export('Job URL', job.url)
次のコマンドを実行して、
resource-prefix
という名前の構成値を定義し、それをハードコーディングされた値pulumi-demo
に設定します。 この構成値が Pulumi で使用されて、ノートブックとジョブに名前が付けられます。pulumi config set resource-prefix "pulumi-demo"
Pulumi で、
__main__.py
ファイルと同じディレクトリにPulumi.dev.yaml
という名前のファイルが作成され、この YAML ファイルに次のコードが追加されます。config: pulumi-demo:resource_prefix: pulumi-demo
構成値を使用すると、コードのモジュール性と再利用性が高まります。 これで、他のユーザーがこの
__main__.py
ファイルを再利用し、__main__.py
ファイルの内容を変更することなくresource_prefix
変数に別の値を定義できるようになりました。次のコマンドを実行して、
node-type
という名前の構成値を定義し、それを次のようにハードコーディングされた値に設定します。 この構成値が Pulumi で使用され、ジョブを実行するクラスターの種類が決定されます。pulumi config set node-type "Standard_D3_v2"
この時点で、
Pulumi.dev.yaml
ファイルの内容は次のようになります。config: pulumi-demo:node-type: Standard_D3_v2 pulumi-demo:resource-prefix: pulumi-demo
Azure Databricks ワークスペースで Pulumi の認証ができるようにするには、関連コマンドを実行して、Azure Databricks 固有の構成値を定義します。 たとえば、Azure Databricks 個人用アクセス トークン認証の場合は、次のコマンドを実行します。 これらのコマンドでは、次のようにします。
<workspace-instance-url>
をワークスペースごとの URL に置き換えます (例:https://adb-1234567890123456.7.azuredatabricks.net
)。<access-token>
は、アクセス トークンの値に置き換えます。--secret
オプションを必ず指定してください。 これにより、セキュリティのベスト プラクティスとしてアクセス トークンを暗号化することを Pulumi に指示します。注意
既定では、Pulumi による値の暗号化には、Pulumi Service によって管理されるスタックごとの暗号化キーと、値ごとの salt が使用されます。 代替の暗号化プロバイダーを使用するには、Pulumi ドキュメントの「シークレット暗号化の構成」を参照してください。
pulumi config set databricks:host "<workspace-instance-url>" pulumi config set databricks:token "<access-token>" --secret
この時点で、
Pulumi.dev.yaml
ファイルの内容は次のようになります。config: databricks:host: <your-workspace-instance-url> databricks:token: secure: <an-encrypted-version-of-your-access-token> pulumi-demo:node-type: Standard_D3_v2 pulumi-demo:resource_prefix: pulumi-demo
別の Azure Databricks 認証の種類を使うには、「要件」を参照してください。 GitHub の Pulumi Databricks リポジトリの「構成」も参照してください。
手順 3: リソースをデプロイする
この手順では、Pulumi Python プロジェクト テンプレート実行の一環として Pulumi によってプロジェクトに提供される、Python 仮想環境をアクティブにします。 この仮想環境は、正しいバージョンの Python、Pulumi、Pulumi Databricks リソース プロバイダーを一緒に使用するのに役立ちます。 用可能な Python 仮想環境フレームワークはいくつかあります。venv、virtualenv、pipenv などです。 この記事と Pulumi Python プロジェクト テンプレートでは.venv
を使用しています。 venv
は既に Python に組み込まれています。 詳細については、「Creating Virtual Environments (仮想環境を作成する)」を参照してください。
オペレーティング システムとシェルの種類に応じた次のコマンドを
pulumi-demo
ディレクトリから実行し、Python 仮想環境をアクティブ化します。プラットフォーム シェル 仮想環境をアクティブ化するコマンド Unix、Linux、macOS bash/zsh source venv/bin/activate
fish source venv/bin/activate.fish
csh/tcsh source venv/bin/activate.csh
PowerShell Core venv/bin/Activate.ps1
Windows cmd.exe venv\Scripts\activate.bat
PowerShell venv\Scripts\Activate.ps1
次のコマンドを実行して、Python パッケージ インデックス (PyPI) から仮想環境に Pulumi Databricks リソース プロバイダーをインストールします。
pip install pulumi-databricks
注意
pip
の一部のインストールでは、pip
ではなくpip3
を使用する必要があります。 その場合は、この記事全体を通して、pip
をpip3
に置き換えてください。次のコマンドを実行して、Pulumi によって作成されるリソースをプレビューします。
pulumi preview
エラーが報告された場合は、修正してからコマンドを再実行します。
Pulumi アカウントで Pulumi によって実行される内容の詳細なレポートをオンラインで表示するには、表示される [View Live] (ライブ表示) のリンクをコピーし、Web ブラウザーのアドレス バーに貼り付けます。
次のコマンドを実行し、リソースを作成して Azure Databricks ワークスペースにデプロイします。
pulumi up
この更新の実行を求められたら、上方向キーを押して [yes] (はい) に移動し、Enter キーを押します。 エラーが報告された場合は、修正してからコマンドを再実行します。
Pulumi アカウントで Pulumi によって実行された内容の詳細なレポートをオンラインで表示するには、表示される [View Live] (ライブ表示) のリンクをコピーし、Web ブラウザーのアドレス バーに貼り付けます。
手順 4: リソースを操作する
この手順では、指定したノートブックを実行するジョブを Azure Databricks ワークスペースで実行します。
- ワークスペースでジョブによって実行されるノートブックを表示するには、表示される [Notebook URL] (ノートブック URL) のリンクをコピーし、Web ブラウザーのアドレス バーに貼り付けます。
- ワークスペースでノートブックを実行するジョブを表示するには、表示される [Job URL] (ジョブ URL) のリンクをコピーし、Web ブラウザーのアドレス バーに貼り付けます。
- ジョブを実行するには、ジョブ ページの [今すぐ実行] ボタンをクリックします。
- ジョブの実行が完了したら、ジョブ実行の結果を表示するには、ジョブ ページの [完了した実行 (過去 60 日間)] の一覧で、[開始時刻] 列の最新の時刻エントリをクリックします。 [出力] ペインには、ノートブックのコードを実行した結果が表示され、1 から 10 までの数値が出力されます。
(省略可能) 手順 5: リソースに変更を加える
省略可能なこの手順では、ノートブックのコードを変更し、変更したノートブックを再デプロイしてから、ジョブを使用して、変更したノートブックを再実行します。
ノートブックを変更しない場合は、「手順 6: クリーンアップする」に進んでください。
__main.py__
ファイルに戻り、次のコード行を変更します。content_base64 = b64encode(b"display(spark.range(10))").decode("UTF-8")
このようにしたら、ファイルを保存します。
content_base64 = b64encode(b''' data = [ { "Category": 'A', "ID": 1, "Value": 121.44 }, { "Category": 'B', "ID": 2, "Value": 300.01 }, { "Category": 'C', "ID": 3, "Value": 10.99 }, { "Category": 'E', "ID": 4, "Value": 33.87} ] df = spark.createDataFrame(data) display(df) ''').decode("UTF-8")
この変更により、数値 1 から 10 ではなく、指定した DataFrame の内容を出力するようにノートブックに指示します。
Note
data
で始まり''').decode("UTF-8")
で終わるコード行が、コード エディターの端に揃っていることを確認します。 そうでないと、Pulumi によってノートブックに追加の空白が挿入され、それが原因で新しい Python コードの実行が失敗する可能性があります。必要に応じて、次のコマンドを実行して、Pulumi によって変更されるリソースをプレビューします。
pulumi preview
エラーが報告された場合は、修正してからコマンドを再実行します。
Pulumi アカウントで Pulumi によって実行される内容の詳細なレポートをオンラインで表示するには、表示される [View Live] (ライブ表示) のリンクをコピーし、Web ブラウザーのアドレス バーに貼り付けます。
次のコマンドを実行して、リソースの変更を Azure Databricks ワークスペースにデプロイします。
pulumi up
この更新の実行を求められたら、上方向キーを押して [yes] (はい) に移動し、Enter キーを押します。 エラーが報告された場合は、修正してからコマンドを再実行します。
Pulumi アカウントで Pulumi によって実行された内容の詳細なレポートをオンラインで表示するには、表示される [View Live] (ライブ表示) のリンクをコピーし、Web ブラウザーのアドレス バーに貼り付けます。
ワークスペースで変更されたノートブックを表示するには、表示される [Notebook URL] (ノートブック URL) のリンクをコピーし、Web ブラウザーのアドレス バーに貼り付けます。
変更されたノートブックでジョブを再実行するには、表示される [Job URL] (ジョブ URL) のリンクをコピーし、Web ブラウザーのアドレス バーに貼り付けます。 次に、ジョブ ページの [今すぐ実行] ボタンをクリックします。
ジョブの実行が完了したら、ジョブ実行の結果を表示するには、ジョブ ページの [完了した実行 (過去 60 日間)] の一覧で、[開始時刻] 列の最新の時刻エントリをクリックします。 [出力] ペインには、ノートブックのコードを実行した結果が表示され、指定した DataFrame の内容が出力されます。
手順 6: クリーンアップする
この手順では、Pulumi に指示をして、Azure Databricks ワークスペースからノートブックとジョブを削除し、Pulumi アカウントから pulumi-demo
プロジェクトとその dev
スタックをオンラインで削除します。
次のコマンドを実行して、Azure Databricks ワークスペースからリソースを削除します。
pulumi destroy
この削除の実行を求められたら、上方向キーを押して [yes] (はい) に移動し、Enter キーを押します。
次のコマンドを実行して、Pulumi の
pulumi-demo
プロジェクトとそのdev
スタックをオンラインの Pulumi アカウントから削除します。pulumi stack rm dev
この削除の実行を求められたら、「
dev
」と入力し、Enter キーを押します。Python 仮想環境
venv
を非アクティブ化するには、次のコマンドを実行します。deactivate
テスト
Pulumi プロジェクトをデプロイする前にテストできます。 Pulumi ドキュメントの Pulumi プログラムのテストを参照してください。
Python ベースの Pulumi プロジェクトの単体テストでは、Python テスト フレームワーク unittest と、Pulumi パッケージの pulumi.runtime 名前空間を使用して単体テストを記述して実行できます。 シミュレートされたリソースに対してテストを実行するには、Pulumi (および Azure Databricks) の呼び出しをモックに置き換えます。 Pulumi ドキュメントの Pulumi プログラムの単体テストを参照してください。
infra.py
という名前の次のファイル例は、この記事の main.py
ファイルで宣言されているノートブックとジョブの実装をモックします。 この例の単体テストでは、ノートブックの Base64 でエンコードされたコンテンツ、ジョブの名前、成功したジョブ実行のメール受信者が、すべて期待値を返すかどうかを確認します。 そのため、ここでは値の例を使用して、関連するプロパティのみをモックします。 また、必要なリソース プロパティ値は、単体テストで使用する予定がない場合でも、常に指定する必要があります。 この例では、これらの必須値はランダムな my-mock-
値に設定され、それらの値はテストされません。
# infra.py
from pulumi_databricks import (
Notebook,
Job,
JobEmailNotificationsArgs
)
notebook = Notebook(
resource_name = 'my-mock-notebook-resource-name',
path = 'my-mock-notebook-path',
content_base64 = 'ZGlzcGxheShzcGFyay5yYW5nZSgxMCkp'
)
job = Job(
resource_name = 'my-mock-job-resource-name',
name = 'pulumi-demo-job',
email_notifications = JobEmailNotificationsArgs(
on_successes = [ 'someone@example.com' ]
)
)
次のファイル例 test_main.py
では、関連するプロパティが期待値を返すかどうかをテストします。
# test_main.py
import pulumi
from pulumi_databricks import *
import unittest
import infra
# Set up mocking.
class MyMocks(pulumi.runtime.Mocks):
def new_resource(self, type_, name, inputs, provider, id_):
return [name + '_id', inputs]
def call(self, token, args, provider):
return {}
pulumi.runtime.set_mocks(MyMocks())
class TestNotebookAndJob(unittest.TestCase):
@pulumi.runtime.test
def test_notebook(self):
def check_notebook_content_base64(args):
content_base64 = args
# Does the notebook's Base64-encoded content match the expected value?
self.assertIn('ZGlzcGxheShzcGFyay5yYW5nZSgxMCkp', content_base64)
# Pass the mocked notebook's content_base64 property value to the test.
return pulumi.Output.all(infra.notebook.content_base64).apply(check_notebook_content_base64)
@pulumi.runtime.test
def test_job(self):
def check_job_name_and_email_onsuccesses(args):
name, email_notifications = args
# Does the job's name match the expected value?
self.assertIn('pulumi-demo-job', name)
# Does the email address for successful job runs match the expected value?
self.assertIn('someone@example.com', email_notifications['on_successes'])
# Pass into the test the mocked job's property values for the job's name
# and the job's email address for successful runs.
return pulumi.Output.all(
infra.job.name,
infra.job.email_notifications
).apply(check_job_name_and_email_onsuccesses)
これらのテストを実行し、テスト結果を表示するには、Pulumi プロジェクトのルート ディレクトリから次のコマンドを実行します。
python -m unittest
実行できるその他の種類のテストについては、Pulumi ドキュメントの次の記事を参照してください。