Webhooks du registre des modèles MLflow dans Azure Databricks

Important

Cette fonctionnalité est disponible en préversion publique.

Les webhooks vous permettent d’écouter les événements de registre de modèle pour que vos intégrations puissent déclencher automatiquement des actions. Vous pouvez utiliser des webhooks pour automatiser et intégrer votre pipeline Machine Learning avec les outils et flux de travail CI/CD. Par exemple, vous pouvez déclencher des builds CI quand une nouvelle version de modèle est créée ou notifier les membres de l’équipe par marge chaque fois qu’une transition de modèle vers la production est demandée.

Les webhooks sont disponibles via l'API REST Databricks ou le client Python databricks-registry-webhooks sur PyPI.

Notes

Les webhooks ne sont pas disponibles lorsque vous utilisez des modèles dans Unity Catalog. Pour une solution alternative, consultez Est-il possible d’utiliser des demandes de transition d’étape ou de déclencher des webhooks sur des événements ?.

Événements de webhook

Vous pouvez spécifier un webhook à déclencher sur un ou plusieurs de ces événements :

  • MODEL_VERSION_CREATED: une nouvelle version de modèle a été créée pour le modèle associé.
  • MODEL_VERSION_TRANSITIONED_STAGE: l’étape d’une version de modèle a été modifiée.
  • TRANSITION_REQUEST_CREATED: un utilisateur a demandé la transition de l’étape d’une version de modèle.
  • COMMENT_CREATED: un utilisateur a écrit un commentaire sur un modèle inscrit.
  • REGISTERED_MODEL_CREATED: un nouveau modèle inscrit a été créé. Ce type d’événement ne peut être spécifié que pour un webhook à l’ensemble du registre, qui peut être créé en ne spécifiant pas de nom de modèle dans la demande de création.
  • MODEL_VERSION_TAG_SET: un utilisateur définit une étiquette sur la version du modèle.
  • MODEL_VERSION_TRANSITIONED_TO_STAGING: une version de modèle a été transférée vers l’environnement intermédiaire.
  • MODEL_VERSION_TRANSITIONED_TO_PRODUCTION: une version de modèle a été transférée en production.
  • MODEL_VERSION_TRANSITIONED_TO_ARCHIVED: une version de modèle a été archivée.
  • TRANSITION_REQUEST_TO_STAGING_CREATED: un utilisateur a demandé la transition d’une version de modèle vers un environnement intermédiaire.
  • TRANSITION_REQUEST_TO_PRODUCTION_CREATED: un utilisateur a demandé la transition d’une version de modèle en production.
  • TRANSITION_REQUEST_TO_ARCHIVED_CREATED: un utilisateur a demandé l’archivage d’une version de modèle.

Types de webhook

Il existe deux types de webhooks en fonction de leurs cibles de déclencheur :

  • Webhooks avec des points de terminaison HTTP : envoie des déclencheurs à un point de terminaison HTTP.
  • Webhooks avec déclencheurs de tâche (webhooks de registre de travaux) : déclenche un travail dans un espace de travail Azure Databricks. Si la liste d'adresses IP autorisées est activée dans l’espace de travail du travail, vous devez autoriser les adresses IP de l’espace de travail du registre du modèle. Pour plus d’informations, consultez Liste d'adresses IP autorisées pour les webhooks du registre de travail.

Il existe également deux types de webhooks en fonction de leur étendue, avec différentes exigences en matière de contrôle d’accès :

  • Webhooks spécifiques au modèle: le webhook s’applique à un modèle inscrit spécifique. Vous devez avoir les autorisations PEUT GÉRER sur le modèle inscrit pour créer, modifier, supprimer ou tester des webhooks spécifiques au modèle.
  • Webhooks à l’ensemble du Registre: le webhook est déclenché par des événements sur tout modèle inscrit dans l’espace de travail, y compris la création d’un nouveau modèle inscrit. Pour créer un webhook à l’ensemble du registre, omettez le champ model_name lors de la création. Vous devez disposer d’autorisations d’administrateur d’espace de travail pour créer, modifier, supprimer ou tester des webhooks à l’ensemble du registre.

Charge utile de webhook

Chaque déclencheur d’événement a des champs minimaux inclus dans la charge utile de la demande sortante envoyée au point de terminaison webhook.

  • Les informations sensibles telles que l’emplacement du chemin d’artefact sont exclues. Les utilisateurs et les principaux avec des listes de contrôle d’accès appropriées peuvent utiliser des API clientes ou REST pour interroger le registre de modèle pour ces informations.
  • Les charges utiles ne sont pas chiffrées. Pour plus d’informations sur la façon de vérifier que Azure Databricks est la source du webhook, consultez Sécurité.
  • Le champ text facilite l’intégration de Slack. Pour envoyer un message Slack, fournissez un point de terminaison webhook Slack comme URL du webhook.

Charge utile de webhook du registre de travaux

La charge utile d’un webhook du registre de travaux dépend du type de travail et est envoyée au point de terminaison jobs/run-now de l’espace de travail cible.

Travaux à tâche unique

Les travaux à tâche unique ont l’une des trois charges utiles en fonction du type de tâche.

Travaux de roue de notebook et Python

Les travaux de roue de notebook et Python ont une charge utile JSON avec un dictionnaire de paramètres qui contient un champ event_message.

{
  "job_id": 1234567890,
  "notebook_params": {
    "event_message": "<Webhook Payload>"
  }
}
Travaux d’envoi Python, JAR et Spark

Les travaux d’envoi Python, JAR et Spark ont une charge utile JSON avec une liste de paramètres.

{
  "job_id": 1234567890,
  "python_params": ["<Webhook Payload>"]
}
Tous les autres travaux

Tous les autres types de travaux ont une charge utile JSON sans paramètres.

{
  "job_id": 1234567890
}

Travaux à tâches multiples

Les travaux à tâches multiples ont une charge utile JSON avec tous les paramètres renseignés pour prendre en compte différents types de tâches.

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

Exemples de charges utiles

événement : MODEL_VERSION_TRANSITIONED_STAGE

Réponse

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."
}

événement : MODEL_VERSION_TAG_SET

Réponse

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."
}

événement : COMMENT_CREATED

Réponse

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."
}

Sécurité

Pour la sécurité, Azure Databricks comprend la signature X-Databricks dans l’en-tête calculé à partir de la charge utile et la clé secrète partagée associée au webhook à l’aide de HMAC avec l’algorithme SHA-256.

En outre, vous pouvez inclure un en-tête d’autorisation standard dans la demande sortante en spécifiant un en-tête dans le HttpUrlSpec du webhook.

Vérification du client

Si un secret partagé est défini, le destinataire de la charge utile doit vérifier la source de la requête HTTP en utilisant le secret partagé pour encoder la charge utile par HMAC, puis en comparant la valeur encodée avec le X-Databricks-Signature de l’en-tête. Cela est particulièrement important si la validation du certificat SSL est désactivée (autrement dit, si le champ enable_ssl_verification a la valeur false).

Notes

enable_ssl_verification est true par défaut. Pour les certificats auto-signés, ce champ doit être false, et le serveur de destination doit désactiver la validation des certificats.

Pour des raisons de sécurité, Databricks vous recommande d’effectuer une validation secrète avec la partie encodée HMAC de la charge utile. Si vous désactivez la validation du nom d’hôte, vous augmentez le risque qu’une demande soit acheminée de manière malveillante vers un hôte involontaire.

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.')

En-tête d’autorisation pour les webhooks du registre HTTP

Si un en-tête d’autorisation est défini, les clients doivent vérifier la source de la requête HTTP en vérifiant le jeton du porteur ou les informations d’identification de l’autorisation dans l’en-tête d’autorisation.

Liste d’adresses IP autorisées pour les webhooks du registre de travail

Pour utiliser un webhook qui déclenche l’exécution d’un travail dans un autre espace de travail sur lequel la liste d'adresses IP autorisées est activée, vous devez autoriser l’adresse IP NAT de la région où se trouve le webhook pour accepter les demandes entrantes.

Si le webhook et le travail se trouvent dans le même espace de travail, vous n’avez pas besoin d’ajouter des adresses IP à votre liste.

Si votre travail se trouve dans une région multilocataire Azure, consultez Adresses du plan de contrôle Azure Databricks. Pour toutes les autres régions, contactez votre équipe de compte pour identifier les adresses IP que vous devez autoriser.

Journalisation d’audit

Si la journalisation d’audit est activée pour votre espace de travail, les événements suivants sont inclus dans les journaux d’audit :

  • Créer un webhook
  • Mettre à jour le webhook
  • Lister le webhook
  • Supprimer un webhook
  • Tester un webhook
  • Déclencheur de webhook

Journalisation des audits de déclencheur webhook

Pour les webhooks avec des points de terminaison HTTP, la requête HTTP envoyée à l’URL spécifiée pour le webhook, ainsi que l’URL et les valeurs enable_ssl_verification sont journalisées.

Pour les webhooks avec des déclencheurs de tâche, les valeurs job_id et workspace_url sont journalisées.

Exemples

Cette section inclut les éléments suivants :

Exemple de flux de travail de webhook du registre HTTP

1. Créer un webhook

Quand un point de terminaison HTTPS est prêt à recevoir la demande d’événement webhook, vous pouvez créer un webhook à l’aide de l’API REST Databricks de webhooks. Par exemple, l’URL du webhook peut pointer vers la marge pour envoyer des messages vers un canal.

$ 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"
)

Réponse

{"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
}}}

Vous pouvez également créer un webhook de registre HTTP avec le fournisseur Databricks Terraform et databricks_mlflow_webhook.

2. Tester le webhook

Le webhook précédent a été créé dans TEST_MODE. Un événement factice peut donc être déclenché pour envoyer une demande à l’URL spécifiée. Toutefois, le webhook ne se déclenche pas sur un événement réel. Le point de terminaison de test retourne le corps et le code d’état reçus à partir de l’URL spécifiée.

$ 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"
)

Réponse

{
 "status":200,
 "body":"OK"
}

3. Mettre à jour le webhook à l’état actif

Pour activer le webhook pour les événements réels, définissez son état sur ACTIVE à l’aide d’un appel de mise à jour, qui peut également être utilisé pour modifier l’une de ses autres propriétés.

$ 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"
)

Réponse

{"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.Supprimer le webhook

Pour désactiver le webhook, définissez son état sur DISABLED (à l’aide d’une commande de mise à jour similaire à la précédente) ou supprimez-le.

$ 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"
)

Réponse

{}

Exemple de flux de travail de webhook du registre de travail

Le flux de travail pour la gestion des webhooks du registre de travail est similaire aux webhooks du registre HTTP, la seule différence étant le champ job_spec qui remplace le champ http_url_spec.

Avec les webhooks, vous pouvez déclencher des tâches dans le même espace de travail ou dans un autre espace de travail. L’espace de travail est spécifié à l’aide du paramètre workspace_url facultatif. Si aucun workspace_url n’est présent, le comportement par défaut consiste à déclencher un travail dans le même espace de travail que le webhook.

Spécifications

Notes

En guise de bonne pratique de sécurité, quand vous vous authentifiez avec des outils, systèmes, scripts et applications automatisés, Databricks recommande d’utiliser des jetons d’accès personnels appartenant à des principaux de service et non des utilisateurs de l’espace de travail. Pour créer des jetons d’accès pour des principaux de service, consultez la section Gérer les jetons pour un principal de service.

Créer un webhook de registre de travail

$ 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"
)

Réponse

{"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"
}}}

Vous pouvez également créer un webhook de registre de travaux avec le fournisseur Databricks Terraform et databricks_mlflow_webhook.

Exemple de webhooks de registre de liste

$ 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>")

Réponse

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

Notebooks

Exemple de bloc-notes de l’API REST des webhooks du registre de modèles MLflow

Obtenir le notebook

Exemple de bloc-notes du client python du registre de modèles MLflow

Obtenir le notebook