Inicio rápido: Uso de Python API para ejecutar un trabajo de Azure Batch

Para empezar a trabajar con Azure Batch, utilice Python API para ejecutar un trabajo de Azure Batch desde una aplicación. La aplicación carga archivos de datos de entrada en Azure Storage y crea un grupo de nodos de proceso de Batch (máquinas virtuales). Luego, crea un trabajo que ejecuta tareas para procesar todos los archivo de entrada del grupo mediante un comando básico.

Tras completar este inicio rápido, conocerá los conceptos clave del servicio Batch y estará listo para probar dicho servicio con cargas de trabajo más realistas y a mayor escala.

Introducción al flujo de trabajo de Azure Batch

Prerrequisitos

  • Una cuenta de Azure con una suscripción activa. Cree una cuenta gratuita.

  • Una cuenta de Batch y una cuenta de Azure Storage vinculada. Para crear estas cuentas, consulte las guías de inicio rápido de Batch con Azure Portal o la CLI de Azure.

  • Python, versión 3.6, o posteriores, incluido el administrador de paquetes pip.

Inicio de sesión en Azure

Inicie sesión en Azure Portal en https://portal.azure.com.

Obtención de credenciales de la cuenta

En este ejemplo, debe especificar las credenciales de las cuentas de Batch y Storage. Azure Portal es una manera sencilla de obtener las credenciales necesarias. (también se pueden obtener mediante las API de Azure o las herramientas de línea de comandos).

  1. Seleccione Todos los servicios>Cuentas de Batch y, después, seleccione el nombre de la cuenta de Batch.

  2. Para ver las credenciales de Batch, haga clic en Claves. Copie los valores de cuenta de Batch, URL y Clave de acceso principal en un editor de texto.

  3. Para ver el nombre y las claves de la cuenta de almacenamiento, seleccione Cuenta de almacenamiento. Copie los valores de Nombre de la cuenta de almacenamiento y Key1 en un editor de texto.

Descarga del ejemplo

Descargue o clone la aplicación de ejemplo desde GitHub. Para clonar el repositorio de la aplicación de ejemplo con un cliente de Git, use el siguiente comando:

git clone https://github.com/Azure-Samples/batch-python-quickstart.git

Vaya al directorio que contiene el script de Python python_quickstart_client.py.

En el entorno de desarrollo de Python, instale los paquetes necesarios mediante pip.

pip install -r requirements.txt

Abra el archivo config.py. Actualice las cadenas de credenciales tanto de Batch como de la cuenta de almacenamiento con los valores obtenidos para sus cuentas. Por ejemplo:

BATCH_ACCOUNT_NAME = 'mybatchaccount'
BATCH_ACCOUNT_KEY = 'xxxxxxxxxxxxxxxxE+yXrRvJAqT9BlXwwo1CwF+SwAYOxxxxxxxxxxxxxxxx43pXi/gdiATkvbpLRl3x14pcEQ=='
BATCH_ACCOUNT_URL = 'https://mybatchaccount.mybatchregion.batch.azure.com'
STORAGE_ACCOUNT_NAME = 'mystorageaccount'
STORAGE_ACCOUNT_KEY = 'xxxxxxxxxxxxxxxxy4/xxxxxxxxxxxxxxxxfwpbIC5aAWA8wDu+AFXZB827Mt9lybZB1nUcQbQiUrkPtilK5BQ=='

Ejecución la aplicación

Para ver el flujo de trabajo de Batch en acción, ejecute el script:

python python_quickstart_client.py

Después de ejecutar el script, examine el código para ver qué es lo que hace cada parte de la aplicación.

Al ejecutar la aplicación de ejemplo, la salida de la consola es similar a la siguiente. Durante la ejecución, se experimenta una pausa en Monitoring all tasks for 'Completed' state, timeout in 00:30:00... mientras se inician los nodos de proceso del grupo. Las tareas se ponen en cola para ejecutarse en cuanto lo haga el primer nodo de proceso. Vaya a la cuenta de Batch en Azure Portal para supervisar el grupo, los nodos de proceso, el trabajo y las tareas en su cuenta de Batch.

Sample start: 11/26/2018 4:02:54 PM

Uploading file taskdata0.txt to container [input]...
Uploading file taskdata1.txt to container [input]...
Uploading file taskdata2.txt to container [input]...
Creating pool [PythonQuickstartPool]...
Creating job [PythonQuickstartJob]...
Adding 3 tasks to job [PythonQuickstartJob]...
Monitoring all tasks for 'Completed' state, timeout in 00:30:00...

Cuando finalicen las tareas, verá una salida similar a la siguiente en cada tarea:

Printing task output...
Task: Task0
Node: tvm-2850684224_3-20171205t000401z
Standard output:
Batch processing began with mainframe computers and punch cards. Today it still plays a central role in business, engineering, science, and other pursuits that require running lots of automated tasks....
...

Habitualmente, el tiempo de ejecución es de, aproximadamente, 3 minutos cuando la aplicación se ejecuta con su configuración predeterminada. La mayor parte del tiempo lo ocupa la configuración inicial del grupo.

Revisión del código

En esta guía de inicio rápido, la aplicación de Python realiza las siguientes operaciones:

  • Carga tres archivos de texto pequeños en un contenedor de blobs de su cuenta de Azure Storage. Estos archivos son entradas que las tareas de Batch procesan.
  • Crea un grupo de dos nodos de proceso que ejecutan Ubuntu 20.04 LTS.
  • Crea un trabajo y tres tareas que se ejecutan en los nodos. Cada tarea procesa uno de los archivos de entrada mediante una línea de comandos del shell de Bash.
  • Muestra los archivos devueltos por las tareas.

Para más información, consulte las secciones siguientes y vea el archivo python_quickstart_client.py.

Pasos preliminares

Para interactuar con una cuenta de almacenamiento, la aplicación crea un objeto BlobServiceClient.

blob_service_client = BlobServiceClient(
        account_url=f"https://{config.STORAGE_ACCOUNT_NAME}.{config.STORAGE_ACCOUNT_DOMAIN}/",
        credential=config.STORAGE_ACCOUNT_KEY
    )

La aplicación usa la referencia blob_service_client para crear un contenedor en la cuenta de almacenamiento y cargar archivos de datos en el contenedor. Los archivos de almacenamiento se definen como objetos ResourceFile de Batch para que el servicio los descargue después en nodos de proceso.

input_file_paths = [os.path.join(sys.path[0], 'taskdata0.txt'),
                    os.path.join(sys.path[0], 'taskdata1.txt'),
                    os.path.join(sys.path[0], 'taskdata2.txt')]

input_files = [
    upload_file_to_container(blob_service_client, input_container_name, file_path)
    for file_path in input_file_paths]

La aplicación crea un objeto BatchServiceClient para crear y administrar los grupos, los trabajos y las tareas en el servicio Batch. El cliente de Batch del ejemplo utiliza la autenticación de clave compartida. Batch también admite la autenticación de Azure Active Directory.

credentials = SharedKeyCredentials(config.BATCH_ACCOUNT_NAME,
        config.BATCH_ACCOUNT_KEY)

    batch_client = BatchServiceClient(
        credentials,
        batch_url=config.BATCH_ACCOUNT_URL)

Creación de un grupo de nodos de proceso

Para crear un grupo de Batch, la aplicación usa la clase PoolAddParameter para establecer el número de nodos, el tamaño de la máquina virtual y una configuración de grupo. En este caso, un objeto VirtualMachineConfiguration especifica un valor de ImageReference a una imagen de Ubuntu Server 20.04 LTS publicada en Azure Marketplace. Batch es compatible con una amplia gama de imágenes de Linux y Windows Server de Azure Marketplace, así como con las imágenes de máquina virtual personalizadas.

El número de nodos (POOL_NODE_COUNT) y el tamaño de la máquina virtual (POOL_VM_SIZE) son constantes definidas. De forma predeterminada el ejemplo crea un grupo de dos nodos de tamaño Standard_DS1_v2. El tamaño que se sugiere ofrece un buen equilibrio entre rendimiento y costo para este ejemplo rápido.

El método pool.add envía el grupo al servicio Batch.

new_pool = batchmodels.PoolAddParameter(
        id=pool_id,
        virtual_machine_configuration=batchmodels.VirtualMachineConfiguration(
            image_reference=batchmodels.ImageReference(
                publisher="canonical",
                offer="0001-com-ubuntu-server-focal",
                sku="20_04-lts",
                version="latest"
            ),
            node_agent_sku_id="batch.node.ubuntu 20.04"),
        vm_size=config.POOL_VM_SIZE,
        target_dedicated_nodes=config.POOL_NODE_COUNT
    )
    batch_service_client.pool.add(new_pool)

Creación de un trabajo de Batch

Un trabajo de Batch es una agrupación lógica de una o varias tareas. Un trabajo incluye valores comunes para las tareas, como la prioridad y el grupo en el que se ejecutan las tareas. La aplicación usa la clase JobAddParameter para crear un trabajo en el grupo. El método job.add agrega un trabajo a la cuenta de Batch especificada. Inicialmente, el trabajo no tiene tareas.

job = batchmodels.JobAddParameter(
    id=job_id,
    pool_info=batchmodels.PoolInformation(pool_id=pool_id))

batch_service_client.job.add(job)

Creación de tareas

La aplicación crea una lista de objetos de tarea mediante la clase TaskAddParameter. Cada tarea procesa un objeto resource_files de entrada mediante un parámetro command_line. En el ejemplo, la línea de comandos ejecuta el comando cat del shell de Bash para mostrar el archivo de texto. Este comando es un ejemplo sencillo para fines de demostración. Cuando se usa Batch, la línea de comandos es el lugar en el que se especifica la aplicación o el script. Batch proporciona varias formas de implementar aplicaciones y scripts en nodos de proceso.

A continuación, la aplicación agrega tareas al trabajo con el método task.add_collection, que las pone en cola para que se ejecuten en los nodos de proceso.

tasks = []

for idx, input_file in enumerate(resource_input_files):
    command = f"/bin/bash -c \"cat {input_file.file_path}\""
    tasks.append(batchmodels.TaskAddParameter(
        id=f'Task{idx}',
        command_line=command,
        resource_files=[input_file]
    )
    )

batch_service_client.task.add_collection(job_id, tasks)

Visualización de la salida de la tarea

La aplicación supervisa el estado de la tarea para asegurarse de que completan las tareas. Luego, la aplicación muestra el archivo stdout.txt que ha generado cada una de las tareas que se completa. Cuando la tarea se ejecuta correctamente, la salida del comando de la tarea se escribe en stdout.txt:

tasks = batch_service_client.task.list(job_id)

for task in tasks:

    node_id = batch_service_client.task.get(job_id, task.id).node_info.node_id
    print(f"Task: {task.id}")
    print(f"Node: {node_id}")

    stream = batch_service_client.file.get_from_task(
        job_id, task.id, config.STANDARD_OUT_FILE_NAME)

    file_text = _read_stream_as_string(
        stream,
        text_encoding)

    if text_encoding is None:
        text_encoding = DEFAULT_ENCODING

    sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding = text_encoding)
    sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding = text_encoding)

    print("Standard output:")
    print(file_text)

Limpieza de recursos

La aplicación elimina automáticamente el contenedor de almacenamiento que crea y ofrece la opción de eliminar el grupo y el trabajo de Batch. Se cobran el grupo mientras que los nodos estén en ejecución, aunque no haya trabajos programados. Cuando no necesite el grupo, elimínelo. Al eliminar el grupo, las salidas de tarea de los nodos también se eliminan.

Cuando ya no los necesite, elimine el grupo de recursos, la cuenta de Batch y la de Storage. Para hacerlo desde Azure Portal, seleccione el grupo de recursos de la cuenta de Batch y seleccione Eliminar grupo de recursos.

Pasos siguientes

En esta guía de inicio rápido, se ha ejecutado una aplicación pequeña compilada mediante la API de Python de Batch para crear un grupo de Batch y un trabajo de Batch. El trabajo ha ejecutado tareas de ejemplo y ha descargado la salida que se ha creado en los nodos. Ahora que conoce los conceptos clave del servicio Batch, ya esta listo para probar dicho servicio con cargas de trabajo más realistas y a mayor escala. Para más información acerca de Azure Batch y examinar una carga de trabajo en paralelo con una aplicación real, diríjase al tutorial de Python de Batch.