使用 Azure Batch 執行容器工作負載

警告

這篇文章參考 CentOS,這是接近生命週期結束 (EOL) 狀態的 Linux 發行版本。 請據以考慮您的使用方式和規劃。 如需詳細資訊,請參閱 CentOS 生命週期結束指引

Azure Batch 可讓您在 Azure 上執行和擴展大量批次運算作業。 Batch 工作可以直接在 Batch 集區中的虛擬機器 (節點) 上執行,但您也可以設定 Batch 集區,以在節點上的 Docker 相容容器中執行工作。 本文說明如何建立支援執行容器工作的計算節點集區,然後在集區上執行容器工作。

這裡的程式代碼範例會使用 Batch .NET 和 Python SDK。 您也可以使用其他 Batch SDK 和工具,包括 Azure 入口網站,來建立已啟用容器的 Batch 集區,以及執行容器工作。

為何要使用容器?

容器可讓您輕鬆執行 Batch 工作,而不需要管理環境和相依性來執行應用程式。 容器會將應用程式部署為輕量型、可攜、自給自足的單位,可以在數個不同環境中執行。 例如,在本機建置及測試容器,然後將容器映像上傳至 Azure 或其他位置的登錄。 容器部署模型可確保應用程式運行時間環境一律會在您裝載應用程式的位置正確安裝及設定。 Batch 中的容器型工作也可以利用非容器工作的功能,包括應用程式封裝和資源檔與輸出檔案管理。

必要條件

您應該熟悉容器概念,以及如何建立 Batch 集區和作業。

  • SDK 版本:Batch SDK 支援容器映射,如下列版本所示:

    • Batch REST API 2017-09-01.6.0 版
    • Batch .NET SDK 8.0.0 版
    • Batch Python SDK 4.0 版
    • Batch Java SDK 3.0 版
    • Batch Node.js SDK 3.0 版
  • 帳戶:在您的 Azure 訂用帳戶中,您必須建立 Batch 帳戶,並選擇性地建立 Azure 儲存體 帳戶。

  • 支援的虛擬機 (VM) 映射:只有使用虛擬機組態建立的集區才支援容器,來自支援的映像(下一節所列)。 如果您提供自定義映像,請參閱下一節中的考慮,以及使用受控映像來建立自定義映射集區的需求。

注意

從 Batch SDK 版本:

  • Batch .NET SDK 16.0.0 版
  • Batch Python SDK 14.0.0 版
  • Batch Java SDK 11.0.0 版
  • Batch Node.js SDK 11.0.0 版

目前, containerConfiguration 需要 Type 傳遞 屬性,且支援的值為: ContainerType.DockerCompatibleContainerType.CriCompatible

請記住下列限制:

  • Batch 僅針對在Linux集區上執行的容器提供遠端直接記憶體存取 (RDMA) 支援。
  • 針對 Windows 容器工作負載,您應該為集區選擇多核心 VM 大小。

重要

根據預設,Docker 會建立具有 子網規格的網路 172.17.0.0/16網橋。 如果您要為集區指定 虛擬網路 ,請確定沒有衝突的IP範圍。

支援的 VM 映像

使用下列其中一個支援的 Windows 或 Linux 映射來建立容器工作負載的 VM 計算節點集區。 如需與 Batch 相容的 Marketplace 映像詳細資訊,請參閱 虛擬機映射清單。

Windows 支援

Batch 支援具有容器支援指定之 Windows 伺服器映像。 如果映像支援 Docker 容器,則列出 Batch 中所有支援的映像的 API 表示 DockerCompatible 功能。 Batch 允許,但不直接支援Mirantis發行且功能為的映像。DockerCompatible 這些映像只能部署在使用者訂用帳戶集區配置模式 Batch 帳戶下。

您也可以建立 自定義映像 ,以在 Windows 上啟用容器功能。

注意

映射 SKU -with-containers-with-containers-smalldisk 已淘汰。 如需詳細數據和替代容器運行時間選項, 請參閱公告

Linux 支援

針對 Linux 容器工作負載,Batch 目前支援在 Azure Marketplace 中發佈的下列 Linux 映像,而不需要自定義映像。

  • 出版商: microsoft-dsvm
    • 提供: ubuntu-hpc

替代影像選項

目前還有其他映像可 microsoft-azure-batch 支援容器工作負載:

  • 出版商: microsoft-azure-batch
    • 提供: centos-container
    • 供應專案: centos-container-rdma (僅適用於 VM SKU 與 Infiniband)
    • 提供: ubuntu-server-container
    • 供應專案: ubuntu-server-container-rdma (僅適用於 VM SKU 與 Infiniband)

重要

建議使用 microsoft-dsvmubuntu-hpc VM 映射,而不是由 發佈的 microsoft-azure-batch映像。 此映像可用於任何 VM SKU。

備註

上述映像的 Docker 資料根目錄位於不同位置:

  • 針對 Azure Batch 已發布 microsoft-azure-batch 的映像(供應專案: centos-container-rdma等.),Docker 數據根目錄會對應至 位於暫存磁碟上的 /mnt/batch/docker
  • 針對 HPC 映射或 microsoft-dsvm (供應專案: ubuntu-hpc等等),Docker 數據根目錄與 Docker 預設值不同,也就是 Linux 上的 /var/lib/docker ,而 Windows 上的 C:\ProgramData\Docker 。 這些資料夾位於OS磁碟上。

針對非 Batch 發佈的映像,OS 磁碟在下載容器映射時,可能會有快速填滿的風險。

客戶的潛在解決方案

在 BatchExplorer 中建立集區時,變更開始工作中 Docker 數據根目錄。 以下是啟動工作命令的範例:

1)  sudo systemctl stop docker
2)  sudo vi /lib/systemd/system/docker.service
    +++
    FROM:
    ExecStart=/usr/bin/docker daemon -H fd://
    TO:
    ExecStart=/usr/bin/docker daemon -g /new/path/docker -H fd://
    +++
3)  sudo systemctl daemon-reload
4)  sudo systemctl start docker

這些映像僅支援在 Azure Batch 集區中使用,且適用於 Docker 容器執行。 其功能:

  • 預安裝的 Docker 相容 Moby 容器運行時間
  • 預安裝的 NVIDIA GPU 驅動程式和 NVIDIA 容器運行時間,以簡化 Azure N 系列 VM 上的部署。
  • 具有後綴的 -rdma VM 映射已預先設定,且支援 InfiniBand RDMA VM 大小。 這些 VM 映像不應與沒有 InfiniBand 支援的 VM 大小搭配使用。

您也可以在與 Batch 相容的其中一個 Linux 發行版上,建立 與 Batch 容器相容的自定義映像 。 針對自定義映像上的 Docker 支援,請安裝適當的 Docker 相容運行時間,例如 Docker 版本Mirantis 容器運行時間。 只安裝 Docker-CLI 相容工具是不夠的;需要 Docker 引擎相容運行時間。

重要

Microsoft 或 Azure Batch 都不會支援 Docker(任何版本或版本)、Mirantis Container Runtime 或 Moby 運行時間相關的問題。 選擇在映像中使用這些運行時間的客戶,應該與提供運行時間問題支援的公司或實體連絡。

使用自訂 Linux 映像的更多考慮:

  • 若要在使用自定義映射時利用 Azure N 系列大小的 GPU 效能,請預安裝 NVIDIA 驅動程式。 此外,您必須安裝適用於 NVIDIA GPU、 NVIDIA Docker 的 Docker 引擎公用程式。
  • 若要存取 Azure RDMA 網路,請使用支援 RDMA 的 VM 大小。 必要的 RDMA 驅動程式會安裝在 Batch 支援的 CentOS HPC 和 Ubuntu 映射中。 執行 MPI 工作負載可能需要額外的設定。 請參閱 在 Batch 集區中使用 RDMA 或 GPU 實例。

Batch 集區的容器組態

若要讓 Batch 集區執行容器工作負載,您必須在集區的 VirtualMachineConfiguration 物件中指定 ContainerConfiguration 設定。 本文提供 Batch .NET API 參考的連結。 對應的設定位於 Batch Python API 中。

您可以使用或不使用預先擷取的容器映射來建立已啟用容器的集區,如下列範例所示。 提取(或預先擷取)程式可讓您從 Docker Hub 或因特網上的另一個容器登錄預先載入容器映像。 為了獲得最佳效能,請在與 Batch 帳戶相同的區域中使用 Azure 容器登錄

預先擷取容器映像的好處是,當工作第一次開始執行時,不必等待容器映像下載。 容器組態會在建立集區時,將容器映像提取至 VM。 在集區上執行的工作接著可以參考容器映像的清單和容器執行選項。

沒有預先擷取容器映像的集區

若要設定未預先擷取容器映像的容器啟用集區,請定義 ContainerConfigurationVirtualMachineConfiguration 物件,如下列範例所示。 這些範例會從 Marketplace 使用適用於 Azure Batch 的 Ubuntu Server 容器集區映像。

注意:此範例中使用的Ubuntu伺服器版本僅供說明之用。 您可以隨意將node_agent_sku_id變更為您所使用的版本。

image_ref_to_use = batch.models.ImageReference(
    publisher='microsoft-dsvm',
    offer='ubuntu-hpc',
    sku='2204',
    version='latest')

"""
Specify container configuration. This is required even though there are no prefetched images.
"""

container_conf = batch.models.ContainerConfiguration()

new_pool = batch.models.PoolAddParameter(
    id=pool_id,
    virtual_machine_configuration=batch.models.VirtualMachineConfiguration(
        image_reference=image_ref_to_use,
        container_configuration=container_conf,
        node_agent_sku_id='batch.node.ubuntu 22.04'),
    vm_size='STANDARD_D2S_V3',
    target_dedicated_nodes=1)
...
ImageReference imageReference = new ImageReference(
    publisher: "microsoft-dsvm",
    offer: "ubuntu-hpc",
    sku: "2204",
    version: "latest");

// Specify container configuration. This is required even though there are no prefetched images.
ContainerConfiguration containerConfig = new ContainerConfiguration();

// VM configuration
VirtualMachineConfiguration virtualMachineConfiguration = new VirtualMachineConfiguration(
    imageReference: imageReference,
    nodeAgentSkuId: "batch.node.ubuntu 22.04");
virtualMachineConfiguration.ContainerConfiguration = containerConfig;

// Create pool
CloudPool pool = batchClient.PoolOperations.CreatePool(
    poolId: poolId,
    targetDedicatedComputeNodes: 1,
    virtualMachineSize: "STANDARD_D2S_V3",
    virtualMachineConfiguration: virtualMachineConfiguration);

預先擷取容器組態的映像

若要預先擷取集區上的容器映像,請將容器映像清單(container_image_names 在 Python 中)新增至 ContainerConfiguration

下列基本 Python 範例示範如何從 Docker Hub 預先擷取標準 Ubuntu 容器映像。

image_ref_to_use = batch.models.ImageReference(
    publisher='microsoft-dsvm',
    offer='ubuntu-hpc',
    sku='2204',
    version='latest')

"""
Specify container configuration, fetching the official Ubuntu container image from Docker Hub.
"""

container_conf = batch.models.ContainerConfiguration(
    container_image_names=['ubuntu'])

new_pool = batch.models.PoolAddParameter(
    id=pool_id,
    virtual_machine_configuration=batch.models.VirtualMachineConfiguration(
        image_reference=image_ref_to_use,
        container_configuration=container_conf,
        node_agent_sku_id='batch.node.ubuntu 22.04'),
    vm_size='STANDARD_D2S_V3',
    target_dedicated_nodes=1)
...

下列 C# 範例假設您想要從 Docker Hub 預先擷取 TensorFlow 映像。 此範例包含啟動工作,此工作會在集區節點上的 VM 主機上執行。 例如,您可以在主機中執行啟動工作,以掛接可從容器存取的文件伺服器。

ImageReference imageReference = new ImageReference(
    publisher: "microsoft-dsvm",
    offer: "ubuntu-hpc",
    sku: "2204",
    version: "latest");

ContainerRegistry containerRegistry = new ContainerRegistry(
    registryServer: "https://hub.docker.com",
    userName: "UserName",
    password: "YourPassword"
);

// Specify container configuration, prefetching Docker images
ContainerConfiguration containerConfig = new ContainerConfiguration();
containerConfig.ContainerImageNames = new List<string> { "tensorflow/tensorflow:latest-gpu" };
containerConfig.ContainerRegistries = new List<ContainerRegistry> { containerRegistry };

// VM configuration
VirtualMachineConfiguration virtualMachineConfiguration = new VirtualMachineConfiguration(
    imageReference: imageReference,
    nodeAgentSkuId: "batch.node.ubuntu 22.04");
virtualMachineConfiguration.ContainerConfiguration = containerConfig;

// Set a native host command line start task
StartTask startTaskContainer = new StartTask( commandLine: "<native-host-command-line>" );

// Create pool
CloudPool pool = batchClient.PoolOperations.CreatePool(
    poolId: poolId,
    virtualMachineSize: "Standard_NC6S_V3",
    virtualMachineConfiguration: virtualMachineConfiguration);

// Start the task in the pool
pool.StartTask = startTaskContainer;
...

從私人容器登錄預先擷取映像

您也可以藉由向私人容器登錄伺服器驗證來預先擷取容器映像。 在下列範例中, ContainerConfigurationVirtualMachineConfiguration 物件會從私人 Azure 容器登錄預先擷取私人 TensorFlow 映像。 影像參考與上一個範例中的相同。

image_ref_to_use = batch.models.ImageReference(
    publisher='microsoft-dsvm',
    offer='ubuntu-hpc',
    sku='2204',
    version='latest')

# Specify a container registry
container_registry = batch.models.ContainerRegistry(
        registry_server="myRegistry.azurecr.io",
        user_name="myUsername",
        password="myPassword")

# Create container configuration, prefetching Docker images from the container registry
container_conf = batch.models.ContainerConfiguration(
        container_image_names = ["myRegistry.azurecr.io/samples/myImage"],
        container_registries =[container_registry])

new_pool = batch.models.PoolAddParameter(
            id="myPool",
            virtual_machine_configuration=batch.models.VirtualMachineConfiguration(
                image_reference=image_ref_to_use,
                container_configuration=container_conf,
                node_agent_sku_id='batch.node.ubuntu 22.04'),
            vm_size='STANDARD_D2S_V3',
            target_dedicated_nodes=1)
// Specify a container registry
ContainerRegistry containerRegistry = new ContainerRegistry(
    registryServer: "myContainerRegistry.azurecr.io",
    userName: "myUserName",
    password: "myPassword");

// Create container configuration, prefetching Docker images from the container registry
ContainerConfiguration containerConfig = new ContainerConfiguration();
containerConfig.ContainerImageNames = new List<string> {
        "myContainerRegistry.azurecr.io/tensorflow/tensorflow:latest-gpu" };
containerConfig.ContainerRegistries = new List<ContainerRegistry> { containerRegistry } );

// VM configuration
VirtualMachineConfiguration virtualMachineConfiguration = new VirtualMachineConfiguration(
    imageReference: imageReference,
    nodeAgentSkuId: "batch.node.ubuntu 22.04");
virtualMachineConfiguration.ContainerConfiguration = containerConfig;

// Create pool
CloudPool pool = batchClient.PoolOperations.CreatePool(
    poolId: poolId,
    targetDedicatedComputeNodes: 2,
    virtualMachineSize: "Standard_NC6S_V3",
    virtualMachineConfiguration: virtualMachineConfiguration);
...

ACR 的受控識別支援

當您存取儲存在 Azure Container Registry 中的容器時,可以使用使用者名稱/密碼或受控識別來向服務進行驗證。 若要使用受控識別,請先確定身分識別已 指派給集 區,而身分識別具有 AcrPull 您想要存取之容器登錄的角色。 然後,指示 Batch 使用 ACR 進行驗證時要使用的身分識別。

ContainerRegistry containerRegistry = new ContainerRegistry(
    registryServer: "myContainerRegistry.azurecr.io",
    identityReference: new ComputeNodeIdentityReference() { ResourceId = "/subscriptions/SUB/resourceGroups/RG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/identity-name" }
);

// Create container configuration, prefetching Docker images from the container registry
ContainerConfiguration containerConfig = new ContainerConfiguration();
containerConfig.ContainerImageNames = new List<string> {
        "myContainerRegistry.azurecr.io/tensorflow/tensorflow:latest-gpu" };
containerConfig.ContainerRegistries = new List<ContainerRegistry> { containerRegistry } );

// VM configuration
VirtualMachineConfiguration virtualMachineConfiguration = new VirtualMachineConfiguration(
    imageReference: imageReference,
    nodeAgentSkuId: "batch.node.ubuntu 22.04");
virtualMachineConfiguration.ContainerConfiguration = containerConfig;

// Create pool
CloudPool pool = batchClient.PoolOperations.CreatePool(
    poolId: poolId,
    targetDedicatedComputeNodes: 2,
    virtualMachineSize: "Standard_NC6S_V3",
    virtualMachineConfiguration: virtualMachineConfiguration);
...

工作的容器設定

若要在已啟用容器的集區上執行容器工作,請指定容器特定的設定。 設定 包含要使用的映像、登錄和容器執行選項。

  • ContainerSettings使用工作類別的 屬性來設定容器特定的設定。 這些設定是由 TaskContainer 設定 類別所定義。 --rm容器選項不需要另一個選項--runtime,因為它由 Batch 負責。

  • 如果您在容器映像上執行工作, 雲端工作作業管理員工作 需要容器設定。 不過,啟動工作作業準備工作和作業發行工作不需要容器設定(也就是說,它們可以在容器內容中執行,或直接在節點上執行)。

  • 針對Linux,Batch會將使用者/群組許可權對應至容器。 如果存取容器內的任何資料夾需要 管理員 istrator 許可權,您可能需要以具有管理員提高許可權層級的集區範圍執行工作。 這可確保 Batch 在容器內容中以根目錄身分執行工作。 否則,非系統管理員使用者可能無法存取這些資料夾。

  • 對於已啟用 GPU 硬體的容器集區,Batch 會自動啟用容器工作的 GPU,因此您不應該包含 –gpus 自變數。

容器工作命令行

當您執行容器工作時,Batch 會自動使用 docker create 命令,使用工作中指定的映像來建立容器。 Batch 接著會控制容器中的工作執行。

如同非容器 Batch 工作,您可以為容器工作設定命令行。 因為 Batch 會自動建立容器,因此命令行只會指定在容器中執行的命令或命令。

如果 Batch 工作的容器映像是使用 ENTRYPOINT 腳本設定,您可以將命令行設定為使用預設 ENTRYPOINT 或覆寫它:

  • 若要使用容器映像的預設 ENTRYPOINT,請將工作命令行設定為空字串 ""

  • 若要覆寫預設 ENTRYPOINT,請新增 --entrypoint 自變數,例如: --entrypoint "/bin/sh - python"

  • 如果映像沒有 ENTRYPOINT,請設定適合容器的命令列,例如 或 /app/myapp/bin/sh -c python myscript.py

選擇性 ContainerRunOptions 是您提供給 docker create Batch 用來建立和執行容器之命令的其他自變數。 例如,若要設定容器的工作目錄,請設定 --workdir <directory> 選項。 如需更多選項, 請參閱 docker create 參考。

容器工作工作目錄

Batch 容器工作會在容器的工作目錄中執行,其類似於 Batch 為一般 (非容器) 工作設定的目錄。 如果在映像中設定此工作目錄,或預設容器工作目錄(C:\在 Windows 容器或 / Linux 容器上),則此工作目錄與 WORKDIR 不同

針對 Batch 容器工作:

  • 主機節點上下方的所有目錄(Azure Batch 目錄的根目錄)會以遞歸 AZ_BATCH_NODE_ROOT_DIR 方式對應到容器中。
  • 所有工作環境變數都會對應至容器。
  • 節點上的工作工作目錄 AZ_BATCH_TASK_WORKING_DIR 與一般工作設定相同,並對應至容器。

重要

針對具有暫時磁碟之 VM 系列上的 Windows 容器集區,由於 Windows 容器限制,整個暫時磁碟會對應至容器空間。

這些對應可讓您以與非容器工作相同的方式來處理容器工作。 例如,使用應用程式套件安裝應用程式、從 Azure 儲存體 存取資源檔、使用工作環境設定,以及在容器停止之後保存工作輸出檔案。

針對容器工作進行疑難解答

如果您的容器工作未如預期般執行,您可能需要取得容器映像之 WORKDIR 或 ENTRYPOINT 設定的相關信息。 若要查看組態,請 執行 Docker 映像檢查 命令。

如有需要,請根據映像調整容器工作的設定:

  • 在工作命令行中指定絕對路徑。 如果影像的預設 ENTRYPOINT 用於工作命令行,請確定已設定絕對路徑。
  • 在工作的容器執行選項中,變更工作目錄以符合映像中的 WORKDIR。 例如,設定 --workdir /app

容器工作範例

下列 Python 代碼段顯示從 Docker Hub 提取的虛構映像所建立容器中執行的基本命令行。 在這裡, --rm 容器選項會在工作完成之後移除容器,而 選項會 --workdir 設定工作目錄。 命令行會使用簡單的殼層命令覆寫容器 ENTRYPOINT,以將小型檔案寫入主機上的工作工作目錄。

task_id = 'sampletask'
task_container_settings = batch.models.TaskContainerSettings(
    image_name='myimage',
    container_run_options='--rm --workdir /')
task = batch.models.TaskAddParameter(
    id=task_id,
    command_line='/bin/sh -c \"echo \'hello world\' > $AZ_BATCH_TASK_WORKING_DIR/output.txt\"',
    container_settings=task_container_settings
)

下列 C# 範例顯示雲端工作的基本容器設定:

// Simple container task command
string cmdLine = "c:\\app\\myApp.exe";

TaskContainerSettings cmdContainerSettings = new TaskContainerSettings (
    imageName: "myimage",
    containerRunOptions: "--rm --workdir c:\\app"
    );

CloudTask containerTask = new CloudTask (
    id: "Task1",
    commandline: cmdLine);
containerTask.ContainerSettings = cmdContainerSettings;

下一步