Blog
Stellen Sie Ihren eigenen Databricks Feature Store auf Azure mit Terraform bereit
Eine Anleitung zur Bereitstellung eines der wichtigsten Bestandteile der modernen Datenplattform, die MLOps ermöglicht: der Feature Store auf Azure Databricks mit Terraform als IaC.

Machine Learning Operations (MLOps)- das ist heutzutage ein trendiges Schlagwort, nicht wahr? Nun, heute werden wir hier nicht darüber debattieren, warum Sie dies für Ihr Unternehmen brauchen und welche verschiedenen Aspekte Sie dabei berücksichtigen sollten. Stattdessen möchten wir Ihnen mitteilen, was wir bei der Einrichtung eines Teils der Datenplattform gelernt haben, der Datenwissenschaftlern und Ingenieuren für maschinelles Lernen wirklich helfen würde - der Feature Store auf Azure Databricks. Aufgrund seiner Beliebtheit, seines Cloud-unabhängigen Ansatzes und der großartigen Benutzerfreundlichkeit dank der deklarativen Syntax haben wir uns für Terraform als Infrastructure as Code (IaC) Framework entschieden, was sich als sehr nützlich erwiesen hat. Lassen Sie uns ohne Umschweife zur Sache kommen.
Databricks Feature Store auf Azure - wichtige Ressourcen
In diesem Blog-Beitrag stellen wir Ihnen die folgenden Dienste vor, die in der Azure-Cloud bereitgestellt werden:
- Databricks Arbeitsbereich
- Azure Data Lake Storage Konto gen. 2
- Schlüssel Tresor
- CosmosDB Arbeitsbereich mit Core (SQL) API
Vollwertige Datenplattformen verfügen natürlich über mehr Ressourcen, aber mit den hier verwendeten erhalten Sie die volle Funktionalität des Feature Store, einschließlich seiner Offline- und Online-Versionen.
Anforderungen
- Azure-Konto mit einem Contributor- oder Owner-Zugriff auf eine bestimmte Ressourcengruppe
- Bash und jq auf dem Computer, auf dem der Code ausgeführt wird (wenn Sie Windows verwenden, können Sie die Anwendung Git Bash benutzen)
- Azure CLI-Anwendung, die auf dem Rechner installiert ist, der das Skript ausführt
- Databricks CLI (optional, Sie können ein AAD-Token für die Authentifizierung verwenden).
Feature Store Beispiel-Notizbücher
In dem in diesem Blog-Beitrag vorgestellten Code-Repository haben wir zwei leicht modifizierte Notebooks aufgenommen, die ursprünglich von Databricks erstellt wurden. Unsere Änderungen ermöglichen es Ihnen, die Notebooks direkt nach der Bereitstellung der Infrastruktur auszuführen, so dass Sie sich sofort mit den Funktionalitäten des Feature Store vertraut machen können. Da sie sehr gut dokumentiert sind, überlassen wir es Ihnen, sie auf eigene Faust zu erkunden. Sie können sie hier finden.
Terraform Status Informationen
Dabei gehen wir davon aus, dass Sie den Terraform-Code von Ihrem eigenen Computer aus ausführen, was dazu führt, dass die Statusinformationen lokal gespeichert werden. Wenn Sie diese Datei mit anderen Teammitgliedern teilen müssen oder bereits Pipelines für die Bereitstellung der Infrastruktur eingerichtet haben, sollten Sie die Statusinformationen an einem leichter zugänglichen Ort speichern, z. B. in einem Blob-Speicher. Wie Sie dies tun, erfahren Sie in diesem offiziellen Azure-Tutorial.
Terraform Arbeitsablauf
Codebase
Um den Databricks Feature Store auf Databricks bereitzustellen, werden wir zwei Terraform-Dateien nutzen, die den Code enthalten:
- variables.tf
Benennung der Ressourcen, die bereitgestellt werden sollen - main.tf
Die gesamte Spezifikation der Infrastruktur mit allen einzelnen Ressourcen und den Verbindungen zwischen ihnen
Der gebrauchsfertige Terraform Code ist im Github Repo verfügbar. Sie können ihn sich jederzeit ansehen, aber wir werden Sie sorgfältig durch den gesamten Code führen, damit Sie sowohl den Code als auch die Dienste, die Teil des DataBricks Feature Store sein werden, verstehen können. Den vollständigen Code finden Sie hier:
GitHub - getindata/azure-databricks-feature-store-poc
Azure CLI Anmeldung
Bevor Sie Terraform-Code ausführen, müssen Sie sich bei der Azure-Cloud authentifizieren. Dies geschieht über Azure CLI, das auf dem Computer installiert sein muss, den Sie für die Bereitstellung der Infrastruktur verwenden werden. Eine Anleitung dazu finden Sie hier.
Wenn CLI installiert ist, stellen Sie sicher, dass Sie sich bei CLI anmelden, indem Sie den folgenden Befehl ausführen und den Anweisungen auf dem Bildschirm folgen:
az login
Terraform Initialisierung
Der erste Schritt in den Terraform-Arbeitsabläufen ist die Initialisierung eines Arbeitsverzeichnisses. Dadurch wird auch sichergestellt, dass alle im Code angegebenen Provider-Plugins ordnungsgemäß installiert und in einer lokalen Sperrdatei nachverfolgt werden. Sie können dies durch den Aufruf dieses einfachen Befehls tun:
terraform init
Bereitstellen in einer Ressourcengruppe, die nicht leer ist
Wenn Sie eine bestehende Ressourcengruppe für dieses Tutorial verwenden möchten, sollten Sie zunächst deren Definition in eine lokale Statusdatei importieren. Dazu müssen Sie die Abschnitte des Codes auskommentieren, die (an dieser Stelle) vorzeitig ausgewertet werden. Diese Angaben lauten wie folgt:
- provider "databricks"
- data “local_file” “aad_token_fle”
- data "databricks_current_user" "me"
Der Code für diese Teile sollte also wie folgt lauten:
# provider "databricks" {
# host = azurerm_databricks_workspace.dbx.workspace_url
# token = trimsuffix(data.local_file.aad_token_file.content, "\r\n")
# }
# data "local_sensitive_file" "aad_token_file" {
# depends_on = [null_resource.get_aad_token_for_dbx]
# filename = var.aad_token_file
# }
# data "databricks_current_user" "me" {
# depends_on = [azurerm_databricks_workspace.dbx]
# }
Nachdem Sie diese Abschnitte auskommentiert haben, kopieren Sie die ID Ihres Azure-Abonnements (Sie können sie über das Azure-Portal oder über Azure CLI überprüfen). Führen Sie dann den folgenden Befehl aus:
terraform import azurerm_resource_group.rg /subscriptions/<your-subscription-id>/resourceGroups/<your-resource-group-name>
Die erfolgreiche Ausführung der Import-Anweisung führt zur Erstellung einer Statusdatei, in der die von Terraform verwalteten Ressourcen genauestens nachverfolgt werden. Je nach Bedarf müssen Sie die Statusdatei manchmal ändern, z.B. wenn Sie alle Ressourcen löschen möchten, die über einen bestimmten Terraform-Code erstellt wurden, aber nicht die gesamte Ressourcengruppe löschen möchten. Dann können Sie die temporäre Ressourcengruppe aus der Statusdatei (azurerm_resource_group.rg) entfernen und alle Ressourcen durch Ausführen von terraform destroy zerstören. Wenn Sie die Ressourcen wieder in dieser Ressourcengruppe einsetzen möchten, führen Sie einfach den oben genannten terraform import Befehl erneut aus. Bitte beachten Sie, dass Sie die Zustandsdatei niemals manuell ändern sollten - Zustandsänderungen sollten immer über Argumente erfolgen, die dem Befehl terraform state übergeben werden.
Wenn es in dieser Ressourcengruppe Ressourcen gibt, die nicht in Terraform importiert werden, bleiben diese intakt, egal was Sie im Code tun (es sei denn, Sie entscheiden sich, die Ressourcengruppe aus Terraform zu zerstören - in diesem Fall wäre das Entfernen der Ressourcengruppe aus der Statusdatei die bessere Option).
Anbieter
Der folgende Code wird für die Anbietererklärung verwendet:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.26.0"
}
databricks = {
source = "databricks/databricks"
version = ">= 1.4.0"
}
}
required_version = ">= 1.1.0"
}
provider "azurerm" {
features {
key_vault {
purge_soft_delete_on_destroy = true
}
}
}
provider "databricks" {
host = azurerm_databricks_workspace.dbx.workspace_url
token = trimsuffix(data.local_sensitive_file.aad_token_file.content, "\r\n")
}
data "local_sensitive_file" "aad_token_file" {
depends_on = [null_resource.get_aad_token_for_dbx]
filename = var.aad_token_file
}
resource "null_resource" "get_aad_token_for_dbx" {
triggers = { always_run = "${timestamp()}" }
provisioner "local-exec" {
command = format("az account get-access-token --resource 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d | jq -r .accessToken > %s", var.aad_token_file)
}
}
In diesem Tutorial verwenden wir 2 verschiedene Terraform-Anbieter: azurerm und databricks. Wie Sie sehen können, gibt es eine zusätzliche Option für key_vault innerhalb des azurerm Providers, und zwar purge_soft_delete_on_destroy. Da die hier gezeigte Infrastruktur nie für den Einsatz in realen Produktionsabläufen gedacht war, stellen wir mit dieser Option sicher, dass die Inhalte von key_vault zusammen mit ihrer Löschung bereinigt werden.
Der Provider für Databricks ist jedoch interessanter. Da das Ziel hier darin bestand, alles, was für die Nutzung des Feature Store erforderlich ist, von einer Codebasis aus einzurichten, war es notwendig, einen geheimen Bereich innerhalb von Databricks zu erstellen, der durch Azure Key Vault gesichert ist. Dazu müssen Sie sich beim Databricks-Anbieter entweder mit Azure CLI oder AAD-Token authentifizieren. Das Databricks Personal Access Token (Standard-Authentifizierungsmethode) können Sie für diesen Zweck nicht verwenden, da es Sie in keiner Weise zum Zugriff auf native Azure-Ressourcen, wie z.B. Key Vault, autorisiert. Die Authentifizierung über Service Principal wird derzeit nicht unterstützt. Weitere Informationen finden Sie unter diesem Link.
Die Authentifizierung über ein AAD-Token wird wie folgt gehandhabt: Die Ressource "null_resource" "get_aad_token_for_dbx" wird für einen Azure CLI-Aufruf verwendet, der ein Token mit dem Flag— resource 2ff814a6–3304–4ab8–85cb-cd0e6f879c1d abruft, das die programmatische ID von Azure für den Databricks-Arbeitsbereich ist. Die Ausgabe des Azure CLI-Aufrufs wird über eine Pipeline an den jq-Befehl jq -r .accessToken > %s weitergeleitet, der den Token-Wert an %s ausgibt. Der gesamte CLI-Aufruf und die Pipeline sind in den nativen Terraform-Befehl format() verpackt, der %s auf den Namen der Datei abbildet, die für die Aufbewahrung des AAD-Tokens verwendet wird. Wie in der Datei variables.tf angegeben, ist dies aad_token.txt.
Sobald der Token in eine lokale Datei geschrieben wurde, kann er über einen Datenblock referenziert werden, der hier als ”local_sensitive_file” “aad_token_file” angegeben ist.
Dieser Datenblock wird im Block provider "databricks" referenziert, wo wir seinen Inhalt als Token angeben und uns gleichzeitig um überflüssige Dateiformate kümmern, die je nach Betriebssystem unserer Wahl in die Datei gelangt sein könnten. Dieses Trimmen erfolgt über die Funktion trimsuffix.
Bevor wir mit den eigentlichen Ressourcen arbeiten, sollten wir uns das Leben später etwas leichter machen und einige Metadaten deklarieren.
Zusätzliche Metadaten
data "azurerm_client_config" "current" {}
data "databricks_current_user" "me" {
depends_on = [azurerm_databricks_workspace.dbx]
}
Durch die Angabe dieser beiden Datenblöcke können wir im gesamten Code auf einige Argumente verweisen, z.B. tenant_id und object_id, die mit unserem Benutzerkonto auf Azure und unserem Home-Pfad des Databricks Workspace verbunden sind. Durch die Angabe von depends_on = [azurerm_databricks_workspace .dbx] in databricks_current_user stellen wir sicher, dass der Databricks-Benutzer erst ausgewertet wird, wenn der Databricks Workspace tatsächlich bereitgestellt wird.
Ressourcengruppe
resource "azurerm_resource_group" "rg" {
name = var.resource_group
location = "West Europe"
tags = {
"tag1" = "tag1value"
"tag2" = "tag2value"
}
}
Wie bereits erwähnt, können Sie eine bestehende Ressourcengruppe für die Bereitstellung Ihres Feature Stores nutzen, aber Sie können auch eine ganz neue Gruppe direkt in Terraform erstellen. Wenn Sie Ihre Ressourcengruppe importieren und keine ihrer Spezifikationen ändern möchten, stellen Sie sicher, dass ihre Definition im Terraform-Code genau mit der Definition einer bestehenden Ressourcengruppe übereinstimmt, einschließlich aller Tags. Sie können diese entweder im Portal oder beim Ausführen des Befehls terraform plan oder terraform apply überprüfen. Wenn die Ressourcengruppe in der Nachricht, die Sie nach der Ausführung eines dieser Befehle erhalten, in keiner Weise geändert wird, stimmt Ihre Definition vollständig mit der Definition einer bereits vorhandenen Ressourcengruppe überein. Andernfalls können Sie entweder Ihren Code ändern oder die Definition der Ressourcengruppe überschreiben.
Speicherkonto
resource "azurerm_storage_account" "adls2" {
name = var.stg_name
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
account_kind = "StorageV2"
is_hns_enabled = "true"
}
resource "azurerm_storage_data_lake_gen2_filesystem" "stg1" {
name = "offline-feature-store"
storage_account_id = azurerm_storage_account.adls2.id
}
resource "azurerm_storage_data_lake_gen2_filesystem" "stg2" {
name = "temp"
storage_account_id = azurerm_storage_account.adls2.id
}
Obwohl eine dedizierte Speicherlösung nicht notwendig ist, um Databricks mit seinem Feature Store in Betrieb zu nehmen, ist es im Allgemeinen eine gute Idee, Ihre Daten getrennt vom Databricks Workspace zu halten. Dies schränkt Ihre Möglichkeiten in keiner Weise ein, sondern bietet vielmehr viel mehr Flexibilität für die Architektur, die Sie aufbauen. In einem solchen Fall ist es eine gute Idee, unverwaltete Deltatabellen zu verwenden - das bedeutet, dass Databricks nur die Metadaten (wie den Pfad auf dem zugrunde liegenden Speicher) der Deltatabelle und nicht die Daten selbst verwaltet. Weitere Informationen hierzu finden Sie unter diesem Link.
Aufgrund der inhärenten Vorteile von Azure Data Lake ver. 2 gegenüber Azure Blob Storage ist es eine gute Idee, ihn als zugrunde liegende Lösung für die Speicherung großer Datenmengen zu nutzen. Um dies zu erreichen, müssen account_kind und is_hns_enabledin der Ressource azurerm_storage_account auf StorageV2 bzw. true festgelegt werden.
Beachten Sie bitte, wie die Attribute der Ressourcen hier wiederverwendet werden. Anstatt resource_group_name und location manuell einzugeben, machen wir uns die Tatsache zunutze, dass diese Attribute im Status angegeben sind, und verweisen hier einfach auf sie.
Container bilden die Hierarchie für die Daten, die auf Azure Storage-Lösungen gespeichert sind. Sie können wie ein übergeordnetes Verzeichnis in einem bestimmten Storage-Konto behandelt werden, so dass der Pfad zu <storage-name>/<container-name> auf die oberste Ebene des Containers abgebildet wird. Innerhalb des Terraform-Codes können Container mit der Ressource azurerm_storage_data_lake_gen2_filesystem erstellt werden.
Databricks Arbeitsbereich
resource "azurerm_databricks_workspace" "dbx" {
name = var.dbx_workspace_name
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
sku = "premium"
}
Die Bereitstellung des Databricks-Arbeitsbereichs erfolgt mit dem azurerm Provider und nicht mit dem databricks Provider - letzterer ist für die Interaktion mit dem Arbeitsbereich selbst gedacht und erfordert, dass der Arbeitsbereich zuerst erstellt wird. Der Parameter sku steuert, ob Sie einen standard oder premium Arbeitsbereich verwenden werden. Den Vergleich ihrer Funktionen und Preise finden Sie hier.
Bitte beachten Sie, dass dadurch nur der Arbeitsbereich bereitgestellt wird. Durch die Bereitstellung eines Arbeitsbereichs wird automatisch eine neue Ressourcengruppe erstellt, die von dem Databricks-Arbeitsbereich verwaltet wird. Innerhalb dieser Ressourcengruppe erscheinen Ressourcen, die von Databricks bereitgestellt werden, sobald neue Ressourcen benötigt werden. Wenn Sie also einen neuen Cluster starten, wird darin ein neuer Satz von Ressourcen für einen bestimmten VM-Typ bereitgestellt.
Azure Schlüssel Tresor
resource "azurerm_key_vault" "kv" {
name = var.kv_name
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
enabled_for_disk_encryption = true
tenant_id = data.azurerm_client_config.current.tenant_id
soft_delete_retention_days = 7
purge_protection_enabled = false
sku_name = "standard"
}
resource "azurerm_key_vault_access_policy" "kv_ap" {
key_vault_id = azurerm_key_vault.kv.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id
secret_permissions = [
"Set",
"List",
"Get",
"Delete",
"Recover",
"Restore",
"Purge"
]
depends_on = [azurerm_key_vault.kv]
}
Da Databricks eine Möglichkeit bietet, Geheimnisse aus dem Azure Key Vault direkt in der Databricks Runtime zu verwenden, sollten wir dies für die Speicherung der Schlüssel nutzen, die für die Bereitstellung von Verbindungsnachweisen erforderlich sind. Dazu müssen wir zunächst einen Key Vault einrichten.
Der Zugriff auf einen Key Vault kann auf zwei Arten gehandhabt werden, entweder über eine Zugriffsrichtlinie oder eine rollenbasierte Zugriffskontrolle. Wir haben uns für Ersteres entschieden, weil es so einfach ist. Die Art und Weise, wie der Terraform-Code hier angegeben ist, erzeugt einen vollständigen Satz geheimer Berechtigungen für den authentifizierten Benutzer auf azurerm provider, da der Parameter object_id auf data.azurerm_client_config.current.object_id gesetzt ist. Um eine Zugriffsrichtlinie für einen anderen Benutzer, eine andere Gruppe oder einen anderen Dienstprinzipal zu erstellen, ändern Sie diesen Wert.
Bitte beachten Sie auch, dass die Option depends_on in azurerm_key_vault_access_policyauf [azurerm_key_vault.kv] gesetzt ist. Dies geschieht, um sicherzustellen, dass die Richtlinie erstellt wird, nachdem der zugrunde liegende Key Vault bereits bereitgestellt wurde.
Registrierung eines Key Vault als geheimer Bereich in Databricks Workspace
resource "databricks_secret_scope" "kv" {
name = azurerm_key_vault.kv.name
keyvault_metadata {
resource_id = azurerm_key_vault.kv.id
dns_name = azurerm_key_vault.kv.vault_uri
}
}
Der Zugriff auf Key Vault-Geheimnisse vom Databricks-Arbeitsbereich aus ist sehr einfach, wenn er über Terraform erfolgt. Alles, was Sie tun müssen, ist, resource_id und dns_name als Ressource keyvault_metadata in databricks_secret_scope einzubinden. Bitte denken Sie jedoch daran, dass Sie sich gegenüber dem Provider Databricks auf eine Weise authentifizieren müssen, die den Zugriff auf Databricks Workspace und Azure Key Vault ermöglicht, wie im Abschnitt Providers beschrieben. Die Registrierung eines Key Vault innerhalb von Databricks Workspace als geheimer Bereich ist genau der Grund, warum die Authentifizierung über ein AAD-Token erfolgt.
Bitte beachten Sie auch, dass in einem solchen Fall der Zugriff auf Geheimnisse nicht über Databricks, sondern über die Zugriffskontrolle auf einen Key Vault verwaltet wird. Die Art und Weise, wie Sie diesen Zugriff kontrollieren, wird im obigen Abschnitt (Azure Key Vault) beschrieben.
Cosmos DB - Backend für den Online-Funktionsspeicher
resource "azurerm_cosmosdb_account" "cdbacc" {
name = var.cosmos_db_name
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
offer_type = "Standard"
kind = "GlobalDocumentDB"
enable_automatic_failover = true
tags = {
defaultExperience = "Core (SQL)"
hidden-cosmos-mmspecial = ""
}
consistency_policy {
consistency_level = "BoundedStaleness"
max_interval_in_seconds = 300
max_staleness_prefix = 100000
}
geo_location {
location = azurerm_resource_group.rg.location
failover_priority = 0
}
}
resource "azurerm_cosmosdb_sql_database" "db" {
name = "tf-db"
resource_group_name = azurerm_resource_group.rg.name
account_name = azurerm_cosmosdb_account.cdbacc.name
}
resource "azurerm_cosmosdb_sql_container" "cnt" {
name = "tf-container"
resource_group_name = azurerm_resource_group.rg.name
account_name = azurerm_cosmosdb_account.cdbacc.name
database_name = azurerm_cosmosdb_sql_database.db.name
partition_key_path = "/definition/id"
partition_key_version = 1
throughput = 400
indexing_policy {
indexing_mode = "consistent"
included_path {
path = "/*"
}
included_path {
path = "/included/?"
}
excluded_path {
path = "/excluded/?"
}
}
unique_key {
paths = ["/definition/idlong", "/definition/idshort"]
}
}
Es gibt 3 verschiedene Backends für den Online Feature Store auf Azure Databricks:
- Azure Cosmos DB,
- Azure MySQL ,
- Azure SQL Server.
Von diesen drei Optionen bietet Cosmos DB die meisten Funktionen, weshalb sie hier verwendet wird.
Es gibt jedoch einige Einschränkungen bei der Verwendung von Cosmos DB als Feature Store-Backend, und zwar:
- wird nur von Clustern unterstützt, auf denen Databricks ML Runtime mit einer höheren Version als 11.1 installiert ist
- es kann nur mit der Core (SQL) API verwendet werden
- Netzwerkkonnektivität muss auf alle Netzwerke eingestellt sein
Abgesehen davon wird die Verbindung zwischen Databricks Runtime und Cosmos DB über einen separaten OLTP-Connector abgewickelt, der auf dem Cluster installiert werden muss - auf dieses Thema kommen wir später noch einmal zurück. Wenn all diese Nachteile Sie nicht davon abgehalten haben, Cosmos DB als Feature Store-Backend zu verwenden, lassen Sie uns fortfahren.
Die Standard-SQL-Hierarchie von Cosmos DB besteht aus den folgenden Entitäten:
Cosmos DB Arbeitsbereich > Datenbank > Container > Tabelle > Elemente
Zunächst muss also der Arbeitsbereich erstellt werden. Cosmos mit Core (SQL) API kann von Terraform aus bereitgestellt werden, indem Sie kind = “GlobalDocumentDB” angeben und die Tags auf
tags = {
defaultExperience = "Core (SQL)"
hidden-cosmos-mmspecial = ""
}
Sobald das Cosmos DB-Konto erstellt ist, können wir Datenbanken und Container erstellen. Bitte beachten Sie, dass throughput innerhalb von Containern festgelegt wird. Indem Sie diesen Wert ändern, können Sie bestimmen, wie viel Rechenleistung für Ihre Arbeitslasten reserviert wird, und somit auch die Kosten der Ressource kontrollieren.
Sobald die grundlegende Einrichtung von Cosmos DB abgeschlossen ist, können wir mit der Herstellung der Verbindung zwischen Databricks Workspace und der Datenbank fortfahren. Zu diesem Zweck benötigen wir einen Cluster, der als unsere Rechenmaschine auf Databricks dient.
Databricks-Cluster
resource "databricks_cluster" "dbx_cluster" {
cluster_name = var.cluster_name
spark_version = "11.2.x-cpu-ml-scala2.12"
node_type_id = "Standard_F4"
autotermination_minutes = 30
num_workers = 1
spark_conf = {
format("fs.azure.account.key.%s.dfs.core.windows.net", azurerm_storage_account.adls2.name) = azurerm_storage_account.adls2.primary_access_key
}
}
Die Anpassung einer Clusterspezifikation ist etwas, auf das Sie (anfangs) nicht allzu viel Zeit verwenden sollten. Sie kann jederzeit geändert und angepasst werden, wenn Sie mit Ihren Arbeitsabläufen fortfahren. Sie können auch so viele Cluster erstellen, wie Sie möchten - die Erstellung selbst kostet nichts, Sie zahlen nur, wenn die Cluster laufen. Daher ist es eine sehr gute Idee, eine Option zur automatischen Beendigung einzurichten, damit Sie nicht dafür bezahlen müssen, dass die Cluster über Nacht ungenutzt bleiben, falls Sie vergessen, sie abzuschalten. Sie können auch wählen, welche VM-Typen verwendet werden sollen und wie viele Worker hochgefahren werden sollen. Bei Bedarf können Sie auch eine automatische Skalierung für Ihre Cluster festlegen, aber für POC-Zwecke sind die billigsten verfügbaren VMs ausreichend. Hier können Sie auch eine Spark-Version auswählen, die Ihren Arbeitslasten zur Verfügung stehen soll. Wenn Sie eine Feature Store-Bibliothek auf dem Cluster vorinstalliert haben möchten, sollten Sie hier nachsehen, welche Version von Databricks Machine Learning Runtime Sie verwenden sollten. Wie im Code angezeigt, wurde bei der Erstellung dieses Blogposts Databricks Runtime 11.2 für Machine Learning verwendet.
Abgesehen von der Cluster-Hardware und der Laufzeitspezifikation können Sie mit der Ressource databricks_cluster auch Spark-Konfigurationseigenschaften hinzufügen, die für die Anpassung der Laufzeit genutzt werden können. Hier wird spark_conf verwendet, um den Zugriffsschlüssel für das ADLS2-Konto bereitzustellen. Bitte beachten Sie, dass zunächst der Befehl format verwendet wird, um innerhalb des Strings auf azurerm_storage_account.adls2.name zu verweisen, dem dann der Schlüsselwert selbst zugewiesen wird. Da diese Zuweisung über die Referenzierung von Eigenschaften von Objekten erfolgt, die zuvor erstellt wurden, wird der Speicherschlüssel niemals im Code selbst offengelegt - er wird zur Laufzeit ausgewertet, sobald Sie terraform apply drücken.
Durch das Hinzufügen der ADLS2-Schlüssel zur Spark-Konfiguration des Clusters können Sie über den Azure Blob Filesystem-Treiber auf die Daten in diesem Speicher zugreifen. Es funktioniert so, dass Speicherpfade auf den abfss-Pfad abgebildet werden. Sie können beispielsweise Objekte auflisten, die sich in einem der Container befinden, die wir zuvor erstellt haben, indem Sie den folgenden Befehl im Databricks-Arbeitsbereich ausführen (denken Sie jedoch daran, dass Sie einen Cluster mit dem zur Spark-Konfiguration hinzugefügten Speicherschlüssel verwenden müssen):
dbutils.fs.ls("abfss://offline-feature-store@<stg_name_from_variables.tf>.dfs.core.windows.net/external-location/path/to/data")
Wir halten die Verwendung eines dedizierten Speicherkontos für eine optimale Möglichkeit, mit Delta-Tabellen auf Databricks zu arbeiten. Die volle Kontrolle über alle Speicherfunktionen bietet den Benutzern der Plattform große Flexibilität.
Installation des Cosmos DB-Treibers auf dem Databricks-Cluster
resource "databricks_library" "cosmos" {
cluster_id = databricks_cluster.dbx_cluster.id
maven {
coordinates = "com.azure.cosmos.spark:azure-cosmos-spark_3-2_2-12:4.14.1"
}
}
Nun, da der Cluster und ein dedizierter Cosmos DB-Arbeitsbereich für unseren Feature Store beide bereit sind, müssen wir die Verbindung zwischen diesen beiden Ressourcen einrichten. Die Verbindung wird über den Azure Cosmos DB OLTP Spark Connector hergestellt, der mit der Maven-Plattform ausgeliefert wird. Diese Bibliothek ist jedoch nicht auf dem Cluster vorinstalliert und muss manuell auf dem Cluster installiert werden. Dank der Ressource databricks_library ist dies jedoch sehr einfach über das Skript möglich. Wir müssen nur die Quelle der Bibliothek (maven) und ihre Koordinaten zusammen mit der entsprechenden Cluster-ID angeben.
Jetzt kann die Verbindung zwischen den Ressourcen für den Feature Store hergestellt werden. Zu diesem Zweck müssen wir dem Databricks-Cluster Cosmos DB-Anmeldeinformationen zur Verfügung stellen, auf die über den OLTP-Connector, den wir gerade installiert haben, zugegriffen wird. Diese Anmeldeinformationen können sich in einem beliebigen geheimen Bereich im Databricks-Arbeitsbereich befinden. Da wir jedoch bereits einen geheimen Bereich mit Azure Key Vault als Backend erstellt haben, nutzen wir diesen einfach aus.
Einfügen von Cosmos DB-Schlüsseln in Azure Key Vault
resource "azurerm_key_vault_secret" "cdb-primary-key-write" {
name = "cosmosdb-primary-key-write-authorization-key"
value = azurerm_cosmosdb_account.cdbacc.primary_key
key_vault_id = azurerm_key_vault.kv.id
depends_on = [azurerm_key_vault_access_policy.kv_ap]
}
resource "azurerm_key_vault_secret" "cdb-primary-key-read" {
name = "cosmosdb-primary-key-read-authorization-key"
value = azurerm_cosmosdb_account.cdbacc.primary_readonly_key
key_vault_id = azurerm_key_vault.kv.id
depends_on = [azurerm_key_vault_access_policy.kv_ap]
}
Wenn das Cosmos DB-Konto erstellt wird, stehen seine Zugriffsschlüssel als Parameter zur Verfügung, die im gesamten Terraform-Skript wiederverwendet werden können, ähnlich wie wir es mit ADLS2 gemacht haben. Legen wir also einfach den erforderlichen Zugriffsschlüssel in unserem Key Vault ab.
Bitte beachten Sie die Namenskonvention für die Geheimnisse: beide Zugriffsschlüssel (Lese- und Schreibschlüssel) haben das Suffix authorization-key. Dies geschieht nicht zufällig. Tatsächlich erwartet die Feature Store Bibliothek, dass die Zugriffsschlüssel diese spezielle Endung haben, unabhängig davon, was sonst noch im Namen steht. Wir finden das merkwürdig, zumal Sie im Code immer auf den geheimen Namen verweisen müssen, aber ohne dieses Suffix verbirgt die Feature Store Bibliothek diesen Zusatz einfach vor dem Benutzer. Weitere Informationen finden Sie in den Originaldokumenten. Sie können auch einen Blick auf den Python-Code für diese Verbindung in den Notebooks werfen, die zusammen mit dem Terraform-Code in das Repo hochgeladen wurden.
Databricks Token für Echtzeit-Inferenz
resource "databricks_token" "pat" {
comment = "Terraform Provisioning"
// 100 day token
lifetime_seconds = 8640000
}
resource "azurerm_key_vault_secret" "databricks-token" {
name = "databricks-token"
value = databricks_token.pat.token_value
key_vault_id = azurerm_key_vault.kv.id
depends_on = [azurerm_key_vault_access_policy.kv_ap, databricks_token.pat]
}
Eines der im Repo verfügbaren Notebooks ermöglicht das Testen von Echtzeit-Inferenz, indem ein Endpunkt aufgerufen wird, der Ihr Mlflow-Modell bedient. Um eine solche Verbindung zu authentifizieren, verwenden wir ein Personal Access Token für Databricks Workspace. Es kann über die Ressource databricks_token erstellt werden. Sobald es bereitgestellt ist, fügen wir es in Key Vault ein, so wie wir es für andere Anmeldeinformationen getan haben.
Hochladen von Notizbüchern in Databricks Arbeitsbereich
resource "databricks_notebook" "online-fs-wine-example" {
source = format("${path.module}/databricks_notebooks/%s", var.notebook_1)
path = format("${data.databricks_current_user.me.home}/terraform/%s", var.notebook_1)
}
resource "databricks_notebook" "notebook-2" {
source = format("${path.module}/databricks_notebooks/%s", var.notebook_2)
path = format("${data.databricks_current_user.me.home}/terraform/%s", var.notebook_2)
}
Sobald die Ressourcen richtig eingerichtet sind, brauchen wir nur noch ein funktionierendes Beispiel dafür, wie der Feature Store funktioniert. Dazu müssen wir lediglich die Git-Version der Notebooks in unseren Databricks-Arbeitsbereich hochladen. Dies geschieht mit einer databricks_notebook Ressource. Für den Umgang mit Pfaden nutzen wir die leistungsstarke Funktion format, die in Terraform verfügbar ist. source gibt die lokale path zur Datei an und path ist der Zielpfad im Databricks-Arbeitsbereich. Wir können ${path.module} verwenden, um den Pfad zum Dateisystem zu ermitteln, in dem sich unser Code befindet. Um den Pfad im Databricks-Arbeitsbereich zu analysieren, können wir data.databricks_current_user.me.home nutzen, das Attribut von data, das wir zuvor angegeben haben. Dadurch entspricht der Anfang des Pfades dem home Pfad unseres Benutzers im Databricks-Arbeitsbereich.
Databricks Arbeitsabläufe
resource "databricks_job" "run-online-fs-wine-example" {
name = "run-wine-example"
new_cluster {
num_workers = 1
spark_version = "11.2.x-cpu-ml-scala2.12"
node_type_id = "Standard_DS3_v2"
}
spark_conf = {
format("fs.azure.account.key.%s.dfs.core.windows.net", azurerm_storage_account.adls2.name) = azurerm_storage_account.adls2.primary_access_key
}
notebook_task {
notebook_path = databricks_notebook.online-fs-wine-example.path
}
library {
maven {
coordinates = "com.azure.cosmos.spark:azure-cosmos-spark_3-2_2-12:4.14.1"
}
}
}
Bisher haben wir uns darauf konzentriert, die Einrichtung für eine interaktive Erfahrung mit Databricks zu schaffen. Das ist die Standardeinstellung, bei der Sie herumgehen, Code produzieren und Codezeilen ausführen, während Sie gehen. Databricks war jedoch nie dazu gedacht, nur eine interaktive Plattform zu sein. Databricks unterstützt auch geplante Aufträge, die für alle Produktionsfälle notwendig sind. Diese werden auf Job-Clustern ausgeführt, die sich von den interaktiven unterscheiden und in der Tat billiger zu verwenden sind. Sie existieren nur für die Dauer der Ausführung eines bestimmten Teils des Codes. Außerdem müssen sie vor dem Start des Auftrags vollständig eingerichtet werden, und wenn Ihr Auftrag fehlschlägt, muss der Cluster erneut bereitgestellt werden.
Workflows werden mit einer databricks_job Ressource erstellt. Im Grunde handelt es sich um die gleiche Einrichtung wie bei den interaktiven Clustern innerhalb einer Ressource. Der einzige wirkliche Unterschied im Code ist die Hinzufügung von notebook_task, die den Pfad zu dem Notebook angibt, das den Python-Code enthält, der innerhalb des Workflows ausgeführt wird. Sobald der Terraform-Code erfolgreich ausgeführt wurde, sieht die Aufgabenspezifikation für diesen Workflow in Databricks UI so aus:

Führen Sie das Skript aus
So, das war's mit der Beschreibung des gesamten Terraform-Codes. Wenn Sie in eine bestehende Ressourcengruppe deployen, müssen Sie den Code auskommentieren, der im Abschnitt Deployment in eine Ressourcengruppe, die nicht leer ist, auskommentiert wurde und die folgenden Entitäten umfasst:
- provider "databricks"
- data “local_sensitive_file” “aad_token_fle”
- data "databricks_current_user" "me"
Jetzt können wir untersuchen, welche Ressourcen Terraform versucht zu erstellen, indem wir sie aufrufen:
terraform plan
Sie sollten eine Aufforderung erhalten, in der Sie darüber informiert werden, was in der Ressourcengruppe passiert, wenn Sie mit der Bereitstellung der Ressourcen fortfahren. Wenn Sie noch Änderungen an Ihrem Code vornehmen möchten, können Sie dies jetzt tun.
Wenn Sie bereit sind, ist es an der Zeit, alle Dienste einzurichten. Bitte führen Sie den Befehl aus:
terraform apply
Zunächst erhalten Sie dieselbe Eingabeaufforderung, die Ihnen nach der Ausführung von terraform plan angezeigt wurde. Allerdings werden Sie jetzt auch gefragt, ob Sie mit der Bereitstellung fortfahren möchten. Wenn ja, geben Sie yes ein, klicken Sie auf die Eingabetaste und warten Sie ein wenig, bis Terraform seine Arbeit erledigt und alle Ressourcen bereitgestellt hat.
Sobald die Bereitstellung abgeschlossen ist, können Sie die in den Arbeitsbereich hochgeladenen Notizbücher erkunden. Sie veranschaulichen die Funktionen des Feature Stores unter Verwendung des Terraform Codes. Sie können auch den erstellten Workflow ausführen - er wird auf der Registerkarte Workflows in der Benutzeroberfläche angezeigt.
Zusammenfassung
Und da haben Sie es! Wir hoffen, dass dieser Blog-Beitrag Ihnen nicht nur gezeigt hat, wie Sie den Databricks Feature Store bereitstellen können, sondern auch, dass die Arbeit mit Terraform einfach und effektiv ist, vor allem dank der sehr gut durchdachten deklarativen Syntax. Vor allem dann, wenn es eine ganze Reihe von Komponenten in der Cloud gibt, zwischen denen Verbindungen hergestellt werden müssen. Da die Zustandsverwaltung in Terraform den Endbenutzern überlassen bleibt, kann es natürlich manchmal mühsam sein, sie richtig hinzubekommen, aber wir finden immer noch, dass der Preis für das, was wir dafür bekommen, sehr niedrig ist.
Wir hoffen, dass dieses Tutorial Ihnen beim Start Ihres Feature Stores innerhalb der Databricks-Plattform geholfen hat. Wenn Sie mehr darüber lesen möchten, wie der Feature Store in MLOps-Workflows eingesetzt wird, welche Anwendungsfälle die Databricks-Plattform in der modernen Datenwelt bietet oder warum wir Terraform so sehr mögen, lassen Sie es uns wissen.
In der Zwischenzeit empfehlen wir Ihnen, einen Blick auf unseren anderen Blogbeitrag über Feature Stores zu werfen:
Feature Store Vergleich: 4 Feature Stores - erklärt und verglichen
Feature Store - Verwaltung mehrerer Datenquellen mit Feast
Und unsere kostenlose Schritt-für-Schritt-Anleitung mit allem, was Sie über den Feature Store wissen müssen, einschließlich:
- MLOps, MLOps-Plattformen und Funktionsspeicher
- Beispiele für MLOps Arbeitsabläufe
- Entwerfen und Erstellen eines Feature Stores mit VertexAI, Snowflake und dbt
- Verwendung von Terraform zur Einrichtung und Wartung der Infrastruktur
Verfasst von
Szymon Żaczek
Unsere Ideen
Weitere Blogs
Contact



