使用 Azure Batch 在 Azure 中有效率地執行大規模的平行和高效能運算 (HPC) 批次作業。 本教學課程會逐步解說使用 Batch 執行平行工作負載的 Python 範例。 您會了解 Batch 應用程式的通用工作流程,以及如何以程式設計方式與 Batch 和儲存體資源進行互動。
- 驗證 Batch 和儲存體帳戶。
- 將輸入檔案上傳至儲存體。
- 建立計算節點的集區來執行應用程式。
- 建立作業和工作來處理輸入檔案。
- 監控任務執行。
- 擷取輸出檔案。
在本教學課程中,您會使用 ffmpeg 開放原始碼工具將 MP4 媒體檔案平行轉換為 MP3 格式。
如果您沒有 Azure 帳戶,請在開始之前建立 免費帳戶 。
先決條件
授與您的 Batch 和儲存體帳戶的存取權
這個教學展示了如何使用 Microsoft Entra ID 搭配 DefaultAzureCredential 來驗證 Azure Batch 和 Azure 儲存體。 這個應用程式不會使用帳號金鑰。 執行應用程式前,請確認你所使用的身分在兩個帳戶中皆具有必要的角色。
請使用 Azure CLI 登入。
DefaultAzureCredential會自動偵測到這次登入:az login為你的使用者帳號指派一個角色,允許在批次帳號上進行資料平面操作,例如 Azure Batch Data Contributor。 此角色需要建立資源池、工作與任務。 你可以在 Azure 入口網站的批次帳號存取控制(IAM)頁面上指定角色,或使用 Azure CLI:
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>"將你的使用者帳號指定為儲存帳號上的 Storage Blob 資料貢獻者 角色。 此角色需要建立容器、上傳輸入檔案,並請求簽署任務所使用的共享存取簽章(SAS)URL 的使用者委派金鑰:
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>"請注意以下數值,請在下一節加入樣本的 config.py 檔。 你可以在 Azure 入口網站中每個帳戶的總覽頁面找到它們:
- 批次帳號名稱
- 批次帳戶 URL,例如
https://mybatchaccount.westus2.batch.azure.com - 儲存體帳戶名稱
Note
角色指派可能需要幾分鐘才會生效。 如果應用程式在你指派角色後立刻出現授權錯誤失敗,請等幾分鐘再試一次。
下載及執行範例應用程式
Important
batch-python-ffmpeg-tutorial 倉庫中可下載的範例正在更新以符合此教學。 在該更新發布前,倉庫可能仍包含早期的基於金鑰的認證和 Ubuntu 20.04 程式碼。 本文中的程式碼是真實的來源。 如果下載的樣本與這裡的片段不符,請依照本文所示的程式碼操作。
下載範例應用程式
從 GitHub 下載或複製範例應用程式。 若要使用 Git 用戶端複製範例應用程式存放庫,請使用下列命令:
git clone https://github.com/Azure-Samples/batch-python-ffmpeg-tutorial.git
流覽至包含 檔案batch_python_tutorial_ffmpeg.py的目錄。
在您的 Python 環境中,使用 pip安裝必要的套件。
pip install -r requirements.txt
使用程式代碼編輯器開啟 檔案 config.py。 使用您帳戶專屬的名稱更新 Batch 和儲存體帳戶值。 範例使用 DefaultAzureCredential 來認證,因此不再需要帳號金鑰。 例如:
_BATCH_ACCOUNT_NAME = 'yourbatchaccount'
_BATCH_ACCOUNT_URL = 'https://yourbatchaccount.yourbatchregion.batch.azure.com'
_STORAGE_ACCOUNT_NAME = 'mystorageaccount'
請確認你是使用 az login 登入,且你的身分具有 授與 Batch 和儲存體帳戶的存取權 中所述的角色。
DefaultAzureCredential也能發現其他憑證來源,例如管理身份、Visual Studio Code 或環境變數。
執行應用程式
執行指令碼:
python batch_python_tutorial_ffmpeg.py
當您執行範例應用程式時,主控台輸出大致如下。 在執行期間,集區的計算節點啟動後,您會在 Monitoring all tasks for 'Completed' state, timeout in 00:30:00... 遇到暫停。
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
請前往 Azure 入口網站中的 Batch 帳戶,以監視集區、計算節點、作業和任務。 例如,若要查看集區中計算節點的熱度圖,請選取 [集區]> [LinuxFFmpegPool]。
當工作正在執行時,熱度圖會如下所示:
一般運行時間大約是 5 分鐘 ,當您在其預設組態中執行應用程式。 建立集區佔用大部分的時間。
擷取輸出檔案
您可以使用 Azure 入口網站來下載 ffmpeg 工作所產生的 MP3 輸出檔案。
- 按一下 [所有服務]>[儲存體帳戶],然後按一下您的儲存體帳戶名稱。
- 按一下 [Blob]> [輸出]。
- 以滑鼠右鍵按一下其中一個 MP3 輸出檔案,然後按 [下載]。 請依照瀏覽器的提示開啟或儲存檔案。
此範例雖未示範,但您也可以用程式設計方式從計算節點或儲存體容器下載檔案。
檢閱程式碼
後面各節將範例應用程式細分為用來處理 Batch 服務中工作負載的數個步驟。 當您閱讀本文的其餘部分時,請參閱 Python 程式代碼,因為不會討論範例中的每一行程序代碼。
驗證 Blob 和 Batch 用戶端
範例使用 DefaultAzureCredential(來自 azure-identity 套件),同時向 Storage 和 Batch 進行驗證。
DefaultAzureCredential 嘗試依序嘗試多種憑證類型(環境變數、管理身份、Azure CLI登入等),使同一程式碼在本地開發和生產環境中都能運作,且不儲存帳號金鑰。
要與儲存帳號互動,應用程式會使用 azure-storage-blob 套件來建立一個使用 credential 的 BlobServiceClient 物件。
範例匯入以下身份與儲存類型,並從 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)
應用程式會建立一個 BatchClient 物件,用來建立和管理批次服務中的池、工作與任務。 批次用戶端使用相同的 DefaultAzureCredential 透過 Microsoft Entra ID 進行認證。
batch_client = BatchClient(
endpoint=config._BATCH_ACCOUNT_URL,
credential=credential)
批次運算節點透過共享存取簽章(SAS)網址存取輸入與輸出容器。 因為應用程式不使用儲存帳號金鑰,無法用它簽署 SAS 代幣。 相反地,應用程式會向 Blob 服務請求一組使用者委派金鑰,該金鑰以應用程式的 Microsoft Entra 憑證簽署,並用該金鑰產生 SAS 憑證。 如需詳細資訊,請參閱建立使用者委派 SAS。
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
此範例中的使用者委派金鑰有效期為四小時。 用使用者委派金鑰簽署的 SAS 憑證無法超過金鑰的壽命,而使用者委派金鑰最多可有效七天。 對於長時間執行的工作負載,請申請新的金鑰,並在 SAS URL 到期之前重新產生 SAS URL。
上傳輸入檔案
在建立輸入和輸出容器後 blob_service_client,應用程式會將 InputFiles 資料夾中的每個本地 MP4 檔案上傳到輸入容器。 以下 upload_file_to_container 的輔助程式上傳單一檔案,產生一個只讀的 SAS 標記,該標記以使用者委派金鑰簽署,並回傳一個 Batch ResourceFile 物件,其 URL 包含 SAS 標記,讓 Batch 之後能將檔案下載到運算節點。 應用程式會對每個輸入檔案呼叫此輔助器一次:
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)
應用程式也會為輸出容器產生一個 SAS URL,授予寫入權限。 任務使用此網址將其輸出檔案上傳至儲存空間:
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}")
建立計算節點的集區
接著,範例會透過呼叫 create_pool,在 Batch 帳戶中建立計算節點集區。 此定義函式使用 Batch BatchPoolCreateOptions 類別來設定節點數量、虛擬機大小及池組態。 在此配置中,VirtualMachineConfiguration 物件指定一個 BatchVmImageReference,指向發佈於 Azure Marketplace 的 Ubuntu Server 22.04 LTS 映像。 Batch 支援 Azure Marketplace 中各式各樣的 VM 映像,以及自訂 VM 映像。
使用已定義的常數可設定節點數目和 VM 大小。 Batch 支援專用節點和現成品節點,而您可以在集區中使用其中一種或同時使用兩種。 專用節點會保留給您的集區使用。 現成品節點則會以較低的價格從 Azure 中的剩餘容量提供。 如果 Azure 沒有足夠的容量,現成節點將無法使用。 根據預設,此範例會建立集區,其大小只有五個 Spot 節點 Standard_A1_v2。
除了實體節點屬性外,此池配置還包含一個 BatchStartTask 物件。 BatchStartTask 會在每個節點加入池時執行,每次節點重啟時也會執行。 在此範例中,BatchStartTask 執行 Bash shell 指令,安裝節點上的 ffmpeg 套件及依賴關係。
create_pool 方法將池提交給批次服務。
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
Marketplace 虛擬機映像檔和批次節點代理都有支援結束日期。 Ubuntu Server 20.04 LTS 映像檔及 batch.node.ubuntu 20.04 節點代理已不再支援新的批次池。 要列出你的批次帳號目前支援的映像參考和節點代理 SKU,請呼叫 list_supported_images 方法。
建立職位
Batch 工作會指定要在其中執行工作的集區及選擇性設定,例如工作的優先順序和排程。 該範例透過呼叫 create_job來建立一個工作。 此已定義的函式會使用 BatchJobCreateOptions 類別,在您的集區上建立作業。
create_job 方法會將工作提交給批次服務。 一開始這份工作沒有任何任務。
job = models.BatchJobCreateOptions(
id=job_id,
pool_info=models.BatchPoolInfo(pool_id=pool_id))
batch_client.create_job(job=job)
建立任務
應用程式會藉由呼叫 add_tasks 在作業中建立工作。 此定義函式使用 BatchTaskCreateOptions 類別建立任務物件清單。 每個工作都會執行 ffmpeg,以使用 resource_files 參數處理輸入command_line物件。 ffmpeg 已在先前建立集區時安裝於每個節點上。 在此,命令列會執行 ffmpeg,將每個輸入 MP4 (影片) 檔案轉換為 MP3 (音訊) 檔案。
此範例會在執行命令列之後,為 MP3 檔案建立 OutputFile 物件。 每個任務的輸出檔案(在此案例中一個)會使用任務的 output_files 屬性上傳至已連結的儲存帳戶中的容器。
接著,應用程式會用 create_tasks 方法將任務加入工作,並排隊在運算節點上執行。
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)
監視工作
當任務被新增至作業時,Batch 會自動將它們排入佇列,並排程它們在相關聯集區中的計算節點上執行。 根據您指定的設定,Batch 會處理所有工作佇列、排程、重試和其他工作管理職責。
監視工作執行的方法有很多種。 此範例中的 wait_for_tasks_to_complete 函式會使用 BatchTaskState 物件,在時限內監視任務是否處於特定狀態,在此情況下為已完成狀態。
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)
...
清理資源
應用程式在執行工作之後,會自動刪除它所建立的輸入儲存體容器,並且為您提供用於刪除 Batch 集區和工作的選項。 類別中的 begin_delete_job 和 BatchClient 方法在確認提示符時各自啟動相應的刪除操作。 雖然你不需為工作和任務本身收費,但計算節點則需收費。 因此,僅依需求分配池。 當您刪除集區時,節點上的所有工作輸出也會跟著刪除。 不過,輸出檔案會保留在儲存體帳戶中。
若不再需要,可刪除資源群組、Batch 帳戶和儲存體帳戶。 若要在 Azure 入口網站中這樣做,請選取 Batch 帳戶的資源群組,然後選擇 [ 刪除資源群組]。
後續步驟
在本教程中,您將學到如何:
- 驗證 Batch 和儲存體帳戶。
- 將輸入檔案上傳至儲存體。
- 建立計算節點的集區來執行應用程式。
- 建立作業和工作來處理輸入檔案。
- 監控任務執行。
- 擷取輸出檔案。
如需使用 Python API 排程及處理 Batch 工作負載的更多範例,請參閱 GitHub 上的 Batch Python 範例 。