Compartir a través de


Aviso de obsolescencia y guía de migración de envío de trabajos de Spark

Advertencia

La tarea Envío de Spark está en desuso y está pendiente de eliminación. No se permite el uso de este tipo de tarea para los nuevos casos de uso y no se recomienda encarecidamente para los clientes existentes. Consulte Envío de Spark (heredado), donde encontrará la documentación original para este tipo de tarea. Siga leyendo las instrucciones de migración.

¿Por qué spark Submit está en desuso?

El tipo de tarea Envío de Spark está en desuso debido a limitaciones técnicas y lacunas de funcionalidades que no están en las tareas JAR, Notebook o de Python script. Estas tareas ofrecen una mejor integración con las características de Databricks, un rendimiento mejorado y una mayor confiabilidad.

Medidas de desaprobación

Databricks implementa las siguientes medidas en relación con la descontinuación:

  • Creación restringida: solo los usuarios que han usado tareas de Envío de Spark en el mes anterior, a partir de noviembre de 2025, pueden crear nuevas tareas de envío de Spark . Si necesita una excepción, póngase en contacto con el soporte técnico de su cuenta.
  • Restricciones de versión de Databricks Runtime: el uso de envío de Spark está restringido a las versiones existentes de Databricks Runtime y a las versiones de mantenimiento. Las versiones existentes de Databricks Runtime con Spark Submit seguirán recibiendo versiones de mantenimiento de seguridad y de corrección de errores hasta que la característica se apague por completo. Databricks Runtime 17.3+ y 18.x+ no admitirán este tipo de tarea.
  • Advertencias de UI: aparecen advertencias en toda la interfaz de usuario de Databricks donde las tareas Spark Submit están en uso, y las comunicaciones se envían a los administradores de espacio de trabajo en cuentas de los usuarios existentes.

Migración de cargas de trabajo de JVM a tareas JAR

En el caso de las cargas de trabajo de JVM, migre las tareas de Envío de Spark a tareas JAR. Las tareas JAR proporcionan un mejor soporte de funciones e integración con Databricks.

Siga estos pasos para migrar:

  1. Cree una nueva tarea de JAR en su trabajo.
  2. En los parámetros de la tarea Envío de Spark , identifique los tres primeros argumentos. Por lo general, siguen este patrón: ["--class", "org.apache.spark.mainClassName", "dbfs:/path/to/jar_file.jar"]
  3. Quite el --class parámetro .
  4. Establezca el nombre de clase principal (por ejemplo, org.apache.spark.mainClassName) como clase Main para la tarea JAR.
  5. Proporcione la ruta de acceso al archivo JAR (por ejemplo, dbfs:/path/to/jar_file.jar) en la configuración de la tarea JAR.
  6. Copie los argumentos restantes de su tarea Spark Submit a los parámetros de la tarea JAR.
  7. Ejecute la tarea JAR y compruebe que funciona según lo previsto.

Para obtener información detallada sobre cómo configurar tareas JAR, vea Tarea JAR.

Migración de cargas de trabajo de R

Si está iniciando un script de R directamente desde una tarea Spark Submit, hay varias rutas de migración disponibles.

Opción A: Utilizar tareas de notebook

Migre el script de R a un cuaderno de Databricks. Las tareas de cuaderno admiten un conjunto completo de características, incluido el escalado automático del clúster, y proporcionan una mejor integración con la plataforma de Databricks.

Opción B: Scripts de Bootstrap R desde una tarea de Notebook

Use una tarea de Notebook para iniciar tus scripts de R. Cree un cuaderno con el código siguiente y haga referencia al archivo de R como parámetro de trabajo. Modifique para agregar parámetros usados por el script de R, si es necesario:

dbutils.widgets.text("script_path", "", "Path to script")
script_path <- dbutils.widgets.get("script_path")
source(script_path)

Búsqueda de trabajos que usan tareas de envío de Spark

Puede usar los siguientes scripts de Python para identificar los trabajos del área de trabajo que contienen tareas de envío de Spark. Se necesitará un acceso personal válido u otro token y se debe usar la dirección URL del área de trabajo .

Opción A: Análisis rápido (ejecutar esto primero, solo trabajos persistentes)

Este script solo examina los trabajos persistentes (creados a través /jobs/create de o la interfaz web) y no incluye trabajos efímeros creados a través de /runs/submit. Este es el método recomendado de primera elección para identificar el uso de "Spark Submit" porque es mucho más rápido.

#!/usr/bin/env python3
"""
Requirements:
    databricks-sdk>=0.20.0

Usage:
    export DATABRICKS_HOST="https://your-workspace.cloud.databricks.com"
    export DATABRICKS_TOKEN="your-token"
    python3 list_spark_submit_jobs.py

Output:
    CSV format with columns: Job ID, Owner ID/Email, Job Name

Incorrect:
    export DATABRICKS_HOST="https://your-workspace.cloud.databricks.com/?o=12345678910"
"""

import csv
import os
import sys
from databricks.sdk import WorkspaceClient
from databricks.sdk.errors import PermissionDenied


def main():
    # Get credentials from environment
    workspace_url = os.environ.get("DATABRICKS_HOST")
    token = os.environ.get("DATABRICKS_TOKEN")

    if not workspace_url or not token:
        print(
            "Error: Set DATABRICKS_HOST and DATABRICKS_TOKEN environment variables",
            file=sys.stderr,
        )
        sys.exit(1)

    # Initialize client
    client = WorkspaceClient(host=workspace_url, token=token)

    # Scan workspace for persistent jobs with Spark Submit tasks
    # Using list() to scan only persistent jobs (faster than list_runs())
    print(
        "Scanning workspace for persistent jobs with Spark Submit tasks...",
        file=sys.stderr,
    )
    jobs_with_spark_submit = []
    total_jobs = 0

    # Iterate through all jobs (pagination is handled automatically by the SDK)
    skipped_jobs = 0
    for job in client.jobs.list(expand_tasks=True, limit=25):
        try:
            total_jobs += 1
            if total_jobs % 1000 == 0:
                print(f"Scanned {total_jobs} jobs total", file=sys.stderr)

            # Check if job has any Spark Submit tasks
            if job.settings and job.settings.tasks:
                has_spark_submit = any(
                    task.spark_submit_task is not None for task in job.settings.tasks
                )

                if has_spark_submit:
                    # Extract job information
                    job_id = job.job_id
                    owner_email = job.creator_user_name or "Unknown"
                    job_name = job.settings.name or f"Job {job_id}"

                    jobs_with_spark_submit.append(
                        {"job_id": job_id, "owner_email": owner_email, "job_name": job_name}
                    )
        except PermissionDenied:
            # Skip jobs that the user doesn't have permission to access
            skipped_jobs += 1
            continue

    # Print summary to stderr
    print(f"Scanned {total_jobs} jobs total", file=sys.stderr)
    if skipped_jobs > 0:
        print(
            f"Skipped {skipped_jobs} jobs due to insufficient permissions",
            file=sys.stderr,
        )
    print(
        f"Found {len(jobs_with_spark_submit)} jobs with Spark Submit tasks",
        file=sys.stderr,
    )
    print("", file=sys.stderr)

    # Output CSV to stdout
    if jobs_with_spark_submit:
        writer = csv.DictWriter(
            sys.stdout,
            fieldnames=["job_id", "owner_email", "job_name"],
            quoting=csv.QUOTE_MINIMAL,
        )
        writer.writeheader()
        writer.writerows(jobs_with_spark_submit)
    else:
        print("No jobs with Spark Submit tasks found.", file=sys.stderr)


if __name__ == "__main__":
    main()

Opción B: Examen completo (más lento, incluye trabajos efímeros de los últimos 30 días)

Si necesita identificar trabajos efímeros creados a través de /runs/submit, use este script más exhaustivo. Este script escanea todas las ejecuciones de trabajos de los últimos 30 días en su área de trabajo, incluidos los trabajos persistentes (creados a través de /jobs/create) y los trabajos efímeros. Este script puede tardar horas en ejecutarse en áreas de trabajo grandes.

#!/usr/bin/env python3
"""
Requirements:
    databricks-sdk>=0.20.0

Usage:
    export DATABRICKS_HOST="https://your-workspace.cloud.databricks.com"
    export DATABRICKS_TOKEN="your-token"
    python3 list_spark_submit_runs.py

Output:
    CSV format with columns: Job ID, Run ID, Owner ID/Email, Job/Run Name

Incorrect:
    export DATABRICKS_HOST="https://your-workspace.cloud.databricks.com/?o=12345678910"
"""

import csv
import os
import sys
import time
from databricks.sdk import WorkspaceClient
from databricks.sdk.errors import PermissionDenied


def main():
    # Get credentials from environment
    workspace_url = os.environ.get("DATABRICKS_HOST")
    token = os.environ.get("DATABRICKS_TOKEN")

    if not workspace_url or not token:
        print(
            "Error: Set DATABRICKS_HOST and DATABRICKS_TOKEN environment variables",
            file=sys.stderr,
        )
        sys.exit(1)

    # Initialize client
    client = WorkspaceClient(host=workspace_url, token=token)

    thirty_days_ago_ms = int((time.time() - 30 * 24 * 60 * 60) * 1000)

    # Scan workspace for runs with Spark Submit tasks
    # Using list_runs() instead of list() to include ephemeral jobs created via /runs/submit
    print(
        "Scanning workspace for runs with Spark Submit tasks from the last 30 days... (this will take more than an hour in large workspaces)",
        file=sys.stderr,
    )
    runs_with_spark_submit = []
    total_runs = 0
    seen_job_ids = set()

    # Iterate through all runs (pagination is handled automatically by the SDK)
    skipped_runs = 0
    for run in client.jobs.list_runs(
        expand_tasks=True,
        limit=25,
        completed_only=True,
        start_time_from=thirty_days_ago_ms,
    ):
        try:
            total_runs += 1
            if total_runs % 1000 == 0:
                print(f"Scanned {total_runs} runs total", file=sys.stderr)

            # Check if run has any Spark Submit tasks
            if run.tasks:
                has_spark_submit = any(
                    task.spark_submit_task is not None for task in run.tasks
                )

                if has_spark_submit:
                    # Extract job information from the run
                    job_id = run.job_id if run.job_id else "N/A"
                    run_id = run.run_id if run.run_id else "N/A"
                    owner_email = run.creator_user_name or "Unknown"
                    # Use run name if available, otherwise try to construct a name
                    run_name = run.run_name or (
                        f"Run {run_id}" if run_id != "N/A" else "Unnamed Run"
                    )

                    # Track unique job IDs to avoid duplicates for persistent jobs
                    # (ephemeral jobs may have the same job_id across multiple runs)
                    key = (job_id, run_id)
                    if key not in seen_job_ids:
                        seen_job_ids.add(key)
                        runs_with_spark_submit.append(
                            {
                                "job_id": job_id,
                                "run_id": run_id,
                                "owner_email": owner_email,
                                "job_name": run_name,
                            }
                        )
        except PermissionDenied:
            # Skip runs that the user doesn't have permission to access
            skipped_runs += 1
            continue

    # Print summary to stderr
    print(f"Scanned {total_runs} runs total", file=sys.stderr)
    if skipped_runs > 0:
        print(
            f"Skipped {skipped_runs} runs due to insufficient permissions",
            file=sys.stderr,
        )
    print(
        f"Found {len(runs_with_spark_submit)} runs with Spark Submit tasks",
        file=sys.stderr,
    )
    print("", file=sys.stderr)

    # Output CSV to stdout
    if runs_with_spark_submit:
        writer = csv.DictWriter(
            sys.stdout,
            fieldnames=["job_id", "run_id", "owner_email", "job_name"],
            quoting=csv.QUOTE_MINIMAL,
        )
        writer.writeheader()
        writer.writerows(runs_with_spark_submit)
    else:
        print("No runs with Spark Submit tasks found.", file=sys.stderr)


if __name__ == "__main__":
    main()

¿Necesita ayuda?

Si necesita ayuda adicional, póngase en contacto con el soporte técnico de su cuenta.