Webhooks de registro de modelo MLflow em Databricks
Visualização
Este recurso está em visualização pública.
Webhooks permitem que você escute eventos de Model Registry para que suas integrações possam acionar ações automaticamente. Você pode usar webhooks para automatizar e integrar seu pipeline machine learning com ferramentas CI/CD existentes e fluxo de trabalho. Por exemplo, você pode acionar builds de CI quando uma nova versão de modelo é criada ou notificar os membros de sua equipe por meio do Slack sempre que uma transição de modelo para produção é solicitada.
Os webhooks estão disponíveis por meio da API REST do Databricks ou do cliente Python databricks-registry-webhooks
no PyPI.
Observação
Os webhooks não estão disponíveis quando o senhor usa Models no Unity Catalog. Para obter uma alternativa, consulte Posso usar solicitações de transição de estágio ou acionar webhooks em eventos? Não há suporte para o envio de webhooks para endpoints privados (endpoints que não são acessíveis pela Internet pública).
Eventos de webhook
Você pode especificar um webhook para ser acionado em um ou mais destes eventos:
MODEL_VERSION_CREATED: Uma nova versão de modelo foi criada para o modelo associado.
MODEL_VERSION_TRANSITIONED_STAGE: O estágio de uma versão do modelo foi alterado.
TRANSITION_REQUEST_CREATED: um usuário solicitou que o estágio de uma versão do modelo fosse transferido.
COMMENT_CREATED: Um usuário escreveu um comentário em um modelo registrado.
REGISTERED_MODEL_CREATED: Um novo modelo registrado foi criado. Esse tipo de evento só pode ser especificado para um webhook em todo o registro, que pode ser criado não especificando um nome de modelo na solicitação de criação.
MODEL_VERSION_TAG_SET: um usuário definiu tags na versão do modelo.
MODEL_VERSION_TRANSITIONED_TO_STAGING: uma versão de modelo foi transferida para teste.
MODEL_VERSION_TRANSITIONED_TO_PRODUCTION: uma versão de modelo foi transferida para produção.
MODEL_VERSION_TRANSITIONED_TO_ARCHIVED: uma versão de modelo foi arquivada.
TRANSITION_REQUEST_TO_STAGING_CREATED: um usuário solicitou que uma versão de modelo fosse transferida para teste.
TRANSITION_REQUEST_TO_PRODUCTION_CREATED: um usuário solicitou que uma versão de modelo fosse transferida para produção.
TRANSITION_REQUEST_TO_ARCHIVED_CREATED: um usuário solicitou que uma versão de modelo fosse arquivada.
Tipos de webhooks
Existem dois tipos de webhooks com base em seus destinos de acionamento:
Webhooks com endpoints HTTP (webhooks de registro HTTP): envie gatilhos para um endpoint HTTP.
Webhooks com gatilhos Job (webhooks de registro de Job ): acione um Job em um workspace Databricks. Se a lista de permissões de IP estiver habilitada no workspace do Job, você deverá permitir os IPs do workspace do registro de modelo. Consulte lista de permissões de IP para webhooks de registro Job para obter mais informações.
Existem também dois tipos de webhooks com base em seu escopo, com diferentes requisitos de controle de acesso:
Webhooks específicos do modelo: O webhook se aplica a um modelo específico registrado. O senhor deve ter permissões de gerenciar o CAN no modelo registrado para criar, modificar, excluir ou testar webhooks específicos do modelo.
Webhooks de todo o registro: o webhook é acionado por eventos em qualquer modelo registrado no workspace, incluindo a criação de um novo modelo registrado. Para criar um webhook em todo o registro, omita o campo
model_name
na criação. Você deve ter permissões de administrador workspace para criar, modificar, excluir ou testar webhooks em todo o registro.
Carga útil do webhook
Cada acionador de evento tem campos mínimos incluídos na carga da solicitação de saída para o endpoint do webhook.
Informações confidenciais, como localização do caminho do artefato, são excluídas. Usuários e principais com ACLs apropriados podem usar o cliente ou APIs REST para query o Model Registry para esta informação.
As cargas não são criptografadas. Consulte Segurança para obter informações sobre como validar que Databricks é a origem do webhook.
O campo
text
facilita a integração do Slack. Para enviar uma mensagem do Slack, forneça um endpoint de webhook do Slack como o URL do webhook.
Carga útil do webhook de registro Job
A carga de um webhook de registro Job depende do tipo de Job e é enviada para o endpoint jobs/run-now
no workspace de destino.
Jobde tarefa única
Job de tarefa única tem uma das três cargas úteis com base no tipo de tarefa.
Job de Notebook e Python wheel
Job de Notebook e Python wheel têm uma carga útil JSON com um dicionário de parâmetros que contém um campo event_message
.
{
"job_id": 1234567890,
"notebook_params": {
"event_message": "<Webhook Payload>"
}
}
Jobmultitarefa
Job multitarefa tem uma carga útil JSON com todos os parâmetros preenchidos para account diferentes tipos de tarefa.
{
"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>"]
}
Exemplo de cargas úteis
evento: MODEL_VERSION_TRANSITIONED_STAGE
Resposta
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."
}
evento: MODEL_VERSION_TAG_SET
Resposta
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."
}
evento: COMMENT_CREATED
Resposta
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."
}
Segurança
Por segurança, o Databricks inclui o X-Databricks-Signature no compute do cabeçalho da carga útil e a key secreta compartilhada associada ao webhook usando o algoritmo HMAC com SHA-256.
Além disso, você pode incluir um cabeçalho de autorização padrão na solicitação de saída especificando um no HttpUrlSpec
do webhook.
verificação do cliente
Se um segredo compartilhado for definido, o destinatário da carga útil deverá verificar a origem da solicitação HTTP usando o segredo compartilhado para codificar HMAC a carga útil e, em seguida, comparar o valor codificado com o X-Databricks-Signature
do cabeçalho. Isso é particularmente importante se a validação do certificado SSL estiver desativada (ou seja, se o campo enable_ssl_verification
estiver definido como false
).
Observação
enable_ssl_verification
é true
por default. Para certificados autoassinados, este campo deve ser false
e o servidor de destino deve desabilitar a validação do certificado.
Para fins de segurança, o Databricks recomenda que você execute a validação secreta com a parte codificada em HMAC da carga útil. Se você desativar a validação do nome do host, aumentará o risco de uma solicitação ser roteada de forma maliciosa para um host indesejado.
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.')
Cabeçalho de autorização para webhooks de registro HTTP
Se um cabeçalho de autorização for definido, os clientes devem verificar a origem da solicitação HTTP verificando os tokens do portador ou as credenciais de autorização no cabeçalho de autorização.
Lista de permissões de IP para webhooks de registro Job
Para usar um webhook que aciona a execução Job em um espaço de trabalho diferente que tenha a lista de permissões de IP habilitada, você deve colocar na lista de permissões o IP NAT da região onde o webhook está localizado para aceitar solicitações recebidas.
Se o webhook e o Job estiverem no mesmo workspace, você não precisará adicionar nenhum IP à sua lista de permissões.
Entre em contato com a equipe da sua account para identificar os IPs que você precisa incluir na lista de permissões.
Log de auditoria
Se o log de auditoria estiver habilitado para seu workspace, os seguintes eventos serão incluídos nos logs de auditoria:
Criar webhook
Atualizar webhook
Listar webhook
Excluir webhook
webhook de teste
Gatilho de webhook
Exemplos
Esta seção inclui:
dois Notebook de exemplo: um ilustrando a API REST e outro ilustrando o cliente Python.
Exemplo de webhook de registro HTTP fluxo de trabalho
1. Crie um webhook
Quando um endpoint HTTPS está pronto para receber a solicitação de evento de webhook, você pode criar um webhook usando a API REST Databricks webhooks. Por exemplo, o URL do webhook pode apontar para o Slack para postar mensagens em um 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"
)
Resposta
{"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
}}}
Você também pode criar um webhook de registro HTTP com o provedor Databricks Terraform e databricks_mlflow_webhook.
2. Teste o webhook
O webhook anterior foi criado em TEST_MODE
, portanto, um evento simulado pode ser acionado para enviar uma solicitação ao URL especificado. No entanto, o webhook não é acionado em um evento real. O endpoint de teste retorna o código de status recebido e o corpo da URL especificada.
$ 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"
)
Resposta
{
"status":200,
"body":"OK"
}
3. Atualize o webhook para o status ativo
Para ativar o webhook para eventos reais, defina seu status como ACTIVE
por meio de uma chamada de atualização, que também pode ser usada para alterar qualquer uma de suas outras propriedades.
$ 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"
)
Resposta
{"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. Exclua o webhook
Para desativar o webhook, defina seu status como DISABLED
(usando um comando de atualização semelhante ao acima) ou exclua-o.
$ 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"
)
Resposta
{}
Exemplo de webhook de registro Job fluxo de trabalho
O fluxo de trabalho para gerenciar webhooks de registro Job é semelhante aos webhooks de registro HTTP, com a única diferença sendo o campo job_spec
que substitui o campo http_url_spec
.
Com webhooks, você pode acionar Job no mesmo workspace ou em um workspace diferente. A workspace é especificada usando o parâmetro opcional workspace_url
. Se nenhum workspace_url
estiver presente, o comportamento default é acionar um Job no mesmo workspace que o webhook.
Requisitos
Um trabalho existente.
Um access tokenpessoal. Observe que o access tokens só pode ser lido pelo serviço MLflow e não pode ser retornado pelos usuários do Databricks no Model Registry API.
Observação
Como prática recomendada de segurança, ao se autenticar com ferramentas, sistemas, scripts e aplicativos automatizados, o site Databricks recomenda que o senhor use o access tokens pessoal pertencente à entidade de serviço em vez do workspace de usuários. Para criar o site tokens para uma entidade de serviço, consulte gerenciar tokens para uma entidade de serviço.
Criar um webhook de registro Job
$ 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"
)
Resposta
{"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"
}}}
Você também pode criar um webhook de registro Job com o provedor Databricks Terraform e databricks_mlflow_webhook.
Exemplo de webhooks de registro de lista
$ 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>")
Resposta
{"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"
}}]}