Compartilhar via


Criar clusters, notebooks e trabalhos com o Terraform

Este artigo mostra como usar o provedor Terraform do Databricks para criar um cluster, um notebook e um trabalho em um workspace existente do Azure Databricks.

Este artigo é um complemento aos seguintes artigos de introdução do Azure Databricks:

Você também pode adaptar as configurações do Terraform descritas neste artigo para criar clusters, notebooks e trabalhos personalizados nos seus workspaces.

Etapa 1: Criar e configurar o projeto Terraform

  1. Crie um projeto Terraform seguindo as instruções na seção Requisitos do artigo de visão geral do provedor do Databricks Terraform.

  2. Para criar um cluster, crie um arquivo chamado cluster.tf e adicione o seguinte conteúdo ao arquivo. Esse conteúdo cria um cluster com a menor quantidade de recursos permitidos. Esse cluster usa a última versão do Databricks Runtime LTS (Suporte de Longo Prazo).

    Para um cluster que funciona com o Catálogo do 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
    }
    

    Para um cluster para todas as finalidades:

    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. Para criar um cluster, crie outro arquivo chamado cluster.auto.tfvars e adicione o seguinte conteúdo ao arquivo. Esse arquivo contém valores de variáveis para personalizar o cluster. Substitua os valores do espaço reservado pelos seus.

    Para um cluster que funciona com o Catálogo do Unity:

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

    Para um cluster para todas as finalidades:

    cluster_name                    = "My Cluster"
    cluster_autotermination_minutes = 60
    cluster_num_workers             = 1
    
  4. Para criar um notebook, crie outro arquivo chamado notebook.tf e adicione o seguinte conteúdo ao arquivo:

    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. Se você estiver criando um cluster, salve o seguinte código do notebook em um arquivo no mesmo diretório do arquivo notebook.tf:

    Para o notebook do Python para Tutorial: executar um pipeline de análise de ponta a ponta do lakehouse, um arquivo nomeado notebook-getting-started-lakehouse-e2e.py com o seguinte conteúdo:

    # 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)
    

    Para o notebook do Python para Guia de Início Rápido: Executar um trabalho do Spark no workspace do Azure Databricks usando o portal do Azure, um arquivo chamado notebook-quickstart-create-databricks-workspace-portal.py com o seguinte conteúdo:

    # 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. Se você estiver criando um notebook, crie outro arquivo chamado notebook.auto.tfvars e adicione o seguinte conteúdo ao arquivo. Esse arquivo contém valores de variáveis para personalizar a configuração do notebook.

    Para o notebook do Python para Tutorial: executar um pipeline de análise de ponta a ponta do lakehouse:

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

    Para o notebook do Python para Guia de Início Rápido: Executar um trabalho do Spark no workspace do Azure Databricks usando o portal do Azure:

    notebook_subdirectory = "Terraform"
    notebook_filename     = "notebook-quickstart-create-databricks-workspace-portal.py"
    notebook_language     = "PYTHON"
    
  7. Se você estiver criando um notebook, no workspace do Azure Databricks, lembre-se de configurar todos os requisitos para que o notebook seja executado com sucesso, referindo-se às seguintes instruções para:

  8. Para criar o trabalho, crie outro arquivo chamado job.tf e adicione o conteúdo a seguir ao arquivo. Esse conteúdo cria um trabalho para executar o notebook.

    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. Se você estiver criando um trabalho, crie outro arquivo chamado job.auto.tfvars e adicione o conteúdo a seguir ao arquivo. Este arquivo contém um valor de variável para personalizar a configuração do trabalho.

    job_name = "My Job"
    task_key = "my_task"
    

Etapa 2: Executar as configurações

Nesta etapa, você executará as configurações do Terraform para implantar o cluster, o notebook e o trabalho no workspace do Azure Databricks.

  1. Verifique se as configurações do Terraform são válidas executando o comando terraform validate. Se forem relatados erros, corrija-os e execute o comando novamente.

    terraform validate
    
  2. Verifique o que o Terraform fará no seu workspace, antes que ele realmente o faça, executando o comando terraform plan.

    terraform plan
    
  3. Implante o cluster, o notebook e o trabalho no seu workspace executando o comando terraform apply. Quando a implantação for solicitada, digite yes e pressione ENTER.

    terraform apply
    

    O Terraform implantará os recursos especificados no seu projeto. A implantação desses recursos (especialmente um cluster) pode levar vários minutos.

Etapa 3: Explorar os resultados

  1. Se você criou um cluster, na saída do comando terraform apply, copie o link ao lado de cluster_url e cole-o na barra de endereços do navegador da Web.

  2. Se você criou um notebook, na saída do comando terraform apply, copie o link ao lado de notebook_url e cole-o na barra de endereços do navegador da Web.

    Observação

    Antes de usar o notebook, talvez seja necessário personalizar o conteúdo dele. Confira a documentação relacionada sobre como personalizar o notebook.

  3. Se você criou um trabalho, na saída do comando terraform apply, copie o link ao lado de job_url e cole-o na barra de endereços do navegador da Web.

    Observação

    Antes de executar o notebook, talvez seja necessário personalizar o conteúdo dele. Confira os links no início deste artigo para ver a documentação relacionada sobre como personalizar o notebook.

  4. Se você criou um trabalho, execute o trabalho da seguinte maneira:

    1. Clique em Executar agora na página do trabalho.
    2. Quando o trabalho terminar de ser executado, para exibir os resultados da execução dele, na lista Execuções concluídas (últimos 60 dias) na página do trabalho, clique na entrada de hora mais recente na coluna Hora de Início. O painel Saída mostra o resultado da execução do código do notebook.

Etapa 4: Limpeza

Nesta etapa, você excluirá os recursos anteriores do workspace.

  1. Verifique o que o Terraform fará no seu workspace, antes que ele realmente o faça, executando o comando terraform plan.

    terraform plan
    
  2. Exclua o cluster, o notebook e o trabalho do workspace executando o comando terraform destroy. Quando a exclusão for solicitada, digite yes e pressione ENTER.

    terraform destroy
    

    O Terraform excluirá os recursos especificados do seu projeto.