Asakusa バッチ実行環境の構成 (後編)

この記事は Asakusa Framework Advent Calendar 2013 の 14 日目の記事として書いています.

今回の記事は以下のページを参考にしています. 用語などもここでの定義を使用しています. http://docs.asakusafw.com/0.5.2/release/ja/html/administration/deployment-with-windgate.html#id1

記事が長いので前編, 後編に分けています.

前編はこちら → Asakusa バッチ実行環境の構成 (前編)

ネットワークの考慮

前編の図2で黄色の線で書いた部分はマシンの外側のデータ転送経路を表しています. この部分はマシン内部のデータの移動に比べ, 速度や安定性の面で劣るので特別な考慮が必要です.

WindGate

WindGate と WindGate Hadoop ブリッジの間の通信は Asakusa バッチの入出力データが通るため, バッチ実行時間のうち比較的長い時間維持されます. これは裏を返すと通信中の異常が起きる可能性が高いとも言えます. それを防ぐために, 通信のリトライ設定が行えるようになっています.

VPC

VPC は AWS の仮想プライベートクラウド環境サービスです. 専用のサブネットを所有し, その中でインターネットから入れないプライベート環境を構築したり, Web サーバを置いてサービスを公開したりできます.

VPC 上のプライベートネットワークには VPN で接続するのですが, この接続が切れることがままあります. それは, VPC 側の VPN ルータの問題が原因だったり, 使っている ISP の回線が不調だったのが原因だったりします. それらは避けようがないので, 接続が切れた場合に備えてリトライ処理を入れることになります.

ただし, 原因が VPC 側の設定や仮想ネットワークの管理プログラムの問題だった場合, サポートに問い合わせても「リトライ処理を入れて欲しい」以上の回答はもらえたことがありません. そういうサービスと思って使っています.

一番良い対策は次に解説する S3 をデータ受け渡しの中心に据えて, 極力長時間のセッションを張らないことです.

S3

前の記事で何度か書いていますが, このサービスは素晴しいです. AWS の中でも一番好きなサービスです. 非常に安価で, 容量の上限が無く, 障害が起きたりサービスが止まったりすることがほとんどないです. AWS も公式に “eleven nine” (1年間の平均喪失率が 0.1^11, 1年間で 10^11 個あるファイルのうち 1 個が壊れる計算になる) と信頼性を謳っています. → http://aws.amazon.com/jp/s3/faqs/#How_durable_is_Amazon_S3

S3 はデータの受け渡しに使えますし, マーカーファイルを使うことで状態を他のシステムに通知することもできます. もちろん AWS なら SQS というメッセージキューイングのサービスがあるのですが, AWS から他のサービスへ移るコストを考えるとマーカーファイルを使っておくのも良いと思います.

Asakusa バッチアプリケーションの配置

Asakusa には様々なコンポーネントがあり, それらを組み合わせてモジュールを構成します. モジュールは分散して配置されることもあります. 分散して配置したときに気を付けないといけないのは,「Asakusa バッチアプリケーションを含むモジュールは全て同一の batchapps.jar を使用しないといけない」ということです. 「同一」というのは「1つの batchapps.jar をコピーしたもの」という意味です.

Asakusa ではコンパイルするたびに出来上がるジョブネット (Hadoop ジョブ群の依存関係) 構成は一定していません. 分散配置された Asakusa バッチアプリケーションが持っているジョブネットは同じものでなくてはいけないため, 別々にビルドした batchapps.jar が混在している場合は InconsistentApplicationException 例外が発生します. これは実行してみないと分からないので, 意外とハマるのではないでしょうか.

全体配置

ここまでの話を踏まえ, 全体構成のパターンを考えてみましょう. Hadoop クラスタが EC2 クラスタや EMR クラスタだった場合の特別な話は適宜書いていきます. またそれぞれのパターンに対して YAESS にはどんな設定をしないといけないかも書いていきます.

  1. all-in-one

    まず一番シンプルなのが, 全てのモジュールが 1 箇所にあり, 入力元も出力先もそのマシン内に収まっているパターン. 開発環境で外部連携も含めてテストしたいときはこの構成になると思います.

    この場合は悩むことはあまりありません. YAESS の設定もデフォルトの設定ファイルのままで大丈夫です.

  2. クラスタが外部

    YAESS と Hadoop クライアントが別のマシンにいるパターン. Hadoop クラスタの切り替えがしやすいので, all-in-one パターンよりは本番運用向きでしょう. EC2 クラスタや EMR クラスタを使用していて, 都度クラスタの起動と停止を行う運用の場合は, 必然的に YAESS と Hadoop クライアントが別のマシンになります

    Hadoop 実行系コンポーネントは Hadoop クライアントと同じマシンに配置します. その場所へのアクセス情報 (IP アドレス, SSH ポート, SSH 秘密鍵など) は YAESS の設定ファイルである yaess.properties に記述します. (yaess.properties は ${ASAKUSA_HOME}/yaess/conf 以下にあります)

    デメリットは, YAESS がいるマシンと Hadoop 実行系コンポーネントがいるマシンに 同一の Asakusa バッチアプリケーションを配置しないといけない制限があることです. また WindGate を使って HDFS へデータを送信する場合, SSH 接続を長時間張ることになり, 障害が起こる危険性が増します.

    それぞれのマシンに必要最低限のコンポーネントを含んだモジュールを配置することもできますが, リリースの手間を考慮して, 全く同じものを配置しても問題ありません.

  3. 完全分散

    YAESS と WindGate と Hadoop クライアントが別のマシンにいるパターン. 普通はやる必要が無いかもしれませんが, 入力の場所と出力の場所が違うマシンである場合はこの構成を取ります.

    WindGate には「プロファイル」という概念があり, WindGate の接続構成を表現しています. yaess.properties には, このプロファイルをどのマシンで使用するかを記述し, YAESS はその情報を元にそのマシンで WindGate のプロセスを起動します.

    WindGate の接続構成は ${ASAKUSA_HOME}/windgate/profile 以下にある プロファイル名.properties というファイルに記述されています. WindGate はこの接続構成の設定をもとにデータの取得や送信を行います. 実は同一のマシンにある WindGate でも別のプロファイルで起動された場合, 別の構成情報を使って動作します.

    デメリットは「2. クラスタが外部」のパターンと同様です. ある程度長時間のデータ転送を行うことで, SSH 接続で障害が起きる確率が上がります.

    リリースも手間を考えると, YAESS 用, WindGate 用, Hadoop 実行系コンポーネント用で同じものを使うのでも良いでしょう.

それぞれのパターンで見たように YAESS の設定ファイルである yaess.properties ファイルには, Hadoop クライアントや WindGate の構成情報を記述します. さらには, それらのコンポーネントが使用する環境の環境変数の設定も記述することができます. 設定ファイルを見て Asakusa の構成を知るには 「yaess.properties を見て全体構成を把握し, そこに書かれている WindGate プロファイルの設定から WindGate が接続するデータの場所を知る」という流れになります.

終わりに

Asakusa 運用環境の構成の全体を 1 つにまとめ上げる部分の話を書きました. 1 つのマシンで動くアプリケーションよりもかなり複雑ですが, yaess.properties と WindGate プロファイルを読むうちにだんだんと感覚がつかめてくるでしょう. ここに書いたこと以外の機能も YAESS, WindGate, Direct I/O にはまだまだあるので, 本家のドキュメント をあたってみてください. もちろん ThunderGate も要件に合えば検討してみてください.

では全体構成の話はここでいったん終わりになります. (今回は構成の話のわりに図が少なかったので, 後程, 補足の記事は書くかもしれません)

余談

リリースノート を改めて見返すと, どうやら自分は ver. 0.2.1 の頃から Asakusa Framework を利用していたようです. ThunerGate だけだった入出力コンポーネントに WindGate, Direct I/O が加わり, バッチ全体の実行機構である YAESS も追加され, あの頃とは運用面でだいぶ変わったなぁと思います. YAESS 以前は experimental.sh なんて名前の shell script を実行してました. 本番で運用する名前とは思えないですね(汗) Gradle を使ってお洒落にビルドできるようになりましたし, Asakusa Framework は今後はどんな姿に変わっていくのでしょうね.