자습서: .NET API를 사용하여 Azure Batch에서 병렬 워크로드 실행
클라우드에서 Azure Batch를 사용하여 대규모 병렬 및 HPC(고성능 컴퓨팅) 일괄 작업을 Azure에서 효율적으로 실행합니다. 이 자습서는 Batch를 사용하여 병렬 워크로드를 실행하는 C#의 예제를 안내합니다. 일반적인 Batch 애플리케이션 워크플로, 그리고 Batch 및 Storage 리소스와 프로그래밍 방식으로 상호 작용하는 방법을 알아봅니다.
- Batch 계정에 애플리케이션 패키지를 추가합니다.
- Batch 및 Storage 계정을 인증합니다.
- 입력 파일을 Storage에 업로드합니다.
- 컴퓨팅 노드 풀을 만들어 애플리케이션을 실행합니다.
- 작업 및 태스크를 만들어 입력 파일을 처리합니다.
- 태스크 실행을 모니터링합니다.
- 출력 파일을 검색합니다.
이 자습서에서는 ffmpeg 오픈 소스 도구를 사용하여 MP4 미디어 파일을 MP3 형식으로 병렬로 변환합니다.
Azure를 구독하고 있지 않다면 시작하기 전에 Azure 체험 계정을 만듭니다.
필수 조건
Linux, macOS 또는 Windows의 경우 Visual Studio 2017 이상 또는 .NET Core SDK.
Batch 계정 및 연결된 Azure Storage 계정. 이러한 계정을 만들려면 Azure Portal 또는 Azure CLI에 대한 Batch 빠른 시작 가이드를 참조하세요.
사용 사례에 적합한 버전의 ffmpeg를 로컬 컴퓨터에 다운로드합니다. 이 자습서 및 관련 샘플 앱은 ffmpeg 4.3.1의 Windows 64비트 전체 빌드 버전을 사용합니다. 이 자습서에서는 zip 파일만 필요합니다. 파일의 압축을 풀거나 로컬에 설치할 필요가 없습니다.
Azure에 로그인
Azure Portal에 로그인합니다.
애플리케이션 패키지 추가
Azure Portal을 사용하여 ffmpeg를 Batch 계정에 애플리케이션 패키지로 추가합니다. 애플리케이션 패키지를 사용하면 풀의 컴퓨팅 노드에 태스크 애플리케이션 및 해당 배포를 간편하게 관리할 수 있습니다.
Azure Portal에서 추가 서비스>배치 계정을 클릭하고 배치 계정 이름을 선택합니다.
애플리케이션>추가를 클릭합니다.
애플리케이션 ID 필드에 ffmpeg를 입력하고, 버전 필드에 패키지 버전 4.3.1을 입력합니다. 다운로드한 ffmpeg Zip 파일을 선택한 다음 제출을 선택합니다. ffmpeg 애플리케이션 패키지가 Batch 계정에 추가됩니다.
계정 자격 증명 가져오기
이 예제에서는 배치 계정과 스토리지 계정에 대한 자격 증명을 제공해야 합니다. 필요한 자격 증명을 가져오는 간단한 방법은 Azure Portal에 있습니다. (Azure API 또는 명령줄 도구를 사용하여 이러한 자격 증명을 가져올 수도 있습니다.)
모든 서비스>배치 계정을 차례로 선택한 다음, 배치 계정의 이름을 선택합니다.
Batch 자격 증명을 보려면 키를 선택합니다. 배치 계정, URL 및 기본 액세스 키의 값을 텍스트 편집기에 복사합니다.
스토리지 계정 이름 및 키를 보려면 스토리지 계정을 선택합니다. 스토리지 계정 이름 및 Key1의 값을 텍스트 편집기에 복사합니다.
샘플 앱 다운로드 및 실행
샘플 앱 다운로드
GitHub에서 샘플 앱을 다운로드 또는 복제합니다. Git 클라이언트를 사용하여 샘플 앱 리포지토리를 복제하려면 다음 명령을 사용합니다.
git clone https://github.com/Azure-Samples/batch-dotnet-ffmpeg-tutorial.git
Visual Studio 솔루션 파일 BatchDotNetFfmpegTutorial.sln이 포함된 디렉터리로 이동합니다.
또한 솔루션의 ffmpeg 애플리케이션 패키지 참조가 Batch 계정에 업로드한 ffmpeg 패키지의 식별자 및 버전과 일치하는지 확인하세요. 예를 들어 ffmpeg
및 4.3.1
를 지정합니다.
const string appPackageId = "ffmpeg";
const string appPackageVersion = "4.3.1";
샘플 프로젝트 빌드 및 실행
Visual Studio 또는 명령줄에서 dotnet build
및 dotnet run
명령을 사용하여 애플리케이션을 빌드 및 실행합니다. 애플리케이션이 실행되면 코드를 검토하여 애플리케이션의 각 부분에서 수행하는 작업을 알아봅니다. 예를 들어 Visual Studio의 경우 다음과 같습니다.
솔루션 탐색기에서 솔루션을 마우스 오른쪽 단추로 클릭하고 솔루션 빌드를 선택합니다.
메시지가 표시되면 모든 NuGet 패키지 복원을 확인합니다. 누락된 패키지를 다운로드해야 하는 경우 NuGet 패키지 관리자가 설치되어 있는지 확인합니다.
솔루션을 실행합니다. 샘플 애플리케이션을 실행하는 경우 콘솔 출력은 다음과 비슷합니다. 실행 중에 풀의 컴퓨팅 노드가 시작되는 동안
Monitoring all tasks for 'Completed' state, timeout in 00:30:00...
에서 일시 중지가 발생합니다.
Sample start: 11/19/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 [WinFFmpegPool]...
Creating job [WinFFmpegJob]...
Adding 5 tasks to job [WinFFmpegJob]...
Monitoring all tasks for 'Completed' state, timeout in 00:30:00...
Success! All tasks completed successfully within the specified timeout period.
Deleting container [input]...
Sample end: 11/19/2018 3:29:36 PM
Elapsed time: 00:09:14.3418742
Azure Portal에서 Batch 계정으로 이동하여 풀, 컴퓨팅 노드, 작업 및 태스크를 모니터링합니다. 예를 들어 풀의 컴퓨팅 노드에 대한 열 지도를 보려면 풀>WinFFmpegPool을 클릭합니다.
태스크가 실행 중일 때 열 지도는 다음과 유사합니다.
기본 구성에서 애플리케이션을 실행하는 경우 일반적인 실행 시간은 약 10분입니다. 풀을 만드는 데 가장 많은 시간이 걸립니다.
출력 파일 검색
Azure Portal을 사용하여 ffmpeg 작업에서 생성된 출력 MP3 파일을 다운로드할 수 있습니다.
- 모든 서비스>스토리지 계정을 차례로 클릭한 다음, 스토리지 계정의 이름을 클릭합니다.
- Blob>출력을 차례로 클릭합니다.
- 출력 MP3 파일 중 하나를 마우스 오른쪽 단추로 클릭한 다음, 다운로드를 클릭합니다. 브라우저의 지시에 따라 파일을 열거나 저장합니다.
이 샘플에서는 표시되지 않지만, 컴퓨팅 노드 또는 스토리지 컨테이너에서 프로그래밍 방식으로 파일을 다운로드할 수도 있습니다.
코드 검토
다음 섹션에서는 샘플 애플리케이션을 Batch 서비스에서 워크로드를 처리하기 위해 수행하는 단계로 세분화합니다. 샘플의 모든 코드 줄이 토론되지는 않으므로 이 문서의 나머지 부분을 읽는 동안 솔루션의 Program.cs 파일을 참조하세요.
Blob 및 Batch 클라이언트 인증
앱은 연결된 스토리지 계정과 상호 작용하기 위해 .NET용 Azure.Storage.Blobs 라이브러리를 사용합니다. 계정 URI에 대한 참조를 사용하는 BlobServiceClient 클래스를 사용하고 DefaultAzureCredential 같은 토큰을 인증합니다.
// TODO: Replace <storage-account-name> with your actual storage account name
Uri accountUri = new Uri("https://<storage-account-name>.blob.core.windows.net/");
BlobServiceClient blobClient = new BlobServiceClient(accountUri, new DefaultAzureCredential());
앱은 Resource Manager의 ArmClient를 통해 BatchAccountResource에 대한 참조를 만들어 Batch 서비스에서 풀을 만듭니다. 샘플의 Arm 클라이언트는 DefaultAzureCredential 인증을 사용합니다.
ArmClient _armClient = new ArmClient(new DefaultAzureCredential());
var batchAccountIdentifier = ResourceIdentifier.Parse(BatchAccountResourceID);
BatchAccountResource batchAccount = await _armClient.GetBatchAccountResource(batchAccountIdentifier).GetAsync();
앱은 Batch 서비스에서 작업 및 태스크를 만드는 BatchClient 개체를 만듭니다. 샘플의 Batch 클라이언트는 DefaultAzureCredential 인증을 사용합니다.
// TODO: Replace <batch-account-name> with your actual storage account name
Uri batchUri = new Uri("https://<batch-account-name>t.eastus.batch.azure.com");
BatchClient _batchClient = new BatchClient(batchUri, new DefaultAzureCredential());
입력 파일 업로드
이 앱은 CreateContainerIfNotExistc
메서드에 blobServerClient
개체를 전달하여 입력 파일(MP4 형식)에 대한 스토리지 컨테이너와 태스크 출력에 대한 컨테이너를 만듭니다.
CreateContainerIfNotExist(blobClient, inputContainerName);
CreateContainerIfNotExist(blobClient, outputContainerName);
그런 다음 로컬 InputFiles 폴더에서 입력 컨테이너로 파일이 업로드됩니다. 스토리지의 파일은 Batch가 나중에 컴퓨팅 노드에 다운로드할 수 있는 Batch ResourceFile 개체로 정의됩니다.
파일 업로드에는 Program.cs의 두 가지 방법이 포함됩니다.
UploadFilesToContainerAsync
:ResourceFile
개체 컬렉션을 반환하고 내부적으로UploadResourceFileToContainerAsync
를 호출하여inputFilePaths
매개 변수에 전달된 각 파일을 업로드합니다.UploadResourceFileToContainerAsync
: 입력 컨테이너에 각 파일을 Blob으로 업로드합니다. 파일을 업로드한 후 Blob에 대한 SAS(공유 액세스 서명)를 가져오고 이를 나타내는ResourceFile
개체를 반환합니다.
string inputPath = Path.Combine(Environment.CurrentDirectory, "InputFiles");
List<string> inputFilePaths = new List<string>(Directory.GetFileSystemEntries(inputPath, "*.mp4",
SearchOption.TopDirectoryOnly));
List<ResourceFile> inputFiles = await UploadFilesToContainerAsync(
blobClient,
inputContainerName,
inputFilePaths);
.NET을 사용하여 파일을 Blob으로 스토리지 계정에 업로드하는 방법에 대한 자세한 내용은 .NET을 사용하여 Blob 업로드, 다운로드 및 나열을 참조하세요.
컴퓨팅 노드 풀 만들기
다음으로, 샘플이 CreatePoolIfNotExistAsync
에 대한 호출을 통해 Batch 계정에 컴퓨팅 노드의 풀을 만듭니다. 이 정의된 메서드는 BatchAccountResource.GetBatchAccountPools().CreateOrUpdateAsync 메서드를 사용하여 노드 수, VM 크기 및 풀 구성을 설정합니다. 여기서 BatchVmConfiguration 개체는 Azure Marketplace에 게시된 Windows Server 이미지에 대한 BatchImageReference를 지정합니다. Batch는 Azure Marketplace의 광범위한 VM 이미지뿐만 아니라 사용자 지정 VM 이미지도 지원합니다.
노드 수 및 VM 크기는 정의된 상수를 사용하여 설정됩니다. Batch는 전용 노드와 스폿 노드를 지원하며, 풀에서 하나 또는 둘 다 사용할 수 있습니다. 전용 노드는 풀에 예약되어 있습니다. 스폿 노드는 Azure의 잔여 VM 용량에서 할인된 가격으로 제공됩니다. Azure에 충분한 용량이 없으면 스폿 노드는 사용할 수 없게 됩니다. 이 샘플은 기본적으로 Standard_A1_v2 크기의 스폿 노드 5개만 포함된 풀을 만듭니다.
참고 항목
노드 할당량을 확인하세요. 할당량 요청을 만드는 방법에 대한 지침은 Batch 서비스 할당량 및 제한을 참조하세요.
풀 구성에 ApplicationPackageReference를 추가하면 컴퓨팅 노드에 ffmpeg 애플리케이션이 배포됩니다.
var credential = new DefaultAzureCredential();
ArmClient _armClient = new ArmClient(credential);
var batchAccountIdentifier = ResourceIdentifier.Parse(BatchAccountResourceID);
BatchAccountResource batchAccount = await _armClient.GetBatchAccountResource(batchAccountIdentifier).GetAsync();
BatchAccountPoolCollection collection = batchAccount.GetBatchAccountPools();
if (collection.Exists(poolId) == false)
{
var poolName = poolId;
var imageReference = new BatchImageReference()
{
Publisher = "MicrosoftWindowsServer",
Offer = "WindowsServer",
Sku = "2019-datacenter-smalldisk",
Version = "latest"
};
string nodeAgentSku = "batch.node.windows amd64";
ArmOperation<BatchAccountPoolResource> armOperation = await batchAccount.GetBatchAccountPools().CreateOrUpdateAsync(
WaitUntil.Completed, poolName, new BatchAccountPoolData()
{
VmSize = "Standard_DS1_v2",
DeploymentConfiguration = new BatchDeploymentConfiguration()
{
VmConfiguration = new BatchVmConfiguration(imageReference, nodeAgentSku)
},
ScaleSettings = new BatchAccountPoolScaleSettings()
{
FixedScale = new BatchAccountFixedScaleSettings()
{
TargetDedicatedNodes = DedicatedNodeCount,
TargetLowPriorityNodes = LowPriorityNodeCount
}
},
Identity = new ManagedServiceIdentity(ManagedServiceIdentityType.UserAssigned)
{
UserAssignedIdentities =
{
[new ResourceIdentifier(ManagedIdentityId)] = new Azure.ResourceManager.Models.UserAssignedIdentity(),
},
},
ApplicationPackages =
{
new Azure.ResourceManager.Batch.Models.BatchApplicationPackageReference(new ResourceIdentifier(appPacakgeResourceID))
{
Version = appPackageVersion,
}
},
});
BatchAccountPoolResource pool = armOperation.Value;
작업 만들기
Batch 작업은 태스크를 실행할 풀과 우선 순위 및 작업 일정과 같은 선택적 설정을 지정합니다. 이 샘플은 CreateJobAsync
를 호출하여 작업을 만듭니다. 이 정의된 메서드는 BatchClient.CreateJobAsync 메서드를 사용하여 풀에 작업을 만듭니다.
BatchJobCreateContent batchJobCreateContent = new BatchJobCreateContent(jobId, new BatchPoolInfo { PoolId = poolId });
await batchClient.CreateJobAsync(batchJobCreateContent);
작업 만들기
이 샘플은 BatchTask 개체 목록을 만드는 AddTasksAsync
메서드를 호출하여 작업에 태스크를 만듭니다. 각 BatchTask
는 CommandLine 속성을 사용하여 입력된 ResourceFile
개체를 처리하는 ffmpeg를 실행합니다. ffmpeg는 이전에 풀이 생성될 때 각 노드에 설치되었습니다. 여기서 명령줄은 fmpeg를 실행하여 입력된 각 MP4(비디오) 파일을 MP3(오디오) 파일로 변환합니다.
이 샘플에서는 명령줄을 실행한 후 MP3 파일에 대한 OutputFile 개체를 만듭니다. 각 태스크의 출력 파일(이 경우에는 하나)은 태스크의 OutputFiles 속성을 사용하여 연결된 스토리지 계정의 컨테이너에 업로드됩니다. outputFile
개체에 설정된 조건을 잘 보세요. 작업이 성공적으로 완료된 후 (OutputFileUploadCondition.TaskSuccess
) 작업의 출력 파일이 컨테이너에만 업로드됩니다. 자세한 구현 정보는 GitHub에서 전체 코드 샘플을 참조하세요.
그런 다음, 샘플에서는 CreateTaskAsync 메서드를 사용하여 작업에 태스크를 추가하고, 해당 태스크를 컴퓨팅 노드에서 실행할 때까지 큐에서 대기합니다.
실행 파일의 파일 경로를 다운로드한 버전의 이름으로 바꿉니다. 이 샘플 코드에서는 예제 ffmpeg-4.3.1-2020-11-08-full_build
를 사용합니다.
// Create a collection to hold the tasks added to the job:
List<BatchTaskCreateContent> tasks = new List<BatchTaskCreateContent>();
for (int i = 0; i < inputFiles.Count; i++)
{
// Assign a task ID for each iteration
string taskId = String.Format("Task{0}", i);
// Define task command line to convert the video format from MP4 to MP3 using ffmpeg.
// Note that ffmpeg syntax specifies the format as the file extension of the input file
// and the output file respectively. In this case inputs are MP4.
string appPath = String.Format("%AZ_BATCH_APP_PACKAGE_{0}#{1}%", appPackageId, appPackageVersion);
string inputMediaFile = inputFiles[i].StorageContainerUrl;
string outputMediaFile = String.Format("{0}{1}",
System.IO.Path.GetFileNameWithoutExtension(inputMediaFile),
".mp3");
string taskCommandLine = String.Format("cmd /c {0}\\ffmpeg-4.3.1-2020-11-08-full_build\\bin\\ffmpeg.exe -i {1} {2}", appPath, inputMediaFile, outputMediaFile);
// Create a batch task (with the task ID and command line) and add it to the task list
BatchTaskCreateContent batchTaskCreateContent = new BatchTaskCreateContent(taskId, taskCommandLine);
batchTaskCreateContent.ResourceFiles.Add(inputFiles[i]);
// Task output file will be uploaded to the output container in Storage.
// TODO: Replace <storage-account-name> with your actual storage account name
OutputFileBlobContainerDestination outputContainer = new OutputFileBlobContainerDestination("https://<storage-account-name>.blob.core.windows.net/output/" + outputMediaFile)
{
IdentityReference = inputFiles[i].IdentityReference,
};
OutputFile outputFile = new OutputFile(outputMediaFile,
new OutputFileDestination() { Container = outputContainer },
new OutputFileUploadConfig(OutputFileUploadCondition.TaskSuccess));
batchTaskCreateContent.OutputFiles.Add(outputFile);
tasks.Add(batchTaskCreateContent);
}
// Call BatchClient.CreateTaskCollectionAsync() to add the tasks as a collection rather than making a
// separate call for each. Bulk task submission helps to ensure efficient underlying API
// calls to the Batch service.
await batchClient.CreateTaskCollectionAsync(jobId, new BatchTaskGroup(tasks));
리소스 정리
앱은 태스크를 실행한 후 생성된 입력 스토리지 컨테이너를 자동으로 삭제하고 사용자에게 Batch 풀 및 작업을 삭제하는 옵션을 제공합니다. BatchClient에는 DeleteJobAsync 작업을 삭제하고 삭제를 확인하는 경우 호출되는 DeletePoolAsync 풀을 삭제하는 메서드가 있습니다. 작업 및 태스크 자체에 대한 요금이 부과되지 않지만 컴퓨팅 노드에 대한 요금이 청구됩니다. 따라서 풀을 필요할 때만 할당하는 것이 좋습니다. 풀을 삭제하면 노드의 모든 태스크 출력이 삭제됩니다. 그러나 출력 파일은 스토리지 계정에 남아 있습니다.
더 이상 필요하지 않으면 리소스 그룹, 배치 계정 및 스토리지 계정을 삭제합니다. Azure Portal에서 이렇게 하려면 배치 계정에 대한 리소스 그룹을 선택하고 리소스 그룹 삭제를 클릭합니다.
다음 단계
이 자습서에서는 다음 작업 방법을 알아보았습니다.
- Batch 계정에 애플리케이션 패키지를 추가합니다.
- Batch 및 Storage 계정을 인증합니다.
- 입력 파일을 Storage에 업로드합니다.
- 컴퓨팅 노드 풀을 만들어 애플리케이션을 실행합니다.
- 작업 및 태스크를 만들어 입력 파일을 처리합니다.
- 태스크 실행을 모니터링합니다.
- 출력 파일을 검색합니다.
.NET API를 사용하여 Batch 워크로드를 예약하고 처리하는 방법에 대한 추가 예는 GitHub의 Batch C# 샘플을 참조하세요.