Udostępnij za pośrednictwem


Tworzenie klastrów, notesów i zadań za pomocą programu Terraform

W tym artykule pokazano, jak za pomocą dostawcy narzędzia Terraform usługi Databricks utworzyć klaster, notes i zadanie w istniejącym obszarze roboczym usługi Azure Databricks.

Ten artykuł jest uzupełnieniem następujących artykułów wprowadzających do usługi Azure Databricks:

Konfiguracje programu Terraform można również dostosować w tym artykule, aby tworzyć niestandardowe klastry, notesy i zadania w obszarach roboczych.

Krok 1. Tworzenie i konfigurowanie projektu Terraform

  1. Utwórz projekt terraform, postępując zgodnie z instrukcjami w sekcji Wymagania artykułu Omówienie dostawcy narzędzia Terraform usługi Databricks.

  2. Aby utworzyć klaster, utwórz plik o nazwie cluster.tfi dodaj następującą zawartość do pliku. Ta zawartość tworzy klaster z najmniejszą dozwoloną ilością zasobów. Ten klaster korzysta z najnowszej wersji środowiska Databricks Runtime Long Term Support (LTS).

    W przypadku klastra, który współpracuje z wykazem aparatu Unity:

    variable "cluster_name" {}
    variable "cluster_autotermination_minutes" {}
    variable "cluster_num_workers" {}
    variable "cluster_data_security_mode" {}
    
    # Create the cluster with the "smallest" amount
    # of resources allowed.
    data "databricks_node_type" "smallest" {
      local_disk = true
    }
    
    # Use the latest Databricks Runtime
    # Long Term Support (LTS) version.
    data "databricks_spark_version" "latest_lts" {
      long_term_support = true
    }
    
    resource "databricks_cluster" "this" {
      cluster_name            = var.cluster_name
      node_type_id            = data.databricks_node_type.smallest.id
      spark_version           = data.databricks_spark_version.latest_lts.id
      autotermination_minutes = var.cluster_autotermination_minutes
      num_workers             = var.cluster_num_workers
      data_security_mode      = var.cluster_data_security_mode
    }
    
    output "cluster_url" {
     value = databricks_cluster.this.url
    }
    

    W przypadku klastra ogólnego przeznaczenia:

    variable "cluster_name" {
      description = "A name for the cluster."
      type        = string
      default     = "My Cluster"
    }
    
    variable "cluster_autotermination_minutes" {
      description = "How many minutes before automatically terminating due to inactivity."
      type        = number
      default     = 60
    }
    
    variable "cluster_num_workers" {
      description = "The number of workers."
      type        = number
      default     = 1
    }
    
    # Create the cluster with the "smallest" amount
    # of resources allowed.
    data "databricks_node_type" "smallest" {
      local_disk = true
    }
    
    # Use the latest Databricks Runtime
    # Long Term Support (LTS) version.
    data "databricks_spark_version" "latest_lts" {
      long_term_support = true
    }
    
    resource "databricks_cluster" "this" {
      cluster_name            = var.cluster_name
      node_type_id            = data.databricks_node_type.smallest.id
      spark_version           = data.databricks_spark_version.latest_lts.id
      autotermination_minutes = var.cluster_autotermination_minutes
      num_workers             = var.cluster_num_workers
    }
    
    output "cluster_url" {
     value = databricks_cluster.this.url
    }
    
  3. Aby utworzyć klaster, utwórz inny plik o nazwie cluster.auto.tfvarsi dodaj następującą zawartość do pliku. Ten plik zawiera wartości zmiennych do dostosowywania klastra. Zastąp wartości symboli zastępczych własnymi wartościami.

    W przypadku klastra, który współpracuje z wykazem aparatu Unity:

    cluster_name                    = "My Cluster"
    cluster_autotermination_minutes = 60
    cluster_num_workers             = 1
    cluster_data_security_mode      = "SINGLE_USER"
    

    W przypadku klastra ogólnego przeznaczenia:

    cluster_name                    = "My Cluster"
    cluster_autotermination_minutes = 60
    cluster_num_workers             = 1
    
  4. Aby utworzyć notes, utwórz inny plik o nazwie notebook.tfi dodaj następującą zawartość do pliku:

    variable "notebook_subdirectory" {
      description = "A name for the subdirectory to store the notebook."
      type        = string
      default     = "Terraform"
    }
    
    variable "notebook_filename" {
      description = "The notebook's filename."
      type        = string
    }
    
    variable "notebook_language" {
      description = "The language of the notebook."
      type        = string
    }
    
    resource "databricks_notebook" "this" {
      path     = "${data.databricks_current_user.me.home}/${var.notebook_subdirectory}/${var.notebook_filename}"
      language = var.notebook_language
      source   = "./${var.notebook_filename}"
    }
    
    output "notebook_url" {
     value = databricks_notebook.this.url
    }
    
  5. Jeśli tworzysz klaster, zapisz następujący kod notesu w pliku w tym samym katalogu co notebook.tf plik:

    Notes języka Python dla samouczka: uruchamianie kompleksowego potoku analizy typu lakehouse o nazwie o następującej notebook-getting-started-lakehouse-e2e.py zawartości:

    # Databricks notebook source
    external_location = "<your_external_location>"
    catalog = "<your_catalog>"
    
    dbutils.fs.put(f"{external_location}/foobar.txt", "Hello world!", True)
    display(dbutils.fs.head(f"{external_location}/foobar.txt"))
    dbutils.fs.rm(f"{external_location}/foobar.txt")
    
    display(spark.sql(f"SHOW SCHEMAS IN {catalog}"))
    
    # COMMAND ----------
    
    from pyspark.sql.functions import col
    
    # Set parameters for isolation in workspace and reset demo
    username = spark.sql("SELECT regexp_replace(current_user(), '[^a-zA-Z0-9]', '_')").first()[0]
    database = f"{catalog}.e2e_lakehouse_{username}_db"
    source = f"{external_location}/e2e-lakehouse-source"
    table = f"{database}.target_table"
    checkpoint_path = f"{external_location}/_checkpoint/e2e-lakehouse-demo"
    
    spark.sql(f"SET c.username='{username}'")
    spark.sql(f"SET c.database={database}")
    spark.sql(f"SET c.source='{source}'")
    
    spark.sql("DROP DATABASE IF EXISTS ${c.database} CASCADE")
    spark.sql("CREATE DATABASE ${c.database}")
    spark.sql("USE ${c.database}")
    
    # Clear out data from previous demo execution
    dbutils.fs.rm(source, True)
    dbutils.fs.rm(checkpoint_path, True)
    
    # Define a class to load batches of data to source
    class LoadData:
    
      def __init__(self, source):
        self.source = source
    
      def get_date(self):
        try:
          df = spark.read.format("json").load(source)
        except:
            return "2016-01-01"
        batch_date = df.selectExpr("max(distinct(date(tpep_pickup_datetime))) + 1 day").first()[0]
        if batch_date.month == 3:
          raise Exception("Source data exhausted")
          return batch_date
    
      def get_batch(self, batch_date):
        return (
          spark.table("samples.nyctaxi.trips")
            .filter(col("tpep_pickup_datetime").cast("date") == batch_date)
        )
    
      def write_batch(self, batch):
        batch.write.format("json").mode("append").save(self.source)
    
      def land_batch(self):
        batch_date = self.get_date()
        batch = self.get_batch(batch_date)
        self.write_batch(batch)
    
    RawData = LoadData(source)
    
    # COMMAND ----------
    
    RawData.land_batch()
    
    # COMMAND ----------
    
    # Import functions
    from pyspark.sql.functions import col, current_timestamp
    
    # Configure Auto Loader to ingest JSON data to a Delta table
    (spark.readStream
      .format("cloudFiles")
      .option("cloudFiles.format", "json")
      .option("cloudFiles.schemaLocation", checkpoint_path)
      .load(file_path)
      .select("*", col("_metadata.file_path").alias("source_file"), current_timestamp().alias("processing_time"))
      .writeStream
      .option("checkpointLocation", checkpoint_path)
      .trigger(availableNow=True)
      .option("mergeSchema", "true")
      .toTable(table))
    
    # COMMAND ----------
    
    df = spark.read.table(table_name)
    
    # COMMAND ----------
    
    display(df)
    

    Notes języka Python dla przewodnika Szybki start: uruchamianie zadania spark w obszarze roboczym usługi Azure Databricks przy użyciu witryny Azure Portal, pliku o nazwie notebook-quickstart-create-databricks-workspace-portal.py z następującą zawartością:

    # Databricks notebook source
    blob_account_name = "azureopendatastorage"
    blob_container_name = "citydatacontainer"
    blob_relative_path = "Safety/Release/city=Seattle"
    blob_sas_token = r""
    
    # COMMAND ----------
    
    wasbs_path = 'wasbs://%s@%s.blob.core.windows.net/%s' % (blob_container_name, blob_account_name,blob_relative_path)
    spark.conf.set('fs.azure.sas.%s.%s.blob.core.windows.net' % (blob_container_name, blob_account_name), blob_sas_token)
    print('Remote blob path: ' + wasbs_path)
    
    # COMMAND ----------
    
    df = spark.read.parquet(wasbs_path)
    print('Register the DataFrame as a SQL temporary view: source')
    df.createOrReplaceTempView('source')
    
    # COMMAND ----------
    
    print('Displaying top 10 rows: ')
    display(spark.sql('SELECT * FROM source LIMIT 10'))
    
  6. Jeśli tworzysz notes, utwórz inny plik o nazwie notebook.auto.tfvarsi dodaj następującą zawartość do pliku. Ten plik zawiera wartości zmiennych do dostosowywania konfiguracji notesu.

    Notes języka Python dla samouczka: uruchamianie kompleksowego potoku analizy typu lakehouse:

    notebook_subdirectory = "Terraform"
    notebook_filename     = "notebook-getting-started-lakehouse-e2e.py"
    notebook_language     = "PYTHON"
    

    Notes języka Python dla przewodnika Szybki start: uruchamianie zadania Spark w obszarze roboczym usługi Azure Databricks przy użyciu witryny Azure Portal:

    notebook_subdirectory = "Terraform"
    notebook_filename     = "notebook-quickstart-create-databricks-workspace-portal.py"
    notebook_language     = "PYTHON"
    
  7. Jeśli tworzysz notes, w obszarze roboczym usługi Azure Databricks upewnij się, że skonfigurować wszystkie wymagania dotyczące notesu do pomyślnego uruchomienia, korzystając z poniższych instrukcji:

  8. Aby utworzyć zadanie, utwórz kolejny plik o nazwie job.tfi dodaj następującą zawartość do pliku. Ta zawartość tworzy zadanie uruchamiania notesu.

    variable "job_name" {
      description = "A name for the job."
      type        = string
      default     = "My Job"
    }
    
    variable "task_key" {
      description = "A name for the task."
      type        = string
      default     = "my_task"
    }
    
    resource "databricks_job" "this" {
      name = var.job_name
      task {
        task_key = var.task_key
        existing_cluster_id = databricks_cluster.this.cluster_id
        notebook_task {
          notebook_path = databricks_notebook.this.path
        }
      }
      email_notifications {
        on_success = [ data.databricks_current_user.me.user_name ]
        on_failure = [ data.databricks_current_user.me.user_name ]
      }
    }
    
    output "job_url" {
      value = databricks_job.this.url
    }
    
  9. Jeśli tworzysz zadanie, utwórz inny plik o nazwie job.auto.tfvarsi dodaj następującą zawartość do pliku. Ten plik zawiera wartość zmiennej do dostosowywania konfiguracji zadania.

    job_name = "My Job"
    task_key = "my_task"
    

Krok 2. Uruchamianie konfiguracji

W tym kroku uruchomisz konfiguracje programu Terraform, aby wdrożyć klaster, notes i zadanie w obszarze roboczym usługi Azure Databricks.

  1. Sprawdź, czy konfiguracje programu Terraform są prawidłowe, uruchamiając terraform validate polecenie . Jeśli zostaną zgłoszone jakiekolwiek błędy, napraw je i ponownie uruchom polecenie.

    terraform validate
    
  2. Sprawdź, co narzędzie Terraform zrobi w obszarze roboczym, zanim narzędzie Terraform rzeczywiście to zrobi, uruchamiając terraform plan polecenie .

    terraform plan
    
  3. Wdróż klaster, notes i zadanie w obszarze roboczym, uruchamiając terraform apply polecenie . Po wyświetleniu monitu o wdrożenie wpisz yes i naciśnij Enter.

    terraform apply
    

    Narzędzie Terraform wdraża zasoby określone w projekcie. Wdrażanie tych zasobów (zwłaszcza klastra) może potrwać kilka minut.

Krok 3. Eksplorowanie wyników

  1. Jeśli utworzono klaster, w danych wyjściowych terraform apply polecenia skopiuj link obok cluster_url, a następnie wklej go na pasku adresu przeglądarki internetowej.

  2. Jeśli utworzono notes, w danych wyjściowych terraform apply polecenia skopiuj link obok notebook_url, a następnie wklej go na pasku adresu przeglądarki internetowej.

    Uwaga

    Przed użyciem notesu może być konieczne dostosowanie jego zawartości. Zapoznaj się z powiązaną dokumentacją dotyczącą dostosowywania notesu.

  3. Jeśli utworzono zadanie, w danych wyjściowych terraform apply polecenia skopiuj link obok job_url, a następnie wklej go na pasku adresu przeglądarki internetowej.

    Uwaga

    Przed uruchomieniem notesu może być konieczne dostosowanie jego zawartości. Zapoznaj się z linkami na początku tego artykułu, aby uzyskać powiązaną dokumentację dotyczącą dostosowywania notesu.

  4. Jeśli utworzono zadanie, uruchom zadanie w następujący sposób:

    1. Kliknij pozycję Uruchom teraz na stronie zadania.
    2. Po zakończeniu działania zadania, aby wyświetlić wyniki przebiegu zadania, na liście Ukończone przebiegi (ostatnie 60 dni) na stronie zadania kliknij ostatni wpis czasu w kolumnie Godzina rozpoczęcia. W okienku Dane wyjściowe zostanie wyświetlony wynik uruchomienia kodu notesu.

Krok 4. Czyszczenie

W tym kroku usuniesz poprzednie zasoby z obszaru roboczego.

  1. Sprawdź, co narzędzie Terraform zrobi w obszarze roboczym, zanim narzędzie Terraform rzeczywiście to zrobi, uruchamiając terraform plan polecenie .

    terraform plan
    
  2. Usuń klaster, notes i zadanie z obszaru roboczego, uruchamiając terraform destroy polecenie . Po wyświetleniu monitu o usunięcie wpisz yes i naciśnij Enter.

    terraform destroy
    

    Narzędzie Terraform usuwa zasoby określone w projekcie.