Azure BatchとDockerで管理サーバレスバッチ環境を作る
サーバレスって言いたいだけじゃないです
Linux向けAzure BatchのPreviewがはじまりました。地味ですが、なかなかのポテンシャルです。
クラウドでバッチを走らせる時にチャレンジしたいことの筆頭は「ジョブを走らせる時だけサーバ使う。待機時間は消しておいて、 節約」でしょう。
ですが、仕組み作りが意外に面倒なんですよね。管理サーバを作って、ジョブ管理ソフト入れて、Azure SDK/CLI入れて。クレデンシャルを安全に管理して。可用性確保して。バックアップして。で、管理サーバは消せずに常時起動。なんか中途半端です。
その課題、Azure Batchを使って解決しましょう。レッツ管理サーバレスバッチ処理。
コンセプト
- 管理サーバを作らない
- Azure Batchコマンドでジョブを投入したら、あとはスケジュール通りに定期実行される
- ジョブ実行サーバ群(Pool)は必要な時に作成され、処理が終わったら削除される
- サーバの迅速な作成とアプリ可搬性担保のため、dockerを使う
- セットアップスクリプト、タスク実行ファイル、アプリ向け入力/出力ファイルはオブジェクトストレージに格納
サンプル
Githubにソースを置いておきます。
バッチアカウントとストレージアカウント、コンテナの作成とアプリ、データの配置
公式ドキュメントで概要を確認しましょう。うっすら理解できたら、バッチアカウントとストレージアカウントを作成します。
ストレージアカウントに、Blobコンテナを作ります。サンプルの構成は以下の通り。
.
├── blob
│ ├── application
│ │ ├── starttask.sh
│ │ └── task.sh
│ ├── input
│ │ └── the_star_spangled_banner.txt
│ └── output
applicationコンテナに、ジョブ実行サーバ作成時のスクリプト(starttask.sh)と、タスク実行時のスクリプト(task.sh)を配置します。
- starttask.sh - docker engineをインストールします
- task.sh - docker hubからサンプルアプリが入ったコンテナを持ってきて実行します。サンプルはPythonで書いたシンプルなWord Countアプリです
また、アプリにデータをわたすinputコンテナと、実行結果を書き込むoutputコンテナも作ります。サンプルのinputデータはアメリカ国歌です。
コンテナ、ファイルには、適宜SASを生成しておいてください。inputではreadとlist、outputでは加えてwrite権限を。
さて、いよいよジョブをJSONで定義します。詳細は公式ドキュメントを確認してください。ポイントだけまとめます。
- 2016/04/29 05:30(UTC)から開始する - schedule/doNotRunUntil
- 4時間ごとに実行する - schedule/recurrenceInterval
- ジョブ実行後にサーバプールを削除する - jobSpecification/poolInfo/autoPoolSpecification/poolLifetimeOption
- ジョブ実行時にtask.shを呼び出す - jobSpecification/jobManagerTask/commandLine
- サーバはUbuntu 14.04とする - jobSpecification/poolInfo/autoPoolSpecification/virtualMachineConfiguration
- サーバ数は1台とする - jobSpecification/poolInfo/autoPoolSpecification/pool/targetDedicated
- サーバプール作成時にstarttask.shを呼び出す - jobSpecification/poolInfo/autoPoolSpecification/pool/startTask
{
"odata.metadata":"https://myaccount.myregion.batch.azure.com/$metadata#jobschedules/@Element",
"id":"myjobschedule1",
"schedule": {
"doNotRunUntil":"2016-04-29T05:30:00.000Z",
"recurrenceInterval":"PT4H"
},
"jobSpecification": {
"priority":100,
"constraints": {
"maxWallClockTime":"PT1H",
"maxTaskRetryCount":-1
},
"jobManagerTask": {
"id":"mytask1",
"commandLine":"/bin/bash -c 'export LC_ALL=en_US.UTF-8; ./task.sh'",
"resourceFiles": [ {
"blobSource":"yourbloburi&sas",
"filePath":"task.sh"
}],
"environmentSettings": [ {
"name":"VAR1",
"value":"hello"
} ],
"constraints": {
"maxWallClockTime":"PT1H",
"maxTaskRetryCount":0,
"retentionTime":"PT1H"
},
"killJobOnCompletion":false,
"runElevated":true,
"runExclusive":true
},
"poolInfo": {
"autoPoolSpecification": {
"autoPoolIdPrefix":"mypool",
"poolLifetimeOption":"job",
"pool": {
"vmSize":"STANDARD_D1",
"virtualMachineConfiguration": {
"imageReference": {
"publisher":"Canonical",
"offer":"UbuntuServer",
"sku":"14.04.4-LTS",
"version":"latest"
},
"nodeAgentSKUId":"batch.node.ubuntu 14.04"
},
"resizeTimeout":"PT15M",
"targetDedicated":1,
"maxTasksPerNode":1,
"taskSchedulingPolicy": {
"nodeFillType":"Spread"
},
"enableAutoScale":false,
"enableInterNodeCommunication":false,
"startTask": {
"commandLine":"/bin/bash -c 'export LC_ALL=en_US.UTF-8; ./starttask.sh'",
"resourceFiles": [ {
"blobSource":"yourbloburi&sas",
"filePath":"starttask.sh"
} ],
"environmentSettings": [ {
"name":"VAR2",
"value":"Chao"
} ],
"runElevated":true,
"waitForSuccess":true
},
"metadata": [ {
"name":"myproperty",
"value":"myvalue"
} ]
}
}
}
}
}
そろそろ人類はJSONに変わるやり口を発明すべきですが、XMLよりはいいですね。
それはさておき、面白そうなパラメータたち。並列バッチやジョブリリース時のタスクなど、今回使っていないものもまだまだあります。応用版はまたの機会に。
ではスケジュールジョブをAzure BatchにCLIで送り込みます。
azure batch job-schedule create -f ./create_jobsched.json -u https://yourendpoint.location.batch.azure.com -a yourbatchaccount -k yourbatchaccountkey
以上です。あとはAzureにお任せです。4時間に1回、アメリカ国歌の単語を数える刺身タンポポなジョブですが、コツコツいきましょう。
Azure Automationとの使い分け
Azure Automationを使っても、ジョブの定期実行はできます。大きな違いは、PowerShellの要否と並列実行フレームワークの有無です。Azure AutomationはPowerShell前提ですが、Azure BatchはPowerShellに馴染みのない人でも使うことができます。また、今回は触れませんでしたが、Azure Batchは並列バッチ、オートスケールなど、バッチ処理に特化した機能を提供していることが特長です。うまく使い分けましょう。