【丁寧解説】大量データを処理するための Azure Batch とは

Masahito Morishima Masahito Morishima
Keiichi Hashimoto Keiichi Hashimoto
【丁寧解説】大量データを処理するための Azure Batch とは

Azure Batch で大量のデータを処理する

Azure Batch とは大規模なコンピュータリソースを必要とするバッチジョブをAzureで効率的に処理するための実行基盤です。本文書では、Azure Batchの概要と利用にまつわる注意点などを解説します。

Azure Bacthを構成する要素

Azure Batch を構成する要素には、ノード、プール、ジョブ、タスクなどがありますが、はじめにこれらの関係について説明します。

アカウント

以降に説明する構成要素(ノード、プール、ジョブ、タスク)を含む実態(エンティティ)をバッチアカウントと呼びます。Azure Batch は入出力を管理するめに必ずストレージアカウントと関連づいています。

ノード

コンピューティングノード(略してノード)とは、Azure Batchにおいて実際になんらかの計算を行うための仮想マシンのことです。Azure Batch で利用する仮想マシンは、他のAzureサービスと同様にサイズを選択することができます。必要なリソースを考慮し、最適なCPUコア数、メモリ、ローカルのストレージサイズをもった仮想マシンサイズを選択します。またOSもWindowsとLinuxから選択することができます。これらの仮想マシンに対しては、Windowsならリモートデスクトップ、LinuxnならSSHで直接アクセスすることもできます。

仮想マシンサイズについては、以下を参考にしてください。

プール

プールはノードの集合(コレクション)であり、各ノードを制御する役割を担います。前述したノードは、直接作成することはできないので、プール作成時に、どのようなノードを作成する、ノード数をいくつにするかなどを指定します。

プールにはいくつか特徴的な機能を備えているため、それらを説明します。

アプリケーション

Azure Batch で利用するアプリケーションをZip形式でアップロードし、プールに紐付けることができます。ノードが展開されるとき(実際にノードの仮想マシンが起動するとき)に、このアプリケーションパッケージは任意のディレクトリに展開され、各ノードから利用することができます。

例えば、バッチ処理のアプリケーションを展開、必要な3rdパーティのアプリケーションを展開することができます。

開始タスク

ノードが起動するときに、一度だけ実行されれるタスクを構成できます。例えばインストールが必要なパッケージのインストーラを起動したり、あらかじめ必要な処理を実行できます。スクリプトを記述できるので各プラットフォーム(Windows/Linux)固有の処理を記述します。

ジョブ

Azure Batchにおけるジョブは、いわゆる「バッチジョブ」を呼ばれる実行単位です。複数のタスクから構成されています、後述するタスクの制約などを指定できます。また、ジョブを作成するときには、どこで実行されるかプールを指定します。

通常は1つのジョブにつき、多くのタスクを定義して実行じます。

タスク

Azure Batchにおける最小実行単位です。ジョブの一部としてノードに展開されて実行されます。プール内に複数のノードがあれば、並列に処理されるでしょう。

他にいくつかタスクの特徴的な機能を以下にあげます。

  • タスク間に依存関係をつけて、実行順序を制御することができたる。
  • マネージャタスクという特別なタスクを用意し、ジョブ実行の制御や監視ができる。
  • ジョブ準備、終了タスクという特別なタスクを用意し、一般タスクの実行準備処理や終了処理ができる。

※ 執筆時点では、クラウドサービスをベースとしたノードを選択できますが、2024年に終了することがアナウンスされています。

この章のまとめとして、簡単にノードとプール、ジョブとタスクの関係製について図示します。

  • ジョブはAzure Batch上で実行を管理する単位です。プールに紐づきま、タスクの集合でもあります。
  • タスクはAzure Batch上での最小実行単位です。いくつか種類があり、ジョブに集約されます。
  • プールはノードの集合です。0個以上のノードを定義できます(0を定義するとノードが展開されない状態になりジョブはキューに滞留します)
  • ノードはタスクを実行する具体的な仮想マシンです。サイズやOSを選択できます。

Azure Batchの操作

Azure Batch を操作するには、ポータル画面、シェル、もしくはBatch API を利用します。一般的なジョブ管理ソフトの管理ツールはありません。

ただ、管理ツールはないと言いましたが、OSSでAzure Batch エクスプローラーが提供されています。機能的にはポータル画面と同等の操作がエクスプローラーUIから操作できます。

以下からダウンロードすることができます。

自動化をするには、シェルもしくはBatch APIを利用する方法になります。APIには、Azure Batch 自身を管理するマネジメント API と、ジョブやタスクを投入するためのサービス API の二種類があります。適宜使い分けて、自動化を図る必要があります。

マネジメント API と サービス API は各言語毎にSDKとして提供されています。詳細は以下を参照してください。

Azure Batchの考慮点

ジョブとタスクの粒度

1つジョブに対して、少ない数のタスクを実行するのは効率的ではないため、なるべく多くのタスク(数百~数千)を定義したほうが実行効率があがります。

タスクについては、タスク自身がどのようなワークロードなのか(CPUを使うのか、IOを使うのか)を考慮して大きな問題をタスクという最小単位に実行すべきです。ただし、実行時間が数秒のタスクは全体的なスループットが低下します。少なくとも数分レベルの実行単位にすべきです(最大で数時間)。

またノードには同時実行タスク数が設定されており既定では1となっています。例えば、マルチスレッド化されてないプログラムを複数コアをもつノードで実行させると効率が悪くなります。そのような場合には、CPU利用率が100%になるよう同時実行タスク数を調整する必要があります。

再試行と冪統制

タスクが失敗したとき、ジョブがどのような振る舞いをするのかはジョブの設定次第です。1つのタスクの失敗がした場合、ジョブそのものを打ち切るのか、タスクを再試行させるのかなどです。

いずれの粒度にしろ、バッチジョブであるかぎりは、再試行を行う必要があるため、タスクは冪等になるよう設計する必要があります。冪等とは、ある入力のタスクが実行回数に関係なく、同じ結果を得られるような性質のことを言います。

たとえば、ある入力にたいする計算結果を永続化するような場合、すでに計算結果ファイルが存在しても上書きするような処理であったり、中断したポイントを判定し再開するような考慮が必要です。

プール

プールについてもいくつか注意点があります。

基本的にプールにおけるノード数は、複数であることが必要です。ノードの障害やOSの更新など、さまざまな問題によってノードがオフライン状態になることがあるため、ビジネスの継続性を鑑みて複数にすることが望ましいでしょう。逆になにも実行しない時間端があるときはプールのノード数を0にすることで、課金を減らすことができます。

各ノードのはAzure Batchのエージェントがインストールされていますが、これらは自動的に更新されません。更新するためには、プールの再作成もしくはノードの再作成が必要です。したがってメンテナンスのため、ノード数を0にしてノードをクリアし、元の値にも戻し再展開することが必要です。

クォータ

お使いのサブスクリプションによって、作成できるノードのVMサイズが異なることがあります。ポータルのBatchからクォータを確認することができますので、確認してください。制限されいているVMサイズを指定すると、ノード作成時に失敗します。

Azure Batch SDK を用いたジョブの実行

Azure Batch SDK for .NET を用いたジョブの実行について解説します。バッチアカウントおよび、プール、ノードは作成済みとし、ここでは以下の処理を考えることとします。

  1. 入力となるファイルは、Azure Storage BLOBにアップロードされる。
  2. BLOBの数は数万件と想定し、1ファイル毎に何らかの処理(例えば変換処理)を実施し、別のBLOBへ出力する。
  3. 毎日午前0時に処理を開始する

SDK の利用に必要な情報設定

SDKを利用する上で必要な情報を情報をポータルから取得します。

  • バッチアカウント名
  • バッチアカウントキー
  • バッチアカウントURL
  • プール名

それに加えて、バッチアカウントに紐づくストレージアカウントの情報も取得します。

  • ストレージアカウント名
  • ストレージアカウントキー

適当なコンソールプロジェクトを作成し、以下のバージョンのSDKををインストールします(執筆時点での最新)。

dotnet add package Microsoft.Azure.Batch --version 14.0.0

ジョブの作成

バッチクライアントを作成するには、必要な認証情報を元に、BatchClient.Openメソッドを呼び出します。

次にCloudJobインスタンスを作成し、必要な情報(ジョブID、プールID)を設定しコミットします。ジョブIDには一意なIDを降り、プールIDには作成済のプールIDを設定します。CommitするとAzure Batch上にジョブが一旦、作成されます。タスクの追加は、ジョブの作成後に実行する必要があります。

            // バッチクライアントの作成
            BatchSharedKeyCredentials creds = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);
            BatchClient batchClient = BatchClient.Open(creds);

            // ジョブの作成
            CloudJob job = batchClient.JobOperations.CreateJob();
            job.Id = "TestJob-" + DateTimeOffset.Now.Ticks;
            job.PoolInformation = new PoolInformation { PoolId = PoolId };
            job.Commit();

タクスの作成は、前述したとおり問題を適当な粒度に分割する必要があります。

タスクの作成

タスクを作成する前にタスクの粒度について考えてみましょう。1つのファイルを処理するのに数秒しか時間がかからなかった場合、1つのタスクに1つのファイル処理を割り当てるのはオーバヘッドが大きく非効率です。前述したように数分から数時間の粒度で考えましょう。ただし、何らかの理由でファイルの変換に失敗しリトライされる場合もタスク単位となります。問題を数分から数十分程度に分割できるのなら、そのほうが効率が良いでしょう。

タスクで実行するアプリケーションは、あらかじめバッチアカウントにアップロードし、プールに紐付けておかなければなりません。そうすることであらかじめ任意のディレクトリにアプリケーションが展開されています。タスクではそれらを実行するように構成します。たとえば、CONVと命名したアプリケーションをアップロードした場合、それらの場所は環境変数に設定されるので、それを参照します。

タスクの作成は、CloudTaskインスタンスを生成し、ジョブにタスクを追加していきます。追加され次第順次実行されていきます。

            foreach (.....)
            {
                var cmd = "cmd /c %AZ_BATCH_APP_PACKAGE_CONV%\\FileConv.exe XXXXXXXXX";
                CloudTask task = new CloudTask("Task-" + i , cmd);
                batchClient.JobOperations.AddTask(job.Id, task);
            }

ここでは、入力パラメータの定義として、コマンドラインで直接受け渡しましたが、これらをファイル経由にすることもできます。 Microsoft.Azure.Batch.FileStaging パッケージに定義されたクラスを利用するとAzure Batch に紐付いたストレージアカウントを利用して、ファイルの受け渡しが簡単にできます。

先ほどの前提条件としてバッチの終了時間を定義しておりませんでしたが、これについては、最大の見積もりを前提に制限時間内で終了するように考慮する必要があります。単純のノード数を増やせばスループットがあがりますし、マルチスレッド対応されているアプリケーションであればコア数を上げるのも手です。シングルスレッドの場合は、ノードあたりの最大並列実行数をコア数と同様にすればよいでしょう。いろんなパターンを考慮して制限時間内に終わるよう考慮すべきです。

結果の取得

標準出力と標準エラー出力に出力すると、それぞれノードの stdout.txtstderr.txt というファイルに書き込まれます。永続化されるわけではないので、これらが必要な場合は別途保存する必要がありますが、これらはCloudTask生成時にオプションとして設定しておくことで、実現可能です。

やや複雑なコードになりますが、OutputFilesプロパティにファイルパターンの条件と、アップロードする条件を定義し、アップロード先のBLOB(SAS付き)を指定します。

            task.OutputFiles = new List<OutputFile>
            {
                 new OutputFile(
                     filePattern: @"..\std*.txt",
                     destination: new OutputFileDestination(
                         new OutputFileBlobContainerDestination(
                             containerUrl: containerSasUrl,
                             path: taskId)),
                     uploadOptions: new OutputFileUploadOptions(
                         uploadCondition: OutputFileUploadCondition.TaskCompletion))
            };

まとめ

簡単にAzure Batch の概要と利用する上でのポイント、SDKの利用方法を説明しました。実世界での処理はこのように単純な話ばかりではありませんが、Azure Batch に触れる一助になればと思います。

お問い合わせはこちらから

問い合わせる
TOP