演習 - ジョブを実行するためにコンピューティング ノードのプールを作成する

完了

バッチ ジョブを実行するには、Batch アカウントに "プール" を追加する必要があります。 プールには、Batch ジョブを実行するエンジンであるコンピューティング ノードが含まれます。 作成時、ノードの数、サイズ、オペレーティング システムを指定します。 この演習では、前の演習で作成したコンソール アプリを改良し、Batch アカウントにプールを追加します。

アプリのコストを制御したいと考えている会社から、決まった数のノードを使用するように求められています。

重要

この演習を行うには、独自の 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 になります。CPU が 1 つ、2 GB の RAM、10 GB の 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 でプールを作成します。
    • 2 つのパラメーター 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 Server を実行する VM であり、CPU が 1 つだけで RAM が 2 GB であることにご留意ください。 Batch で Azure Virtual Machine Marketplace から Windows VM イメージを転送し、VM のインフラストラクチャとネットワークを構築し、最後に各ノードを開始するのに時間がかかります。 ほとんどの Batch ソリューションにおいて、これが最も時間がかかる部分です。 一般的な Batch ワークフローでは、プールとそのノードがクリーンアップされません。