Samouczek: uruchamianie równoległego obciążenia przy użyciu usługi Azure Batch przy użyciu interfejsu API języka Python

Usługa Azure Batch umożliwia wydajne uruchamianie zadań wsadowych obliczeń równoległych i obliczeń o wysokiej wydajności (HPC, large-scale parallel and high-performance computing) na platformie Azure. Ten samouczek przedstawia przykład równoległego uruchamiania zadań z użyciem technologii Batch w języku Python. Poznasz powszechny przepływ pracy aplikacji Batch oraz jak współpracować programistycznie z zasobami Batch i Storage.

  • Uwierzytelnij się za pomocą kont Batch i Storage.
  • Przekazywanie plików wejściowych do usługi Storage.
  • Utwórz pulę węzłów obliczeniowych, aby uruchomić aplikację.
  • Utwórz zadanie oraz zadania do przetwarzania plików wejściowych.
  • Monitorowanie wykonywania zadań.
  • Pobieranie plików wyjściowych.

W tym samouczku przekonwertujesz pliki multimedialne MP4 na format MP3, równolegle przy użyciu narzędzia open source ffmpeg .

Jeśli nie masz jeszcze konta platformy Azure, przed rozpoczęciem utwórz bezpłatne konto.

Wymagania wstępne

Udziel dostępu do swoich kont Batch i Storage

Ten samouczek pokazuje, jak uwierzytelniać się w usługach Azure Batch i Azure Storage przy użyciu identyfikatora Microsoft Entra ID oraz DefaultAzureCredential. Aplikacja nie używa kluczy do konta. Przed uruchomieniem aplikacji upewnij się, że używana przez Ciebie tożsamość ma wymagane role na obu kontach.

  1. Zaloguj się za pomocą Azure CLI. DefaultAzureCredential Automatycznie wykrywa to logowanie:

    az login
    
  2. Przypisz swojemu kontu użytkownika rolę, która umożliwia operacje na płaszczyźnie danych na koncie Batch, na przykład Azure Batch Data Contributor. Ta rola jest wymagana do tworzenia pul, zadań i czynności. Możesz przypisać tę rolę na stronie Kontrola dostępu (IAM) dla konta usługi Batch w witrynie Azure Portal lub użyć interfejsu wiersza polecenia platformy Azure:

    az role assignment create \
        --assignee "<your-user-principal-name>" \
        --role "Azure Batch Data Contributor" \
        --scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Batch/batchAccounts/<batch-account-name>"
    
  3. Przypisz swojemu kontu użytkownika rolę Storage Blob Data Contributor na koncie pamięci. Ta rola jest potrzebna do tworzenia kontenerów, przekazywania plików wejściowych oraz uzyskiwania klucza delegacji użytkownika, który podpisuje adresy URL sygnatur dostępu współdzielonego (SAS) używane przez zadania:

    az role assignment create \
        --assignee "<your-user-principal-name>" \
        --role "Storage Blob Data Contributor" \
        --scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account-name>"
    
  4. Zwróć uwagę na następujące wartości, które dodajesz do pliku config.py próbki w następnej sekcji. Znajdziesz je na stronie Przegląd każdego konta w portalu Azure:

    • Nazwa konta wsadowego
    • Adres URL konta wsadowego, na przykład https://mybatchaccount.westus2.batch.azure.com
    • Nazwa konta magazynu

Note

Propagacja przypisań ról może potrwać kilka minut. Jeśli aplikacja zawiedzie i pojawi się błąd autoryzacji zaraz po przypisaniu ról, poczekaj kilka minut i spróbuj ponownie.

Pobieranie i uruchamianie przykładowej aplikacji

Ważna

Przykład do pobrania z repozytorium batch-python-ffmpeg-tutorial jest aktualizowany, aby był zgodny z tym samouczkiem. Dopóki ta aktualizacja nie zostanie opublikowana, repozytorium może nadal zawierać wcześniejsze uwierzytelnianie oparte na kluczu oraz kod Ubuntu 20.04. Kod opisany w tym artykule jest źródłem prawdy. Jeśli pobrana próbka nie odpowiada zamieszczonym tutaj fragmentom kodu, postępuj zgodnie z kodem pokazanym w tym artykule.

Pobieranie przykładowej aplikacji

Pobierz lub sklonuj przykładową aplikację z usługi GitHub. Aby sklonować repozytorium przykładowej aplikacji za pomocą klienta Git, użyj następującego polecenia:

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

Przejdź do katalogu zawierającego plik batch_python_tutorial_ffmpeg.py.

W środowisku języka Python zainstaluj wymagane pakiety przy użyciu polecenia pip.

pip install -r requirements.txt

Użyj edytora kodu, aby otworzyć config.py pliku. Zaktualizuj wartości usługi Batch i konta magazynu, używając unikatowych nazw Twoich kont. W przykładzie użyto poświadczenia DefaultAzureCredential do uwierzytelniania, więc klucze konta nie są już wymagane. Na przykład:

_BATCH_ACCOUNT_NAME = 'yourbatchaccount'
_BATCH_ACCOUNT_URL = 'https://yourbatchaccount.yourbatchregion.batch.azure.com'
_STORAGE_ACCOUNT_NAME = 'mystorageaccount'

Upewnij się, że zalogowano się przy użyciu az login oraz że do Twojej tożsamości przypisano role opisane w sekcji Przyznawanie dostępu do kont Batch i Storage. DefaultAzureCredentialmoże także odkrywać inne źródła poświadczeń, takie jak zarządzana tożsamość, Visual Studio Code czy zmienne środowiskowe.

Uruchom aplikację

Aby uruchomić skrypt:

python batch_python_tutorial_ffmpeg.py

Po uruchomieniu aplikacji przykładowej dane wyjściowe w konsoli będą wyglądać mniej więcej następująco. W czasie wykonywania nastąpi wstrzymanie operacji w momencie wyświetlenia komunikatu Monitoring all tasks for 'Completed' state, timeout in 00:30:00... podczas uruchamiania węzłów obliczeniowych puli.

Sample start: 11/28/2018 3:20:21 PM

Container [input] created.
Container [output] created.
Uploading file LowPriVMs-1.mp4 to container [input]...
Uploading file LowPriVMs-2.mp4 to container [input]...
Uploading file LowPriVMs-3.mp4 to container [input]...
Uploading file LowPriVMs-4.mp4 to container [input]...
Uploading file LowPriVMs-5.mp4 to container [input]...
Creating pool [LinuxFFmpegPool]...
Creating job [LinuxFFmpegJob]...
Adding 5 tasks to job [LinuxFFmpegJob]...
Monitoring all tasks for 'Completed' state, timeout in 00:30:00...
Success! All tasks reached the 'Completed' state within the specified timeout period.
Deleting container [input]....

Sample end: 11/28/2018 3:29:36 PM
Elapsed time: 00:09:14.3418742

Przejdź do konta usługi Batch w witrynie Azure Portal, aby monitorować pulę, węzły obliczeniowe, zadanie i zadania podrzędne. Aby na przykład wyświetlić mapę cieplną węzłów obliczeniowych w puli, wybierz pozycję Pule>LinuxFFmpegPool.

Podczas wykonywania zadań mapa cieplna wygląda następująco:

Zrzut ekranu przedstawiający mapę cieplną puli.

Typowy czas wykonywania wynosi około 5 minut po uruchomieniu aplikacji w domyślnej konfiguracji. Tworzenie puli zajmuje najwięcej czasu.

Pobieranie plików wyjściowych

Przy użyciu witryny Azure Portal można pobrać wyjściowe pliki MP3 wygenerowane przez zadania ffmpeg.

  1. Kliknij Wszystkie usługi>Konta magazynu i kliknij nazwę swojego konta magazynu.
  2. Kliknij Blob>wyjście.
  3. Kliknij prawym przyciskiem myszy jeden z wyjściowych plików MP3, a następnie kliknij polecenie Pobierz. Postępuj zgodnie z monitami wyświetlanymi w przeglądarce, aby otworzyć lub zapisać plik.

Pobieranie pliku wyjściowego

Mimo że nie pokazano tego w tym przykładzie, pliki można również pobrać programowo z węzłów obliczeniowych lub z kontenera magazynu.

Przeglądanie kodu

W poniższych sekcjach przykładowa aplikacja jest rozłożona na kroki dotyczące przetwarzania obciążenia w usłudze Batch. Zapoznaj się z kodem języka Python podczas czytania pozostałej części tego artykułu, ponieważ nie omówiono każdego wiersza kodu w przykładzie.

Uwierzytelnianie klientów obiektów Blob i klientów Batch

Przykład uwierzytelnia się zarówno w usłudze Storage, jak i w usłudze Batch przy użyciu polecenia DefaultAzureCredential z pakietu azure-identity . DefaultAzureCredential próbuje po kolei wielu typów poświadczeń (zmienne środowiskowe, tożsamość zarządzana, logowanie za pomocą Azure CLI itd.), dzięki czemu ten sam kod działa zarówno podczas programowania lokalnego, jak i w środowisku produkcyjnym, bez konieczności przechowywania kluczy konta.

Aby uzyskać dostęp do konta magazynu danych, aplikacja używa pakietu azure-storage-blob do utworzenia obiektu BlobServiceClient, który używa tych poświadczeń.

Próbka importuje następujące typy tożsamości i pamięci oraz odczytuje nazwy kont z config.py:

import config
from azure.identity import DefaultAzureCredential
from azure.storage.blob import (
    BlobServiceClient,
    BlobSasPermissions,
    ContainerSasPermissions,
    generate_blob_sas,
    generate_container_sas,
)
credential = DefaultAzureCredential()

blob_service_client = BlobServiceClient(
    account_url=f"https://{config._STORAGE_ACCOUNT_NAME}.blob.core.windows.net/",
    credential=credential)

Aplikacja tworzy obiekt BatchClient w celu tworzenia pul, zadań i zadań podrzędnych w usłudze Batch oraz zarządzania nimi. Klient usługi Batch używa tego samego DefaultAzureCredential do uwierzytelniania za pośrednictwem Microsoft Entra ID.

batch_client = BatchClient(
    endpoint=config._BATCH_ACCOUNT_URL,
    credential=credential)

Węzły obliczeniowe usługi Batch uzyskują dostęp do kontenerów wejściowych i wyjściowych za pomocą adresów URL z sygnaturą dostępu współdzielonego (SAS). Ponieważ aplikacja nie używa klucza konta storage, nie może podpisywać tokenów SAS za jego użyciem. Zamiast tego aplikacja żąda klucza delegacji użytkownika od usługi Blob, która jest podpisana logowaniami Microsoft Entra aplikacji, i używa tego klucza do generowania tokenów SAS. Aby uzyskać więcej informacji, zobacz Tworzenie sygnatury dostępu współdzielonego (SAS) delegowanego przez użytkownika.

start = datetime.datetime.now(datetime.timezone.utc)
expiry = start + datetime.timedelta(hours=4)
user_delegation_key = blob_service_client.get_user_delegation_key(
    key_start_time=start, key_expiry_time=expiry)

# Sign the SAS tokens with the same expiry as the user delegation key.
sas_expiry = expiry

Note

Klucz delegacji użytkownika w tym przykładzie jest ważny przez cztery godziny. Token SAS podpisany przy użyciu klucza delegacji użytkownika nie może być ważny dłużej niż ten klucz, a klucz delegacji użytkownika może być ważny maksymalnie siedem dni. W przypadku długotrwałych obciążeń należy zażądać nowego klucza i wygenerować ponownie adresy URL SAS przed ich wygaśnięciem.

Przekazywanie plików wejściowych

Po utworzeniu kontenerów wejściowych i wyjściowych z blob_service_client, aplikacja przesyła każdy lokalny plik MP4 z folderu InputFiles do kontenera wejściowego. Poniższy upload_file_to_container pomocnik przesyła pojedynczy plik, generuje dla niego token SAS tylko do odczytu, podpisany kluczem delegacji użytkownika, oraz zwraca obiekt Batch ResourceFile , którego adres URL zawiera token SAS, aby Batch mógł później pobrać plik do węzła obliczeniowego. Aplikacja wywołuje ten helper raz dla każdego pliku wejściowego:

def upload_file_to_container(blob_service_client, user_delegation_key,
                             sas_expiry, container_name, file_path):
    blob_name = os.path.basename(file_path)
    blob_client = blob_service_client.get_blob_client(container_name, blob_name)

    with open(file_path, "rb") as data:
        blob_client.upload_blob(data, overwrite=True)

    sas_token = generate_blob_sas(
        account_name=config._STORAGE_ACCOUNT_NAME,
        container_name=container_name,
        blob_name=blob_name,
        user_delegation_key=user_delegation_key,
        permission=BlobSasPermissions(read=True),
        expiry=sas_expiry)

    sas_url = f"{blob_client.url}?{sas_token}"

    return models.ResourceFile(http_url=sas_url, file_path=blob_name)

Aplikacja generuje także adres URL SAS dla kontenera wyjściowego, który daje dostęp do zapisu. Zadania wykorzystują ten adres URL do przesyłania plików wyjściowych do pamięci masowej:

sas_token = generate_container_sas(
    account_name=config._STORAGE_ACCOUNT_NAME,
    container_name=output_container_name,
    user_delegation_key=user_delegation_key,
    permission=ContainerSasPermissions(write=True, create=True, list=True),
    expiry=sas_expiry)

output_container_sas_url = (
    f"https://{config._STORAGE_ACCOUNT_NAME}.blob.core.windows.net/"
    f"{output_container_name}?{sas_token}")

Tworzenie puli węzłów obliczeniowych

Następnie przykład tworzy pulę węzłów obliczeniowych na koncie Batch, wywołując create_pool. Ta zdefiniowana funkcja używa klasy BatchPoolCreateOptions , aby ustawić liczbę węzłów, rozmiar maszyny wirtualnej i konfigurację puli. W tej konfiguracji obiekt VirtualMachineConfiguration określa BatchVmImageReference dla obrazu LTS Ubuntu Server 22.04 opublikowanego w Azure Marketplace. Usługa Batch obsługuje szeroki zakres obrazów maszyn wirtualnych z witryny Azure Marketplace oraz niestandardowe obrazy maszyn wirtualnych.

Liczba węzłów i rozmiar maszyny wirtualnej są ustawiane przy użyciu zdefiniowanych stałych. Usługa Batch obsługuje dedykowane węzły i węzły typu spot, a w pulach można używać obu tych węzłów. Dla Twojej puli są zarezerwowane węzły dedykowane. Węzły typu spot są oferowane w obniżonej cenie z nadwyżkowej pojemności maszyn wirtualnych na platformie Azure. Węzły typu spot stają się niedostępne, jeśli platforma Azure nie ma wystarczającej pojemności. Przykład domyślnie tworzy pulę zawierającą tylko pięć węzłów typu spot o rozmiarze Standard_A1_v2.

Oprócz właściwości węzła fizycznego ta konfiguracja puli zawiera obiekt BatchStartTask . Funkcja BatchStartTask jest wykonywana w każdym węźle, gdy węzeł jest przyłączany do puli i za każdym razem, gdy węzeł zostanie uruchomiony ponownie. W tym przykładzie usługa BatchStartTask uruchamia polecenia powłoki Bash w celu zainstalowania pakietu ffmpeg i zależności w węzłach.

Metoda create_pool przesyła pulę do usługi Batch.

new_pool = models.BatchPoolCreateOptions(
    id=pool_id,
    virtual_machine_configuration=models.VirtualMachineConfiguration(
        image_reference=models.BatchVmImageReference(
            publisher="canonical",
            offer="0001-com-ubuntu-server-jammy",
            sku="22_04-lts",
            version="latest"
        ),
        node_agent_sku_id="batch.node.ubuntu 22.04"),
    vm_size=_POOL_VM_SIZE,
    target_dedicated_nodes=_DEDICATED_POOL_NODE_COUNT,
    target_low_priority_nodes=_LOW_PRIORITY_POOL_NODE_COUNT,
    start_task=models.BatchStartTask(
        command_line="/bin/bash -c \"apt-get update && apt-get install -y ffmpeg\"",
        wait_for_success=True,
        user_identity=models.UserIdentity(
            auto_user=models.AutoUserSpecification(
                scope=models.AutoUserScope.POOL,
                elevation_level=models.ElevationLevel.ADMIN)),
    )
)
batch_client.create_pool(pool=new_pool)

Note

Obrazy maszyn wirtualnych w witrynie Marketplace oraz agenci węzłów usługi Batch mają daty zakończenia wsparcia. Obrazy Ubuntu Server 20.04 LTS oraz agent węzła batch.node.ubuntu 20.04 nie są już obsługiwane w nowych pulach usługi Batch. Aby wyświetlić listę odwołań do obrazów i jednostek SKU agentów węzłów, które są obecnie obsługiwane przez Twoje konto usługi Batch, wywołaj metodę list_supported_images.

Utwórz pracę

Zadanie usługi Batch określa pulę do uruchamiania zadań oraz opcjonalne ustawienia, takie jak priorytet i harmonogram pracy. Przykład tworzy zadanie przez wywołanie create_job. Ta funkcja wykorzystuje klasę BatchJobCreateOptions do utworzenia zadania w Twojej puli. Metoda create_job przekazuje zadanie do usługi Batch. Początkowo praca nie ma zadań.

job = models.BatchJobCreateOptions(
    id=job_id,
    pool_info=models.BatchPoolInfo(pool_id=pool_id))

batch_client.create_job(job=job)

Tworzenie zadań

Aplikacja tworzy zadania w zadaniu za pomocą wywołania metody add_tasks. Ta zdefiniowana funkcja tworzy listę obiektów zadań przy użyciu klasy BatchTaskCreateOptions . Każde zadanie uruchamia narzędzie ffmpeg w celu przetworzenia obiektu wejściowego resource_files przy użyciu parametru command_line . Narzędzie ffmpeg było już zainstalowane na wszystkich węzłach podczas tworzenia puli. Tutaj wiersz polecenia jest używany do uruchomienia narzędzia ffmpeg w celu przekonwertowania każdego z plików wejściowych w formacie MP4 (wideo) na format MP3 (audio).

Przykładowa aplikacja tworzy obiekt OutputFile dla pliku MP3 po uruchomieniu wiersza polecenia. Pliki wyjściowe każdego zadania (w tym przypadku jeden) są przekazywane do kontenera w połączonym koncie magazynowym, używając właściwości zadania output_files.

Następnie aplikacja dodaje zadania do zadania za pomocą metody create_tasks , która kolejkuje je do uruchomienia w węzłach obliczeniowych.

tasks = list()

for idx, input_file in enumerate(input_files):
    input_file_path = input_file.file_path
    output_file_path = "".join((input_file_path).split('.')[:-1]) + '.mp3'
    command = "/bin/bash -c \"ffmpeg -i {} {} \"".format(
        input_file_path, output_file_path)
    tasks.append(models.BatchTaskCreateOptions(
        id='Task{}'.format(idx),
        command_line=command,
        resource_files=[input_file],
        output_files=[models.OutputFile(
            file_pattern=output_file_path,
            destination=models.OutputFileDestination(
                container=models.OutputFileBlobContainerDestination(
                    container_url=output_container_sas_url)),
            upload_options=models.OutputFileUploadConfiguration(
                upload_condition=models.OutputFileUploadCondition.TASK_SUCCESS))]
    )
    )
batch_client.create_tasks(job_id=job_id, task_collection=tasks)

Monitorowanie zadań

Gdy zadania są dodawane do zadania, usługa Batch automatycznie kolejkuje je i planuje ich wykonywanie w węzłach obliczeniowych w skojarzonej puli. Na podstawie podanych ustawień usługa Batch obsługuje wszystkie zadania kolejkowania, planowania, ponawiania i innych zadań administracyjnych.

Istnieje wiele podejść do monitorowania wykonywania zadań. Funkcja wait_for_tasks_to_complete w tym przykładzie używa obiektu BatchTaskState do monitorowania zadań dla określonego stanu, w tym przypadku stanu ukończonego w ramach limitu czasu.

while datetime.datetime.now() < timeout_expiration:
    print('.', end='')
    sys.stdout.flush()
    tasks = batch_client.list_tasks(job_id=job_id)

    incomplete_tasks = [task for task in tasks if
                        task.state != models.BatchTaskState.COMPLETED]
    if not incomplete_tasks:
        print()
        return True
    else:
        time.sleep(5)
...

Czyszczenie zasobów

Po wykonaniu zadań aplikacja automatycznie usuwa utworzony wejściowy kontener magazynu. Daje również możliwość usunięcia puli Batch i zadania. Metody begin_delete_job i begin_delete_pool klasy BatchClient każda rozpoczyna odpowiednią operację usuwania po potwierdzeniu monitu. Chociaż opłaty nie są naliczane za same zadania i czynności, są one naliczane za węzły obliczeniowe. Dlatego przydzielaj pule tylko w razie potrzeby. Gdy usuniesz pulę, wszystkie dane wyjściowe zadań na węzłach zostaną usunięte. Jednak pliki wyjściowe pozostają na koncie magazynowym.

Gdy grupa zasobów, konto usługi Batch i konto magazynu nie będą już potrzebne, usuń je. Aby to zrobić w witrynie Azure Portal, wybierz grupę zasobów dla konta usługi Batch i wybierz pozycję Usuń grupę zasobów.

Następne kroki

W tym samouczku nauczyłeś się następujących rzeczy:

  • Uwierzytelnij się za pomocą kont Batch i Storage.
  • Przekazywanie plików wejściowych do usługi Storage.
  • Utwórz pulę węzłów obliczeniowych, aby uruchomić aplikację.
  • Utwórz zadanie oraz zadania do przetwarzania plików wejściowych.
  • Monitorowanie wykonywania zadań.
  • Pobieranie plików wyjściowych.

Aby uzyskać więcej przykładów użycia interfejsu API języka Python do planowania i przetwarzania obciążeń usługi Batch , zobacz Przykłady języka Python usługi Batch w witrynie GitHub.