Azure Databricks の MLflow モデル レジストリ Webhook
重要
この機能はパブリック プレビュー段階にあります。
Webhook を使用すると、モデル レジストリ イベントをリッスンし、統合によってアクションが自動的にトリガーされるようにすることができます。 Webhook を使用して、機械学習パイプラインを自動化し、既存の CI/CD ツールおよびワークフローと統合できます。 たとえば、新しいモデル バージョンが作成されたら CI ビルドをトリガーしたり、モデルから運用への切り替えが要求されるたびに Slack を介してチーム メンバーに通知したりできます。
Webhook は、Databricks REST API、または PyPI の Python クライアント databricks-registry-webhooks
を介して利用できます。
注意
Unity Catalog のモデルを使用する場合、Webhook は使用できません。 別の方法については、「イベントでステージ切り替え要求を使用するか、Webhooks をトリガーできますか?」を参照してください。 プライベート エンドポイント (パブリック インターネットからアクセスできないエンドポイント) への Webhook の送信はサポートされていません。
Webhook イベント
次の 1 つまたは複数のイベントが発生したらトリガーするように Webhook を指定できます。
- MODEL_VERSION_CREATED: 関連付けられたモデルの新しいモデル バージョンが作成された。
- MODEL_VERSION_TRANSITIONED_STAGE: モデル バージョンのステージが変更された。
- TRANSITION_REQUEST_CREATED: ユーザーがモデル バージョンの切り替えを要求した。
- COMMENT_CREATED: ユーザーが、登録済みモデルに関するコメントを書き込んだ。
- REGISTERED_MODEL_CREATED: 新しい登録済みモデルが作成された。 このイベントの種類は、レジストリ全体の Webhook に対してのみ指定できます。これは、作成要求にモデル名を指定しないことによって作成できます。
- MODEL_VERSION_TAG_SET: ユーザーが、モデル バージョンにタグを設定した。
- MODEL_VERSION_TRANSITIONED_TO_STAGING: モデル バージョンがステージングに切り替えられた。
- MODEL_VERSION_TRANSITIONED_TO_PRODUCTION: モデル バージョンが運用に切り替えられた。
- MODEL_VERSION_TRANSITIONED_TO_ARCHIVED: モデル バージョンがアーカイブされた。
- TRANSITION_REQUEST_TO_STAGING_CREATED: ユーザーが、モデル バージョンをステージングに切り替えることを要求した。
- TRANSITION_REQUEST_TO_PRODUCTION_CREATED: ユーザーが、モデル バージョンを運用に切り替えることを要求した。
- TRANSITION_REQUEST_TO_ARCHIVED_CREATED: ユーザーが、モデル バージョンをアーカイブすることを要求した。
Webhook の種類
トリガー ターゲットに基づいて 2 種類の Webhook があります。
- HTTP エンドポイントを使用した Webhook (HTTP レジストリ Webhook): トリガーを HTTP エンドポイントに送信します。
- ジョブ トリガーを使用した Webhook (ジョブ レジストリ Webhook): Azure Databricks ワークスペース内でジョブをトリガーします。 ジョブのワークスペースで IP 許可リストが有効になっている場合は、モデル レジストリのワークスペース IP を許可リストに載せる必要があります。 詳細については、「ジョブ レジストリ Webhook の IP 許可リスト」を参照してください。
さらに、アクセス制御の要件が異なる、スコープに基づく 2 種類の Webhook もあります。
- モデル固有の Webhook: この Webhook は、固有の登録済みモデルに適用されます。 モデル固有の Webhook を作成、変更、削除、またはテストするには、登録済みモデルに対して管理可能アクセス許可を持っている必要があります。
- レジストリ全体の Webhook: この Webhook は、新しい登録済みモデルの作成など、ワークスペース内の登録済みモデルでのイベントによってトリガーされます。 レジストリ全体の Webhook を作成するには、作成時に
model_name
フィールドを省略します。 レジストリ全体の Webhook を作成、変更、削除、またはテストするには、ワークスペース管理者の権限を持っている必要があります。
Webhook ペイロード
各イベント トリガーには、Webhook エンドポイントへの送信要求のペイロードに含まれる最小限のフィールドがあります。
- アーティファクト パスの場所などの機密情報は除外されます。 適切な ACL を持つユーザーとプリンシパルは、クライアントまたは REST API を使用して、モデル レジストリに対してこの情報に関するクエリを実行できます。
- ペイロードは暗号化されません。 Azure Databricks が Webhook のソースであることを検証する方法については、「セキュリティ」を参照してください。
text
フィールドにより、Slack の統合が可能になります。 Slack メッセージを送信するには、Slack Webhook エンドポイントを Webhook URL として指定します。
ジョブ レジストリ Webhook ペイロード
ジョブ レジストリ Webhook のペイロードは、ジョブの種類によって異なり、ターゲット ワークスペース内の jobs/run-now
エンドポイントに送信されます。
単一タスク ジョブ
単一タスク ジョブには、タスクの種類に基づいて、3 つのペイロードのいずれかが割り当てられます。
Notebook と Python のホイール ジョブ
Notebook と Python のホイール ジョブには、フィールド event_message
を含んだパラメーター ディクショナリを伴う JSON ペイロードがあります。
{
"job_id": 1234567890,
"notebook_params": {
"event_message": "<Webhook Payload>"
}
}
Python、JAR、Spark の送信ジョブ
Python、JAR、Spark の送信ジョブには、パラメーター リストを含む JSON ペイロードがあります。
{
"job_id": 1234567890,
"python_params": ["<Webhook Payload>"]
}
その他のすべてのジョブ
その他のすべての種類のジョブには、パラメーターのない JSON ペイロードがあります。
{
"job_id": 1234567890
}
マルチタスク ジョブ
マルチタスク ジョブには、さまざまなタスクの種類を説明するために入力されるすべてのパラメーターを含んだ JSON ペイロードがあります。
{
"job_id": 1234567890,
"notebook_params": {
"event_message": "<Webhook Payload>"
},
"python_named_params": {
"event_message": "<Webhook Payload>"
},
"jar_params": ["<Webhook Payload>"],
"python_params": ["<Webhook Payload>"],
"spark_submit_params": ["<Webhook Payload>"]
}
ペイロードの例
イベント: MODEL_VERSION_TRANSITIONED_STAGE
応答
POST
/your/endpoint/for/event/model-versions/stage-transition
--data {
"event": "MODEL_VERSION_TRANSITIONED_STAGE",
"webhook_id": "c5596721253c4b429368cf6f4341b88a",
"event_timestamp": 1589859029343,
"model_name": "Airline_Delay_SparkML",
"version": "8",
"to_stage": "Production",
"from_stage": "None",
"text": "Registered model 'someModel' version 8 transitioned from None to Production."
}
イベント: MODEL_VERSION_TAG_SET
応答
POST
/your/endpoint/for/event/model-versions/tag-set
--data {
"event": "MODEL_VERSION_TAG_SET",
"webhook_id": "8d7fc634e624474f9bbfde960fdf354c",
"event_timestamp": 1589859029343,
"model_name": "Airline_Delay_SparkML",
"version": "8",
"tags": [{"key":"key1","value":"value1"},{"key":"key2","value":"value2"}],
"text": "example@yourdomain.com set version tag(s) 'key1' => 'value1', 'key2' => 'value2' for registered model 'someModel' version 8."
}
イベント: COMMENT_CREATED
応答
POST
/your/endpoint/for/event/comments/create
--data {
"event": "COMMENT_CREATED",
"webhook_id": "8d7fc634e624474f9bbfde960fdf354c",
"event_timestamp": 1589859029343,
"model_name": "Airline_Delay_SparkML",
"version": "8",
"comment": "Raw text content of the comment",
"text": "A user commented on registered model 'someModel' version 8."
}
Security
セキュリティのために、Azure Databricks では、ペイロードから計算されたヘッダーに X-Databricks-Signature が含まれます。また、HMAC with SHA-256 アルゴリズムを使用して Webhook に関連付けられた共有シークレット キーも含まれます。
さらに、Webhook の HttpUrlSpec
に指定することにより、送信要求に標準 Authorization ヘッダーを組み込むことができます。
クライアントの検証
共有シークレットが設定されている場合、ペイロード受信者は、共有シークレットを使用してペイロードを HMAC エンコードし、エンコードした値をヘッダーの X-Databricks-Signature
と比較することによって、HTTP 要求のソースを検証する必要があります。 これは、SSL 証明書の検証が無効になっている (つまり、enable_ssl_verification
フィールドが false
に設定されている) 場合、特に重要です。
注意
enable_ssl_verification
は既定では true
です。 自己署名証明書の場合、このフィールドは false
である必要があり、宛先サーバーでは証明書の検証を無効にしている必要があります。
セキュリティ上の理由から、Databricks では、ペイロードの HMAC でエンコードされた部分を使用して、シークレットの検証を実行することをお勧めしています。 ホスト名の検証を無効にすると、悪意によって、意図しないホストに要求がルーティングされるリスクが高くなります。
import hmac
import hashlib
import json
secret = shared_secret.encode('utf-8')
signature_key = 'X-Databricks-Signature'
def validate_signature(request):
if not request.headers.has_key(signature_key):
raise Exception('No X-Signature. Webhook not be trusted.')
x_sig = request.headers.get(signature_key)
body = request.body.encode('utf-8')
h = hmac.new(secret, body, hashlib.sha256)
computed_sig = h.hexdigest()
if not hmac.compare_digest(computed_sig, x_sig.encode()):
raise Exception('X-Signature mismatch. Webhook not be trusted.')
HTTP レジストリ Webhook の Authorization ヘッダー
Authorization ヘッダーが設定されている場合、クライアントでは、Authorization ヘッダー内のベアラー トークンまたは認可資格情報を検証することによって、HTTP 要求のソースを検証する必要があります。
ジョブ レジストリ Webhook の IP 許可リスト
IP 許可リストが有効になっている別のワークスペースでジョブ実行をトリガーする Webhook を使用するには、受信要求を受け入れるように、Webhook が配置されているリージョンの NAT IP を許可リストに載せる必要があります。
Webhook とジョブが同じワークスペース内にある場合は、許可リストに IP を追加する必要はありません。
ジョブが Azure マルチテナント リージョンにある場合は、「Azure Databricks コントロール プレーン アドレス」を参照してください。 他のすべてのリージョンについては、アカウント チームに問い合わせて、許可リストに載せる必要がある IP を特定してください。
監査ログ
ワークスペースで監査ログが有効になっている場合は、次のイベントが監査ログに記録されます。
- Webhook の作成
- Webhook の更新
- Webhook の一覧表示
- Webhook の削除
- Webhook をテストする
- webhook トリガー
Webhook トリガーの監査ログ
HTTP エンドポイントを使用した Webhook の場合、Webhook に対して指定された URL に送信される HTTP 要求と、URL と enable_ssl_verification
の値がログに記録されます。
ジョブ トリガーを使用した Webhook では、job_id
と workspace_url
の値がログに記録されます。
例
このセクションには、次が含まれます。
- HTTP レジストリ Webhook ワークフローの例。
- ジョブ レジストリ Webhook ワークフローの例。
- Webhook の一覧表示の例。
- 2 つのノートブック例: 1 つは REST API を示し、もう 1 つは Python クライアントを示しています。
HTTP レジストリ Webhook のワークフローの例
1. Webhook を作成する
HTTPS エンドポイントで Webhook イベント要求を受信する準備ができたら、Webhook Databricks REST API を使用して Webhook を作成できます。 たとえば、Webhook の URL で Slack を指してメッセージをチャネルに投稿できます。
$ curl -X POST -H "Authorization: Bearer <access-token>" -d \
'{"model_name": "<model-name>",
"events": ["MODEL_VERSION_CREATED"],
"description": "Slack notifications",
"status": "TEST_MODE",
"http_url_spec": {
"url": "https://hooks.slack.com/services/...",
"secret": "anyRandomString"
"authorization": "Bearer AbcdEfg1294"}}' https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/create
from databricks_registry_webhooks import RegistryWebhooksClient, HttpUrlSpec
http_url_spec = HttpUrlSpec(
url="https://hooks.slack.com/services/...",
secret="secret_string",
authorization="Bearer AbcdEfg1294"
)
http_webhook = RegistryWebhooksClient().create_webhook(
model_name="<model-name>",
events=["MODEL_VERSION_CREATED"],
http_url_spec=http_url_spec,
description="Slack notifications",
status="TEST_MODE"
)
応答
{"webhook": {
"id":"1234567890",
"creation_timestamp":1571440826026,
"last_updated_timestamp":1582768296651,
"status":"TEST_MODE",
"events":["MODEL_VERSION_CREATED"],
"http_url_spec": {
"url": "https://hooks.slack.com/services/...",
"enable_ssl_verification": True
}}}
Databricks Terraform プロバイダーおよび databricks_mlflow_webhook を使用して HTTP レジストリ Webhook を作成することもできます。
2. Webhook をテストする
以前の Webhook は TEST_MODE
で作成されたため、指定した URL に要求を送信するモック イベントをトリガーできます。 ただし、この Webhook では実際のイベントはトリガーされません。 テスト エンドポイントによって、指定した URL から受信された状態コードと本文が返されます。
$ curl -X POST -H "Authorization: Bearer <access-token>" -d \
'{"id": "1234567890"}' \
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/test
from databricks_registry_webhooks import RegistryWebhooksClient
http_webhook = RegistryWebhooksClient().test_webhook(
id="1234567890"
)
応答
{
"status":200,
"body":"OK"
}
3. Webhook をアクティブ状態に更新する
実際のイベントに対して Webhook を有効にするには、更新呼び出しによってその状態を ACTIVE
に設定します。これは、他のプロパティを変更するためにも使用できます。
$ curl -X PATCH -H "Authorization: Bearer <access-token>" -d \
'{"id": "1234567890", "status": "ACTIVE"}' \
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/update
from databricks_registry_webhooks import RegistryWebhooksClient
http_webhook = RegistryWebhooksClient().update_webhook(
id="1234567890",
status="ACTIVE"
)
応答
{"webhook": {
"id":"1234567890",
"creation_timestamp":1571440826026,
"last_updated_timestamp":1582768296651,
"status": "ACTIVE",
"events":["MODEL_VERSION_CREATED"],
"http_url_spec": {
"url": "https://hooks.slack.com/services/...",
"enable_ssl_verification": True
}}}
4. Webhook を削除する
Webhook を無効にするには、(上記と同様に更新コマンドを使用して) その状態を DISABLED
に設定するか、削除します。
$ curl -X DELETE -H "Authorization: Bearer <access-token>" -d \
'{"id": "1234567890"}' \
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/delete
from databricks_registry_webhooks import RegistryWebhooksClient
http_webhook = RegistryWebhooksClient().delete_webhook(
id="1234567890"
)
応答
{}
ジョブ レジストリ Webhook のワークフローの例
ジョブ レジストリ Webhook を管理するためのワークフローは HTTP レジストリ Webhook と似ています。唯一の違いは、http_url_spec
フィールドが job_spec
フィールドに置き換えられる点です。
Webhook を使用する場合、同じワークスペース内または別のワークスペース内のジョブをトリガーできます。 ワークスペースは、省略可能なパラメーター workspace_url
を使用して指定します。 workspace_url
がない場合、既定の動作では、Webhook と同じワークスペース内のジョブがトリガーされます。
必要条件
- 既存のジョブ。
- 個人用アクセス トークン。 アクセス トークンは MLflow サービスによってのみ読み取ることができ、モデル レジストリ API の Azure Databricks ユーザーが返すことはできません。
Note
セキュリティのベスト プラクティスとして、自動化ツール、システム、スクリプト、アプリを使用して認証する場合、Databricks では、ワークスペース ユーザーではなくサービス プリンシパルに属する個人用アクセス トークンを使用することを推奨しています。 サービス プリンシパルのトークンを作成するには、「サービス プリンシパルのトークンを管理する」をご覧ください。
ジョブ レジストリ Webhook を作成する
$ curl -X POST -H "Authorization: Bearer <access-token>" -d \ '{"model_name": "<model-name>",
"events": ["TRANSITION_REQUEST_CREATED"],
"description": "Job webhook trigger",
"status": "TEST_MODE",
"job_spec": {
"job_id": "1",
"workspace_url": "https://my-databricks-workspace.com",
"access_token": "dapi12345..."}}'
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/create
from databricks_registry_webhooks import RegistryWebhooksClient, JobSpec
job_spec = JobSpec(
job_id="1",
workspace_url="https://my-databricks-workspace.com",
access_token="dapi12345..."
)
job_webhook = RegistryWebhooksClient().create_webhook(
model_name="<model-name>",
events=["TRANSITION_REQUEST_CREATED"],
job_spec=job_spec,
description="Job webhook trigger",
status="TEST_MODE"
)
応答
{"webhook": {
"id":"1234567891",
"creation_timestamp":1591440826026,
"last_updated_timestamp":1591440826026,
"status":"TEST_MODE",
"events":["TRANSITION_REQUEST_CREATED"],
"job_spec": {
"job_id": "1",
"workspace_url": "https://my-databricks-workspace.com"
}}}
Databricks Terraform プロバイダーおよび databricks_mlflow_webhook を使用してジョブ レジストリ Webhook を作成することもできます。
レジストリ Webhook の一覧表示の例
$ curl -X GET -H "Authorization: Bearer <access-token>" -d \ '{"model_name": "<model-name>"}'
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/list
from databricks_registry_webhooks import RegistryWebhooksClient
webhooks_list = RegistryWebhooksClient().list_webhooks(model_name="<model-name>")
応答
{"webhooks": [{
"id":"1234567890",
"creation_timestamp":1571440826026,
"last_updated_timestamp":1582768296651,
"status": "ACTIVE",
"events":["MODEL_VERSION_CREATED"],
"http_url_spec": {
"url": "https://hooks.slack.com/services/...",
"enable_ssl_verification": True
}},
{
"id":"1234567891",
"creation_timestamp":1591440826026,
"last_updated_timestamp":1591440826026,
"status":"TEST_MODE",
"events":["TRANSITION_REQUEST_CREATED"],
"job_spec": {
"job_id": "1",
"workspace_url": "https://my-databricks-workspace.com"
}}]}