Typisches Lakebase-Projektsetup mit Terraform

Diese Seite zeigt eine vollständige Terraform-Konfiguration für ein produktionsreifes Lakebase-Autoscaling-Projekt mit den am häufigsten verwendeten Funktionen:

  • Geschützte Produktionszweige
  • Lese-/Schreibendpunkt für Hochverfügbarkeit (High Availability, HA) mit lesbaren sekundären Replikaten
  • Dienstprinzipal mit DATABRICKS_SUPERUSER Datenbankberechtigungen
  • App-eigene Postgres-Datenbank
  • Postgres-Datenbank, die im Unity-Katalog für Lakehouse-Verbundabfragen von Databricks SQL und Notizbüchern registriert ist
  • Synchronisiertes Tabellenstreaming kontinuierlich aus dem Unity-Katalog
  • Databricks App, die mit dem Lakebase-Projekt verbunden ist

Eine schrittweise Einführung in Terraform mit Lakebase finden Sie unter "Erste Schritte mit Terraform für Lakebase".

Voraussetzungen

Bevor Sie mit diesem Lernprogramm beginnen können, benötigen Sie Folgendes:

Vollständige Konfiguration

Wenn Sie ein Projekt erstellen, erstellt Azure Databricks automatisch einen production Branch, einen primary Lese-/Schreibendpunkt, eine an Ihre Identität gebundene Postgres-Besitzerrolle und eine databricks_postgres Datenbank. Um diese implizit erstellten Ressourcen zu konfigurieren, deklarieren Sie sie in Terraform mit replace_existing = true. Weitere Informationen finden Sie unter databricks_postgres_branch, , databricks_postgres_endpoint, databricks_postgres_roleund databricks_postgres_database.

Warning

Diese Konfiguration setzt is_protected = true auf dem Branch production und enthält eine unprotect_for_destroy-Variable, die in die Branch-Spezifikation eingebunden ist. Terraform kann ein Projekt, das geschützte Verzweigungen enthält, nicht löschen, und die production Verzweigung kann nicht direkt gelöscht werden, da ihr Lebenszyklus vom Projekt gesteuert wird. Um Ressourcen sauber zu zerreißen, verwenden Sie eine zweistufige Zerstörung:

# Step 1: unprotect the branch
terraform apply -var="unprotect_for_destroy=true"

# Step 2: destroy all resources
terraform destroy -var="unprotect_for_destroy=true"

Nach dem Ausführen von terraform destroy wird das Projekt vorläufig gelöscht und 7 Tage lang aufbewahrt, bevor es endgültig gelöscht wird. Um es sofort dauerhaft zu löschen, setzen Sie purge_on_delete = true auf der Ressource databricks_postgres_project, bevor Sie destroy ausführen.

variable "admin_sp_app_id" {
  description = "Application ID of the service principal to grant admin access"
  type        = string
}

variable "unprotect_for_destroy" {
  description = "Set to true before destroy to unprotect the production branch"
  type        = bool
  default     = false
}

# Project — top-level container for branches, endpoints, databases, and roles.
resource "databricks_postgres_project" "this" {
  project_id = "my-lakebase-project"
  # purge_on_delete = true  # Uncomment to permanently delete on destroy (default: soft delete, 7-day retention).
  spec = {
    pg_version   = 17
    display_name = "My Lakebase Project"
    default_endpoint_settings = {
      autoscaling_limit_min_cu = 0.5
      autoscaling_limit_max_cu = 4.0
      suspend_timeout_duration = "300s"
    }
  }
}

# Configure the implicitly created production branch as protected.
resource "databricks_postgres_branch" "production" {
  branch_id = "production"
  parent    = databricks_postgres_project.this.name
  spec = {
    no_expiry    = true
    is_protected = var.unprotect_for_destroy ? false : true
  }
  replace_existing = true
}

# Configure the implicitly created primary endpoint with HA.
# HA requires no_suspension = true. group.min = 2 adds a standby for automatic failover.
resource "databricks_postgres_endpoint" "primary" {
  endpoint_id = "primary"
  parent      = databricks_postgres_branch.production.name
  spec = {
    endpoint_type            = "ENDPOINT_TYPE_READ_WRITE"
    autoscaling_limit_min_cu = 0.5
    autoscaling_limit_max_cu = 4.0
    no_suspension            = true
    group = {
      min                         = 2
      max                         = 2
      enable_readable_secondaries = true
    }
  }
  replace_existing = true
}

# Grant workspace-level CAN_MANAGE on the project to the service principal.
# Use status.project_id (bare ID) not .name (full resource path) — the permissions
# API rejects the full path with a "resource type not found" error.
resource "databricks_permissions" "project" {
  database_project_name = databricks_postgres_project.this.status.project_id
  access_control {
    service_principal_name = var.admin_sp_app_id
    permission_level       = "CAN_MANAGE"
  }
}

# Create a Postgres role backed by the service principal with full database privileges.
# depends_on serializes creation — Lakebase processes one branch operation at a time.
resource "databricks_postgres_role" "admin_sp" {
  role_id = "admin-sp"
  parent  = databricks_postgres_branch.production.name
  spec = {
    identity_type    = "SERVICE_PRINCIPAL"
    postgres_role    = var.admin_sp_app_id
    auth_method      = "LAKEBASE_OAUTH_V1"
    membership_roles = ["DATABRICKS_SUPERUSER"]
    attributes = {
      createdb   = true
      createrole = true
      bypassrls  = true
    }
  }
  depends_on = [databricks_postgres_endpoint.primary]
}

# Create a Postgres database owned by the admin SP role.
resource "databricks_postgres_database" "app" {
  database_id = "app"
  parent      = databricks_postgres_branch.production.name
  spec = {
    postgres_database = "app"
    role              = databricks_postgres_role.admin_sp.name
  }
}

# Register the Postgres database in Unity Catalog. This makes the database queryable
# from Databricks SQL and notebooks through Lakehouse Federation, and serves as the
# parent namespace for synced tables that live inside the Lakebase Catalog.
# create_database_if_missing is set explicitly because the database is managed by
# the databricks_postgres_database resource above.
resource "databricks_postgres_catalog" "app_catalog" {
  catalog_id = "app_catalog"
  spec = {
    postgres_database          = databricks_postgres_database.app.status.postgres_database
    branch                     = databricks_postgres_branch.production.name
    create_database_if_missing = false
  }
}

# Sync a Unity Catalog Delta table into the Lakebase database continuously.
# Prefixing synced_table_id with the Lakebase Catalog name places the synced table
# inside the catalog so it's discoverable alongside the rest of the catalog's contents.
# postgres_database references the catalog's status, which implicitly orders this
# resource after the catalog without an explicit depends_on.
resource "databricks_postgres_synced_table" "orders" {
  synced_table_id = "app_catalog.default.orders_synced"
  spec = {
    branch                             = databricks_postgres_branch.production.name
    postgres_database                  = databricks_postgres_catalog.app_catalog.status.postgres_database
    source_table_full_name             = "my_catalog.default.orders"
    primary_key_columns                = ["order_id"]
    scheduling_policy                  = "CONTINUOUS"
    create_database_objects_if_missing = true
    new_pipeline_spec = {
      storage_catalog = "my_catalog"
      storage_schema  = "default"
    }
  }
}

# Databricks App connected to the Lakebase project.
# database must be the full resource name (databricks_postgres_database.app.name),
# not the Postgres database name. permission must be "CAN_CONNECT_AND_CREATE".
resource "databricks_app" "this" {
  name        = "my-lakebase-app"
  description = "App backed by Lakebase autoscaling project"
  depends_on  = [databricks_postgres_database.app]
  resources = [{
    name = "lakebase-db"
    postgres = {
      branch     = databricks_postgres_branch.production.name
      database   = databricks_postgres_database.app.name
      permission = "CAN_CONNECT_AND_CREATE"
    }
  }]
}

Note

Diese Konfiguration erstellt eine separate Rolle (admin_sp) und datenbank (app) anstatt die implizite Besitzerrolle und databricks_postgres -datenbank zu verwalten. Um diese impliziten Ressourcen stattdessen unter Terraform-Verwaltung zu bringen, deklarieren Sie sie mit replace_existing = true unter Verwendung ihrer vorhandenen IDs. Die Datenbank-ID ist immer databricks-postgres. Die Rollen-ID wird von der Identität abgeleitet, die den Branch erstellt hat: der Teil der E-Mail vor @ (in Kleinbuchstaben, wobei nicht alphanumerische Zeichen durch Bindestriche ersetzt werden) für einen Benutzer oder sp-<application-id> für einen Serviceprinzipal. Wenn Sie sich über den genauen Wert nicht sicher sind, lesen Sie ihn stattdessen aus der Lakebase UI oder der Postgres-API aus, anstatt ihn manuell herzuleiten.

spec.membership_roles überschreibt die Mitgliedschaften der Rolle bei jeder Anwendung, anstatt mit ihnen zusammenzuführen. Behalten Sie DATABRICKS_SUPERUSER in der Liste bei; wenn Sie es weglassen, werden alle Rollenzugehörigkeiten entfernt.

resource "databricks_postgres_role" "owner" {
  role_id = "jane-doe" # normalized login of the creating identity
  parent  = databricks_postgres_branch.production.name
  spec = {
    postgres_role    = "jane.doe@databricks.com" # the raw login
    membership_roles = ["DATABRICKS_SUPERUSER"]
    attributes = {
      createdb   = true
      createrole = true
      bypassrls  = true
    }
  }
  replace_existing = true
}

resource "databricks_postgres_database" "databricks_postgres" {
  database_id = "databricks-postgres"
  parent      = databricks_postgres_branch.production.name
  spec = {
    postgres_database = "databricks_postgres"
    # spec.role is omitted, so the database keeps its existing owner.
  }
  replace_existing = true
}

Weitere Ressourcen