연습 - 작업을 실행할 컴퓨팅 노드 풀 만들기

완료됨

일괄 작업을 실행하려면 Batch 계정에 을 추가해야 합니다. 풀은 일괄 작업을 실행하는 엔진인 컴퓨팅 노드를 포함합니다. 생성 시 노드의 수, 크기 및 운영 체제를 지정합니다. 이 연습에서는 이전 연습에서 만든 콘솔 앱을 수정하여 Batch 계정에 풀을 추가하겠습니다.

회사에서 앱의 비용을 제어하려고 하며 고정된 수의 노드를 사용하도록 요청했습니다.

Important

이 연습을 수행하려면 사용자의 Azure 구독이 필요하며 요금이 발생할 수 있습니다. Azure 구독이 아직 없는 경우 시작하기 전에 체험 계정을 만듭니다.

새 풀의 설정 추가

  1. 다음과 같이 Cloud Shell에서 편집기를 사용하여 Program.cs 파일을 편집합니다.

    code Program.cs
    
  2. Program.cs의 Program 클래스에 다음 속성을 추가합니다.

    private const string PoolId = "WinFFmpegPool";
    private const int DedicatedNodeCount = 0;
    private const int LowPriorityNodeCount = 3;
    private const string PoolVMSize = "STANDARD_D2_v2";
    private const string appPackageId = "ffmpeg";
    private const string appPackageVersion = "3.4";
    

    위의 설정은 코드에서 풀을 만드는 데 사용됩니다. 각 변수를 살펴보면 다음과 같이 설명할 수 있습니다.

    • PoolId: 코드가 다른 일괄 처리 클라이언트 호출에서 풀을 참조하는 데 사용하는 이름입니다.
    • LowPriorityNodeCount: 우선 순위가 낮은 3개의 VM(가상 머신)이 있는 풀을 만듭니다.
    • PoolVMSize: VM은 STANDARD_A1_v2 노드에 1 CPU, 2GB RAM 및 10GB의 SSD 스토리지를 제공합니다.
    • appPackageId: 만드는 노드에서 사용할 애플리케이션 패키지의 이름입니다.
    • appPackageVersion: 만드는 노드에서 사용할 애플리케이션의 버전입니다.

비동기 호출을 지원하도록 Main() 메서드 업데이트

클라우드 서비스에 대한 여러 비동기 호출을 만들 것이므로, 가장 먼저 할 일은 Main을 비동기로 만드는 것입니다. C# .NET 버전 7.1 이상에서는 콘솔 애플리케이션의 비동기 Main 메서드가 지원됩니다.

  1. 먼저 라이브러리를 추가하여 System.Threading.Tasks 비동기 메서드 호출을 허용하도록 콘솔 앱을 변경합니다.

    using System.Threading.Tasks;
    using System.Collections.Generic; // Also add generics to allow the app to use Lists
    
  2. 다음으로 Main 메서드 서명을 다음과 같이 업데이트합니다.

    static async Task Main(string[] args)
    

풀 만들기

  1. 다음 새 메서드를 Program 클래스에 추가하여 Batch 풀을 만듭니다. 메서드:

    • 풀에 추가할 노드에 대한 설정을 저장하는 이미지 참조 개체를 만듭니다.
    • 이미지 참조를 사용하여 개체를 만듭니다 VirtualMachineConfiguration .
    • 이전에 선언된 속성과 을 사용하여 언바운드 풀을 VirtualMachineConfiguration만듭니다.
    • 풀에 애플리케이션 패키지 참조를 추가합니다.
    • Azure에서 풀을 만듭니다.
    • 두 개의 매개 변수를 batchClient 사용합니다.PoolId
      private static async Task CreateBatchPoolAsync(BatchClient batchClient, string poolId)
        {
            CloudPool pool = null;
            Console.WriteLine("Creating pool [{0}]...", poolId);
    
            // Create an image reference object to store the settings for the nodes to be added to the pool
            ImageReference imageReference = new ImageReference(
                    publisher: "MicrosoftWindowsServer",
                    offer: "WindowsServer",
                    sku: "2012-R2-Datacenter-smalldisk",
                    version: "latest");
    
            // Use the image reference to create a VirtualMachineConfiguration object
            VirtualMachineConfiguration virtualMachineConfiguration =
            new VirtualMachineConfiguration(
                imageReference: imageReference,
                nodeAgentSkuId: "batch.node.windows amd64");
    
            try
            {
                // Create an unbound pool. No pool is actually created in the Batch service until we call
                // CloudPool.CommitAsync(). This CloudPool instance is therefore considered "unbound," and we can
                // modify its properties.
                pool = batchClient.PoolOperations.CreatePool(
                    poolId: poolId,
                    targetDedicatedComputeNodes: DedicatedNodeCount,
                    targetLowPriorityComputeNodes: LowPriorityNodeCount,
                    virtualMachineSize: PoolVMSize,
                    virtualMachineConfiguration: virtualMachineConfiguration);  
    
                // Specify the application and version to install on the compute nodes
                pool.ApplicationPackageReferences = new List<ApplicationPackageReference>
                {
                    new ApplicationPackageReference
                    {
                    ApplicationId = appPackageId,
                    Version = appPackageVersion
                    }
                };
    
                // Create the pool
                await pool.CommitAsync();
            }
            catch (BatchException be)
            {
                // Accept the specific error code PoolExists as that is expected if the pool already exists
                if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.PoolExists)
                {
                    Console.WriteLine("The pool [{0}] already existed when we tried to create it", poolId);
                }
                else
                {
                    throw; // Any other exception is unexpected
                }
            }
        }  
    
  2. Main 메서드에서 CreateBatchPoolAsync를 호출합니다. 이제 Main 메서드가 다음과 비슷할 것입니다.

    static async Task Main(string[] args)
    {
        // Read the environment variables to allow the app to connect to the Azure Batch account
        batchAccountUrl = Environment.GetEnvironmentVariable(envVarBatchURI);
        batchAccountName = Environment.GetEnvironmentVariable(envVarBatchName);
        batchAccountKey = Environment.GetEnvironmentVariable(envVarKey);
    
        // Show the user the batch the app is attaching to
        Console.WriteLine("URL: {0}, Name: {1}, Key: {2}", batchAccountUrl, batchAccountName, batchAccountKey);
    
        // The batch client requires a BatchSharedKeyCredentials object to open a connection
        var sharedKeyCredentials = new BatchSharedKeyCredentials(batchAccountUrl, batchAccountName, batchAccountKey);
        var batchClient = BatchClient.Open(sharedKeyCredentials);
    
        // Create the Batch pool, which contains the compute nodes that execute tasks.
        await CreateBatchPoolAsync(batchClient, PoolId);
    }
    

앱 테스트

  1. 코드 편집기에서 마우스 오른쪽 단추를 클릭하고 저장을 선택한 다음 마우스 오른쪽 단추를 클릭하고 종료를 선택합니다.

  2. Cloud Shell에서 다음 명령을 사용하여 앱을 컴파일하고 실행합니다.

    dotnet run
    
  3. 앱을 실행하는 데 몇 분 정도 걸리며 다음 출력을 가져와야 합니다.

    URL: <your batch account url, Name: <your batch name>, Key: <your batch key>
    Creating pool [WinFFmpegPool]...
    

각 노드는 Windows 2012 서버를 실행하는 VM이며, CPU 1개와 2GB RAM을 갖고 있습니다. Batch가 Azure Virtual Machine Marketplace에서 이러한 Windows VM 이미지를 전송하고, VM 인프라 및 네트워킹을 만들고, 마지막으로 각 노드를 시작할 때까지 시간이 걸립니다. 대부분의 Batch 솔루션에서 이 부분에 가장 많은 시간이 소요됩니다. 일반적인 Batch 워크플로에서는 풀과 노드를 정리하지 않습니다.