JavaScript 向け Batch SDK の概要

この記事では、Azure Batch JavaScript SDK を使って JavaScript で Batch クライアントを作成するうえで基本となる事項を説明します。 説明にあたっては、段階的なアプローチを採用しています。具体的には、バッチ アプリケーションを使用するシナリオを紹介したうえで、JavaScript を使ってアプリケーションをセットアップしていきます。

前提条件

この記事では、JavaScript の実務知識を持ち、Linux に精通している読者を想定しています。 また、Batch と Storage の 2 つのサービスを作成できるアクセス権を備えた Azure アカウントも必要になります。

この記事を読む前に、Azure Batch の技術的概要に関する記事を読むことをお勧めします。

シナリオの理解

ここでは、Python で記述された簡単なスクリプトを使用して、Azure Blob Storage コンテナーからすべての csv ファイルをダウンロードし、JSON に変換します。 今回は複数のストレージ アカウントのコンテナーを同時に処理するために、このスクリプトを Azure Batch ジョブとしてデプロイします。

Azure Batch のアーキテクチャ

次の図は、Azure Batch とクライアントを使って Python スクリプトをスケーリングする方法を示しています。

シナリオのアーキテクチャを示す図。

JavaScript サンプルでは、準備タスク (後述) と、ストレージ アカウント内のコンテナーの数に応じた一連のタスクを含むバッチ ジョブをデプロイします。 スクリプトは、GitHub リポジトリからダウンロードできます。

ヒント

上記リンクから入手できる JavaScript サンプルには、Azure 関数アプリとしてデプロイされる特定のコードは含まれていません。 Function App を作成するための手順については、以下のリンクを参照してください。

アプリケーションのビルド

それでは、JavaScript クライアントを作成するプロセスを 1 つずつ実行していきましょう。

手順 1:Azure Batch SDK をインストールする

JavaScript 向け Azure Batch SDK をインストールするには、npm install コマンドを使用します。

npm install @azure/batch

このコマンドを実行すると、azure-batch JavaScript SDK の最新バージョンがインストールされます。

ヒント

Azure Function App では、Azure 関数の [設定] タブにある "Kudu コンソール" から npm install コマンドを実行できます。 この場合、JavaScript 向けの Azure Batch SDK をインストールします。

手順 2:Azure Batch アカウントを作成する

Azure Portal またはコマンド ライン (PowerShell /Azure CLI) から作成できます。

以下で紹介するのは、Azure CLI からアカウントを 1 つ作成するためのコマンドです。

リソース グループを作成します。Batch アカウントの作成先とするリソース グループが既にある場合には、この手順は省略してください。

az group create -n "<resource-group-name>" -l "<location>"

続いて、Azure Batch アカウントを作成します。

az batch account create -l "<location>" -g "<resource-group-name>" -n "<batch-account-name>"

各 Batch アカウントには、対応するアクセス キーが存在します。 Azure Batch アカウントに追加でリソースを作成するには、このアクセス キーが必要になります。 運用環境の場合には、アクセス キーの格納場所として Azure Key Vault を使用すると良いでしょう。 そうすれば、アプリケーション用にサービス プリンシパルを作成できます。 アプリケーションではこのサービス プリンシパルを使用して、キー コンテナーからキーにアクセスするための OAuth トークンを作成します。

az batch account keys list -g "<resource-group-name>" -n "<batch-account-name>"

以降の手順で使用するため、キーをコピーして保存します。

手順 3:Azure Batch サービス クライアントを作成する

次のコード スニペットでは、azure-batch JavaScript モジュールをインポートしたうえで、Batch サービス クライアントを作成します。 最初に、先ほどの手順でコピーしておいた Batch アカウントのキーを使って SharedKeyCredentials オブジェクトを作成する必要があります。

// Initializing Azure Batch variables

import { BatchServiceClient, BatchSharedKeyCredentials } from "@azure/batch";

// Replace values below with Batch Account details
const batchAccountName = '<batch-account-name>';
const batchAccountKey = '<batch-account-key>';
const batchEndpoint = '<batch-account-url>';

const credentials = new BatchSharedKeyCredentials(batchAccountName, batchAccountKey);
const batchClient = new BatchServiceClient(credentials, batchEndpoint);

Azure Batch の URI は、Azure Portal の [概要] タブにあります。 これは、次のような形式になっています。

https://accountname.location.batch.azure.com

スクリーンショットを参照してください。

Azure Batch の URI

手順 4:Azure Batch プールを作成する

Azure Batch プールは、複数の VM (別名 Batch ノード) で構成されています。 Azure Batch サービスでは、そのノードにタスクをデプロイして管理します。 プールには以下の構成パラメーターを定義できます。

  • 仮想マシン イメージの種類
  • 仮想マシン ノードのサイズ
  • 仮想マシン ノードの数

ヒント

仮想マシン ノードのサイズと数は、並行して実行するタスクの数のほか、タスク自体の内容に大きく左右されます。 このため、テストを実施して最適な数とサイズを確認することをお勧めします。

以下のコード スニペットは、構成パラメーター オブジェクトを作成するものです。

// Creating Image reference configuration for Ubuntu Linux VM
const imgRef = {
    publisher: "Canonical",
    offer: "UbuntuServer",
    sku: "20.04-LTS",
    version: "latest"
}
// Creating the VM configuration object with the SKUID
const vmConfig = {
    imageReference: imgRef,
    nodeAgentSKUId: "batch.node.ubuntu 20.04"
};
// Number of VMs to create in a pool
const numVms = 4;

// Setting the VM size
const vmSize = "STANDARD_D1_V2";

ヒント

Azure Batch で利用できる Linux VM イメージの一覧とその SKU ID については、「仮想マシン イメージの一覧」を参照してください。

プールの構成を定義したら、Azure Batch プールを作成できます。 Batch プール コマンドを実行すると、Azure 仮想マシン ノードが作成され、ノードで実行対象のタスクを受信する準備が整います。 各プールには、後の手順で参照するための一意の ID が必要です。

以下のコード スニペットでは、Azure Batch プールが 1 つ作成されます。

// Create a unique Azure Batch pool ID
const now = new Date();
const poolId = `processcsv_${now.getFullYear()}${now.getMonth()}${now.getDay()}${now.getHours()}${now.getSeconds()}`;

const poolConfig = {
    id: poolId,
    displayName: "Processing csv files",
    vmSize: vmSize,
    virtualMachineConfiguration: vmConfig,
    targetDedicatedNodes: numVms,
    enableAutoScale: false
};

// Creating the Pool
var pool = batchClient.pool.add(poolConfig, function (error, result){
    if(error!=null){console.log(error.response)};
});

プールを作成したら、その状態を確認できます。プールにジョブを送信する前に、状態が "アクティブ" であることを確認しましょう。

var cloudPool = batchClient.pool.get(poolId,function(error,result,request,response){
        if(error == null)
        {

            if(result.state == "active")
            {
                console.log("Pool is active");
            }
        }
        else
        {
            if(error.statusCode==404)
            {
                console.log("Pool not found yet returned 404...");

            }
            else
            {
                console.log("Error occurred while retrieving pool data");
            }
        }
        });

上の pool.get 関数によって返される結果オブジェクトのサンプルは、以下のとおりです。

{
  id: 'processcsv_2022002321',
  displayName: 'Processing csv files',
  url: 'https://<batch-account-name>.westus.batch.azure.com/pools/processcsv_2022002321',
  eTag: '0x8D9D4088BC56FA1',
  lastModified: 2022-01-10T07:12:21.943Z,
  creationTime: 2022-01-10T07:12:21.943Z,
  state: 'active',
  stateTransitionTime: 2022-01-10T07:12:21.943Z,
  allocationState: 'steady',
  allocationStateTransitionTime: 2022-01-10T07:13:35.103Z,
  vmSize: 'standard_d1_v2',
  virtualMachineConfiguration: {
    imageReference: {
      publisher: 'Canonical',
      offer: 'UbuntuServer',
      sku: '20.04-LTS',
      version: 'latest'
    },
    nodeAgentSKUId: 'batch.node.ubuntu 20.04'
  },
  resizeTimeout: 'PT15M',
  currentDedicatedNodes: 4,
  currentLowPriorityNodes: 0,
  targetDedicatedNodes: 4,
  targetLowPriorityNodes: 0,
  enableAutoScale: false,
  enableInterNodeCommunication: false,
  taskSlotsPerNode: 1,
  taskSchedulingPolicy: { nodeFillType: 'Spread' }}

手順 4:Azure Batch ジョブを送信する

Azure Batch ジョブは、よく似たタスクを論理的なグループにまとめたものです。 このシナリオでは、"CSV から JSON への処理" です。ここでの各タスクから、各 Azure Storage コンテナーに存在する csv ファイルが処理される可能性があります。

タスクはいずれも並行して実行され、多数のノードにデプロイされます。Azure Batch サービスは、そのオーケストレーションを担当します。

ヒント

1 つのノードで同時に実行できるタスクの最大数を指定するには、taskSlotsPerNode プロパティを使用します。

準備タスク

作成された VM ノードは、空の Ubuntu ノードです。 多くの場合、前提条件としていくつかのプログラムをインストールする必要があります。 Linux ノードの場合には通常、実際のタスクの実行前に前提条件となるプログラムをインストールするシェル スクリプトを用意します。 もっとも、そのようなスクリプトはプログラミング可能な実行可能ファイルであれば何でもかまいません。

この例のシェル スクリプトは、Python pip と Azure Storage Blob SDK for Python をインストールします。

このスクリプトを Azure ストレージ アカウントにアップロードすると、スクリプトにアクセスするための SAS の URI を生成できます。 この処理は、Azure Storage JavaScript SDK を使って自動化することもできます。

ヒント

ジョブの準備タスクは、特定のタスクの実行が必要な VM ノードでのみ実行されます。 ノードで実行するタスクに関係なく全ノードに前提条件をインストールする場合には、プールを追加するときに startTask プロパティを使用します。 以下で紹介する準備タスクの定義は、参考として使用してください。

準備タスクは、Azure Batch ジョブの送信中に指定します。 構成可能な準備タスクのパラメーターを次に示します。

  • [ID] :準備タスクの一意の識別子
  • commandLine:タスクの実行可能ファイルを実行するためのコマンド ライン
  • resourceFiles:このタスクを実行するためにダウンロードが必要なファイルの詳細を指定したオブジェクトの配列。 オプションは以下のとおりです。
    • httpUrl: ダウンロードするファイルの URL
    • filePath:ファイルのダウンロードと保存のためのローカル パス
    • fileMode:0770 を既定値とする 8 進数形式の値 (Linux ノードのみ該当)
  • waitForSuccess:true に設定すると、準備タスクが失敗した場合にタスクが実行されなくなります
  • runElevated:タスクの実行に昇格された特権が必要な場合には true に設定します。

以下のコード スニペットでは、準備タスク スクリプトの構成サンプルを示しています。

var jobPrepTaskConfig = {id:"installprereq",commandLine:"sudo sh startup_prereq.sh > startup.log",resourceFiles: [{ 'httpUrl': 'Blob sh url', 'filePath': 'startup_prereq.sh' }],waitForSuccess:true,runElevated:true, userIdentity: {autoUser: {elevationLevel: "admin", scope: "pool"}}}

タスクを実行するための前提条件が一切インストールされていない場合には、準備タスクを省略できます。 以下のコードは、表示名が "process csv files" のジョブを作成するものです。

// Setting Batch Pool ID
const poolInfo = { poolId: poolId };
// Batch job configuration object
const jobId = "processcsvjob";
const jobConfig = {
    id: jobId,
    displayName: "process csv files",
    jobPreparationTask: jobPrepTaskConfig,
    poolInfo: poolInfo
};
// Adding Azure batch job to the pool
const job = batchClient.job.add(jobConfig, function (error, result) {
        if (error !== null) {
            console.log("An error occurred while creating the job...");
            console.log(error.response);
        }
    }
);

手順 5:ジョブの Azure Batch タスクを送信する

csv を処理するジョブが作成できたので、このジョブのためのタスクを作成しましょう。 コンテナーが 4 つあるとすると、コンテナーごとに 1 つずつ、計 4 つのタスクを作成する必要があります。

Python スクリプトを見ると、次の 2 つのパラメーターを受け取ることがわかります。

  • コンテナー名:ファイルをダウンロードするストレージ コンテナー
  • パターン:ファイル名パターンの省略可能なパラメーター

以下のコードは、コンテナーが "con1"、"con2"、"con3"、"con4" の 4 つであると仮定して、先ほど作成した Azure Batch ジョブ "process csv" に 4 つのタスクを送信する方法を示しています。

// storing container names in an array
const containerList = ["con1", "con2", "con3", "con4"];      //Replace with list of blob containers within storage account
containerList.forEach(function (val, index) {
    console.log("Submitting task for container : " + val);
    const containerName = val;
    const taskID = containerName + "_process";
    // Task configuration object
    const taskConfig = {
        id: taskID,
        displayName: 'process csv in ' + containerName,
        commandLine: 'python processcsv.py --container ' + containerName,
        resourceFiles: [{ 'httpUrl': 'Blob script url', 'filePath': 'processcsv.py' }]
    };

    const task = batchClient.task.add(jobId, taskConfig, function (error, result) {
        if (error !== null) {
            console.log("Error occurred while creating task for container " + containerName + ". Details : " + error.response);
        }
        else {
            console.log("Task for container : " + containerName + " submitted successfully");
        }
    });
});

このコードによって、プールにタスクが複数追加されます。 各タスクは、作成された VM のプール内のノードで実行されます。 タスクの数がプールまたは taskSlotsPerNode プロパティの VM の数を上回った場合には、タスクはノードが利用可能になるまで待機します。 このオーケストレーションは、Azure Batch によって自動的に処理されます。

ポータルでは、タスクとジョブの状態の詳細を確認できます。 また、Azure JavaScript SDK の list および get 関数も使用できます。 詳細については、ドキュメント (リンク) を参照してください。

次のステップ