MLflow モデルレジストリ Webhooks on Databricks

プレビュー

この機能はパブリックプレビュー段階です。

Webhookを使用すると、モデルレジストリイベントをリッスンできるため、統合によってアクションが自動的にトリガーされます。 Webhook を使用して、機械学習パイプラインを自動化し、既存の CI/CD ツールやワークフローと統合できます。 たとえば、新しいモデルバージョンが作成されたときに CI ビルドをトリガーしたり、本番環境へのモデル移行が要求されるたびに Slack を通じてチームメンバーに通知したりできます。

Webhook は、Databricks REST API または Python クライアント databricks-registry-webhooks PyPI から利用できます。

Unity Catalogのモデルを使用する場合、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: ユーザーがモデル バージョンのアーカイブを要求しました。

ウェブフック の種類

トリガーターゲットに基づく2種類のWebhookがあります。

  • HTTP エンドポイントを持つウェブフック (HTTP レジストリ ウェブフック): HTTP エンドポイントにトリガーを送信します。

  • ジョブ トリガーを使用した Webhook (ジョブ レジストリ Webhook): Databricks ワークスペースでジョブをトリガーします。ジョブのワークスペースで IP 許可リストが有効になっている場合は、モデルレジストリのワークスペース IP を許可リストに登録する必要があります。 詳細については、「 ジョブ レジストリ Webhook の IP 許可リスト 」を参照してください。

また、スコープに基づいて 2 種類の Webhook があり、アクセス制御の要件が異なります。

  • モデル固有の Webhook: Webhook は、特定の登録済みモデルに適用されます。 モデル固有の Webhook を作成、変更、削除、またはテストするには、登録済みのモデルに対する CAN MANAGE アクセス許可が必要です。

  • レジストリ全体の Webhook: Webhook は、新しい登録済みモデルの作成など、ワークスペース内の登録済みモデルのイベントによってトリガーされます。 レジストリ全体の Webhook を作成するには、作成時に model_name フィールドを省略します。 レジストリ全体の Webhook を作成、変更、削除、またはテストするには、ワークスペース管理者のアクセス許可が必要です。

ウェブフックペイロード

各イベント トリガーには、Webhook エンドポイントへの送信要求のペイロードに含まれる最小限のフィールドがあります。

  • アーティファクト パスの場所などの機密情報は除外されます。 適切な ACL を持つユーザーとプリンシパルは、クライアントまたは REST APIs を使用して、モデルレジストリにクエリー この情報を取得できます。

  • ペイロードは暗号化されません。 Databricks が Webhook のソースであることを検証する方法については、「情報 のセキュリティ 」を参照してください。

  • text フィールドはSlackの統合を容易にします。Slack メッセージを送信するには、Slack ウェブフック エンドポイントをウェブフック URL として指定します。

ジョブ レジストリ Webhook ペイロード

ジョブ レジストリ Webhook のペイロードは、ジョブの種類によって異なり、ターゲット ワークスペースの jobs/run-now エンドポイントに送信されます。

単一タスク・ジョブ

単一タスクジョブには、タスクタイプに基づく 3 つのペイロードのいずれかがあります。

ノートブックと Python のwheel ジョブ

ノートブック wheel ジョブと Python wheel ジョブには、フィールド 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."
}

安全

セキュリティのために、Databricks には、ペイロードのヘッダー コンピュートに X-Databricks-Signature と、 SHA-256 アルゴリズムを使用した HMAC を使用して Webhook に関連付けられた共有シークレットキーが含まれています。

さらに、Webhook の HttpUrlSpec に標準の承認ヘッダーを指定することで、送信要求に標準の承認ヘッダーを含めることができます。

クライアント検証

共有シークレットが設定されている場合、ペイロードの受信者は、共有シークレットを使用してペイロードを 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 レジストリ ウェブフックの 承認ヘッダー

承認ヘッダーが設定されている場合、クライアントは、承認ヘッダーのベアラー トークンまたは承認資格情報を確認して、HTTP 要求の送信元を確認する必要があります。

ジョブレジストリ Webhook の IP 許可リスト

IP 許可リストが有効になっている別のワークスペースでジョブの実行をトリガーする Webhook を使用するには、受信要求を受け入れるために Webhook が配置されているリージョンの NAT IP を 許可リストに登録する 必要があります。

Webhook とジョブが同じワークスペースにある場合は、許可リストに IP を追加する必要はありません。

アカウントチームに連絡して、許可リストに登録する必要があるIPを特定します。

監査ログ

ワークスペースで監査ログが有効になっている場合、次のイベントが監査ログに含まれます。

  • ウェブフックを作成する

  • ウェブフックを更新する

  • リストウェブフック

  • ウェブフックの削除

  • ウェブフックをテストする

  • ウェブフックトリガー

ウェブフックトリガー監査ログ

HTTP エンドポイントを持つウェブフックの場合、ウェブフックに指定された URL に送信された HTTP リクエストが、URL 値と enable_ssl_verification 値とともにログに記録されます。

ジョブトリガーを含むWebhookの場合、 job_idworkspace_url 値がログに記録されます。

ここでは、次の内容について説明します。

HTTP レジストリ ウェブフックのサンプル ワークフロー

1. ウェブフック を作成する

HTTPS エンドポイントがウェブフック イベント要求を受信する準備ができたら、ウェブフック Databricks REST API を使用してウェブフックを作成できます。 たとえば、ウェブフックの 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 は 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 を有効にするには、他のプロパティの変更にも使用できる更新呼び出しを使用して、そのステータスを 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 を無効にするには、そのステータスを 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 ワークフロー の例

ジョブ・レジストリー・ウェブフックを管理するためのワークフローは、HTTP レジストリー・ウェブフックと似ていますが、唯一の違いは、 http_url_spec フィールドを置き換える job_spec フィールドです。

Webhook を使用すると、同じワークスペースまたは別のワークスペースでジョブをトリガーできます。 ワークスペースは、オプションのパラメーター workspace_urlを使用して指定します。 workspace_url が存在しない場合、既定の動作では、Webhook と同じワークスペースでジョブがトリガーされます。

要件

自動化されたツール、システム、スクリプト、アプリを使用して認証する場合のセキュリティのベスト プラクティスとして、Databricks ではOAuth トークンを使用することをお勧めします。

個人用アクセストークン認証を使用する場合、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 を作成することもできます。

レジストリ ウェブフックの一覧表示の例

$ 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"
}}]}

ノートブック

MLflow モデルレジストリ webhooks REST API サンプル ノートブック

ノートブックを新しいタブで開く

MLflow モデルレジストリ webhooks Python クライアントのサンプル ノートブック

ノートブックを新しいタブで開く