WindowsでワークフローマネージャのAzkabanを動かす

Hadoop向けのワークフローマネージャのAzkaban（[https://azkaban.github.io](https://azkaban.github.io)）をWindowsで動くようにパッチをあててビルドする。

Azkabanは、Hadoop向けといいつつも、コマンドをスケジュールに合わせて動かすことや複数の依存関係のあるジョブを動かすことができるので、Hadoopと関係なく、定期的に動かしたいタスク、特に複数の依存関係のあるタスクを何でも動かすのに利用できる。

ジョブは、簡単なプロパティ形式の記述をするだけでよいし、Web UIは、シンプルで使いやすく処理時間のグラフなども表示される、Web APIもあるのでAzkaban自身を自動処理させることもできることが良い点。逆に、いまひとつな点は、Web UIから、ジョブの追加を行うことができないので、予めテキストエディタで編集して .zip形式でアーカイブしてアップロードする必要がある。
一度ジョブをアップロードしてしまえば、ジョブのプロパティを変更、追加するためのUIは（見つけにくい場所だが）あるので、簡単な編集はできる。
ジョブの開発やテストで、ジョブから呼び出すスクリプトを編集する場合などでは、プロジェクトフォルダに展開されたジョブファイルを直接編集するか、まじめにやるなら、Web APIからアップロードして実行すれば、それほど困難な作業ではない。


ビルドが面倒ならば
パッチ済みバイナリー（ここではSoloサーバー）をダウンロード（[azkaban-solo-server-2.6.4.zip](https://github.com/qtwi/msys-azkaban-2.6.4/raw/master/distributions/azkaban-solo-server-2.6.4.zip)）して、セットアップへ。


## Azkabanのビルド
azkaban 2.6.4のソースをgithubからダウンロード(https://github.com/azkaban/azkaban/archive/2.6.4.zip) するかクローンする。
Windowsで動作するようにパッチを作成したので、[azkaban-2.6.4-src-mingw-0002.patch](https://github.com/qtwi/msys-azkaban-2.6.4/raw/master/patch/azkaban-2.6.4-src-mingw-0002.patch)をダウンロードしてあてる。
パッチをあてないと、ビルドはできるが、実際に動作させると、エラーがでてジョブがうまく動作しないと思う。

```
cd azkaban-2.6.4
patch -u -p1 < azkaban-2.6.4-src-mingw-0002.patch
```

ソースをダウンロードしてきた場合は、ビルド途中に実行される gitコマンドでエラーするので、事前に以下のコマンドを実行しておく。クローンした場合はすでに .gitフォルダがあるはずなので不要。

```
git init
git add -A
git commit -am "init"
git config --add remote.origin.url "https://github.com/yourname/azkaban"
```

ビルドは、gradleで行うが、もし会社などでProxyの設定が必要な場合は、gradlew を編集し、最初のあたりに DEFAULT_JVM_OPTS か JAVA_OPTSで Proxyの設定を行っておく。

```
DEFAULT_JVM_OPTS="-Dhttp.proxyHost=your.domain -Dhttp.proxyPort=8080"
```

では、ビルド開始するが、Windowsでビルドする場合、テストを実行されるとエラーがでて止まってしまうので、テストはスキップする。

```
./gradlew -x test distZip
```

依存ライブラリがダウンロードできていれば、ほどなく、終了し、build/distributions フォルダに各バイナリが出来上がっている。

## Azkabanのセットアップ
ここでは、簡単なSoloサーバーをセットアップする。SoloサーバーならMySQLのセットアップも不要だし、１コマンドで起動して使える。

まずは、conf/azkaban.propertiesを編集して、最低限、タイムゾーンの設定を行う必要がある。また、デフォルトの http/https ポート番号が他のアプリとぶつかりやすい値なので、確認して設定しておく。ここでは、それぞれ、8581と8543に設定している。

```properties:azkaban.properties
default.timezone.id=Asia/Tokyo
;
jetty.ssl.port=8543
jetty.port=8581
;
```

ユーザーアカウントは、azkaban-users.xml に登録するが、デフォルトアカウントが、あまりよくないので、確認して、修正登録しておく。

あとは、sh （MSYS/MinGWでよい)上から、azkaban を起動する。コンソールにログが出力されるので、リダイレクトしておく。

```
bin/azkaban-solo-start.sh 1>azkaban-console.log 2>&1
```

起動したらブラウザから、http://localhost:8581/ （ポート番号を変更していなければ http://localhost:8081/ ）にアクセスし、設定したアカウントでログインする。（何もユーザーアカウント登録、削除をしていなければ、ユーザー azkaban パスワード azkabanでログインできる）

終了するには、以下のようにする。

```
bin/azkaban-solo-shutdown.sh
```


## Azkabanで、シンプルなジョブを動かす
Web UIにログインできたら、プロジェクトを１つ作成しておく。
次に、テキストエディタで、hello.job を作成する。

```job:hello.job
type=command
command=cmd /c "echo Hello Azkaban"
```

hello.job をzip形式で圧縮する。任意の方法で圧縮すればいいが、ここでは、7-zip のコマンドラインで圧縮する。

```
"C:\Program Files/7-Zip/7z.exe" a hello.zip hello.job
```

hello.zip をWeb UI上のプロジェクトのページからアップロードすると、hello ジョブができているから、Execute Flow をクリックし、ダイアログが表示されたら、右下の Execute をクリックすれば、ジョブが実行される。

今回のジョブはシンプルなので、すぐに終了する。終了時のページで、Job Listタブを開き、右端の Detailsをクリックすれば、ログが表示されるので、よく探すと、今回の Hello Azkaban の文字列が見つかると思う。

## Azkabanで、依存関係のあるジョブを動かす
Azkabanのよい所は、依存関係のある複数のジョブを動かせることなので、簡単にそれを試す。
ここではワークフローを設定するジョブと、３つのジョブを依存関係つきで作成する。

```job:ping-flow.job
type=flow
flow.name=ping-test
```

```job:ping-test.job
type=command
command=cmd /c "ping test finished"
dependencies=ping1,ping2
```

```job:ping1.job
type=command
command=ping -n 10 www.yahoo.co.jp
```

```job:ping2.job
type=command
command=ping -n 5 www.google.com
```

ping-flow は、ping-test をジョブに設定して、ping-test を実行するが、ping-test は、ping1とping2 に依存しているので、まずは、ping1、ping2 が先に実行されてから、ping-test が実行される。

これらをping-flow.zipにまとめて、新しいプロジェクトを作成してアップロードする。

```
"C:\Program Files\7-Zip\7z.exe a ping-flow.zip *.job
```

前回と同じようにジョブを実行すると、複数のジョブが実行されたことがわかると思う。ここで、ping1.job、ping2.jobが同時に実行されていることも確認できるはず。

ジョブには、プロパティとして変数を受け取ったり、結果をjson形式で保存し、次のジョブに渡すなどの機能もあるので、連続したジョブの処理をうまく記述すると複雑なジョブを複数のジョブから実現できると思う。

ちなみにジョブの結果表示のStatタブに何も表示されないが、これは本来のHadoopの実行結果を得るためのものなので、上記のようなコマンドでは利用できない。もし、何らかの表示をしたい場合は、コマンドに渡されてくる JOB_PROP_FILE 環境変数にあるファイルを読み、azkaban.job.attachment.file プロパティで指示されたファイルに配列形式のJSONを以下のように書けば、何かは表示される。

```json:
[{"state":{"totalMappers":0,"totalReducers":0}}]
```


以上、お疲れさまでした。