Amazon Web Services ブログ
【寄稿】オンプレミス環境の基幹系JavaバッチジョブのAWS移⾏検討の一事例
この投稿はアクセンチュア株式会社 Technology グループ所属のエンジニア 杉本 優里 氏、 マネージャー 竹内 誠一 氏に、AWS Step Functions、AWS Lambda、Amazon ECS および Amazon EventBridge を活用したプロトタイピングについて寄稿いただいたものです。
オンプレミス環境に構築されたシステムのクラウド移行を検討する際にはオンラインアプリやデータベースにまず目が行きますが、バッチの移行も不可欠のテーマです。しかしAWSにはオンプレミスで使われるジョブ管理システム(ジョブスケジューラ)を置き換えるサービスがないため、ジョブスケジューラごとEC2にリホストするケースや、AWSサービスを使ってリアーキテクトするケースが多いと思います。
本記事は、あるお客様のクラウド移行検討の中でJavaバッチの移行方法を検討し、課題解決策をプロトタイピングによる実証も交えて提案した経験をベースに、その案件で取り上げた課題や解決策をご紹介します。
このお客様の特徴としては「極力マネージドサービスを使用することとし、EC2の使用は原則認めない」というクラウド利用ポリシーを定めていたのでEC2へのリホストは採用できませんでした。またオンプレミス環境の機構は一部残さなければならなかったので、オンプレミスとクラウドにまたがるバッチジョブフローのコントロールが必須となり、オンプレのジョブ管理システムからAWS上のバッチジョブフローをコントロールする仕組みを考案することになりました。
これらを含め、今回の検討における前提条件を整理すると6つです。
- 可能な限り現⾏のJavaプログラムを流⽤する
- シェルスクリプトで複数のJavaプログラムの実⾏順が定義されている
- クラウドではマネージドサービスの利用を原則とし、EC2は利⽤しない
- 現⾏のバッチはオンプレミス環境にあるジョブ管理システム(ジョブスケジューラ)が制御している
- ジョブ管理システムはAWSに移行しない
- バッチジョブフローは複数のアプリにまたがっており、すべてのアプリがクラウドに移行するとは限らない
また、本件は3つの段階で検討を⾏っております。
- Javaプログラムの実⾏環境となるサービスの選定
- シェルスクリプトの代替サービスの選定
- 既存のジョブ管理システムにクラウド上のバッチジョブフローを制御させる方法
今後を踏まえてジョブ管理システムをAWSサービスで実現する案にも触れておりますので、ご興味のある⽅はご覧ください。
バッチ概要
バッチ処理はメインフレーム登場当時から存在し、エンタープライズシステムの効率的なデータ処理⼿段として進化を遂げてきました。バッチはジョブ管理システムというソフトウェアによって制御され、決められた順序で実⾏されます。単に決められた順序で実⾏するだけでなく、多くのジョブ管理システムは以下の機能を提供しています。
- 複数の先行ジョブ・後続ジョブを持ち、複数のアプリ・複数のサーバにまたがるジョブをスケジュール
- バッチ処理の進⾏状況をリアルタイムに可視化し、異常があれば検知・通知
- バッチ実⾏の⼀時停⽌・再開、スケジュールの動的な組み換え
- ⽉初xx⽇⽬、第x〇曜⽇の前⽇等の複雑な実⾏⽇ルールによるジョブのスケジュール
個々のバッチジョブは、シェルスクリプト(Unix、Linux)、バッチファイル(Windows)、JCL(メインフレーム)などで実装され、それぞれのOSの制御の下で実⾏します。バッチジョブを実⾏するサーバにはジョブ管理システムのエージェントが常駐し、ジョブ管理システムのマスターサーバから指⽰を受けてバッチジョブを起動したり、バッチジョブの完了をマスターサーバに通知したりします。
Javaプログラムの実⾏環境となるサービスの選定
まずはJavaで構成されたプログラムの移⾏先について選定を⾏いました。「AWS Lambda」と「Amazon ECS」を候補として検証した結果最も重要なポイントが実行時間でした。よってどちらか⼀⽅ではなく、15分未満に完了する処理はAWS Lambda、15分以上かかる処理はECS Taskと 処理時間に応じて使い分ける⽅法をとることとしました。
ECS Taskのみを利⽤して処理時間をより最適化することを考える場合、バッチのリトライ処理等のジョブ管理の粒度によっても変わってきますが複数個の処理を1つのコンテナにまとめる⽅法も考えられます。加えて、並列処理が可能な場合はタスクを複数個実行し、並列に処理させることも可能です。
重視した観点の比較結果を下表に示します。
考慮点 | Lambda Function | ECS Task |
---|---|---|
既存Javaプログラムの移植 | 可能 ※コード修正必須 |
可能 |
実行時間制約 | 最長15分 | なし |
起動リードタイム | ~数秒 | ~数十秒 |
ファイル入出力 | Amazon S3、Amazon EFSとも利用可能 | |
CI/CD対応(ビルド・デプロイ自働化) | 可能 | |
DBアクセス | 可能 | |
複数Javaプログラムの順次処理方法 | AWS Step FunctionsでLambda Functionを連結 | AWS Step FunctionsでECS Taskを連結、またはECS Task内でシェルスクリプトを使ってJavaアプリを連結 |
バッチの移行方針
まず用語を定義します。以降このブログでは一連のバッチ処理の連鎖をバッチジョブフロー、連鎖の中の個々の実行単位(タスク)をバッチジョブと呼びます。オンプレミス環境の現行システムでは、一個のバッチジョブは一個のシェルスクリプトで実装され、ジョブ管理システムがバッチジョブフローに従ってシェルスクリプトを起動しているものとします。
次に移行対象となるバッチジョブフローの特徴を下図に例を挙げながら確認します。
この図に表現した特徴は次の3点です。
- バッチジョブは複数の先行ジョブを持つことができる。先行ジョブがすべて完了してからバッチジョブが起動する。
- バッチジョブは複数の後続ジョブを持つことができる。また複数に分岐したフローが1つに収束しなくてもよい。
- 他のアプリに属するバッチジョブを先行ジョブまたは後続ジョブとすることができる。他のアプリはオンプレに残留している場合もある。
これらの特徴は基本的にバッチジョブフローに求められるものであり、バッチをクラウドに移行するためのジョブ管理システムの要件となります。前提条件によりクラウド上ではEC2を使用しない方針なので、オンプレミス環境で使用しているジョブ管理システムソフトウェアをクラウド上にインストールすることはできません。既存のジョブ管理システムのスコープをクラウドに拡張する、クラウドのマネージドシステムでバッチジョブフローをコントロールする等の対策が必要になります。また個々のバッチジョブの実体であるシェルスクリプトについても、マネージドサービスによる代替が必要になります。以降の章でシェルスクリプトの代替案、およびジョブ管理システムの実現方針について議論します。
シェルスクリプトの代替サービスの選定
次に、ジョブ実⾏⽤のシェルスクリプトの移⾏先の検討を⾏いました。「AWS Step Functions」と「AWS Batch」 の2つを候補とし、AWS Step Functionsを採⽤しました。
バッチジョブは複数のプログラムで構成されており順序定義は必須です。特に、処理アクションが実⾏失敗した場合、失敗した場所に応じてロールバック処理を細かに設定する必要がありました。AWS Step FunctionsはUI(Workflow Studio)を利⽤した処理フローを定義することができ、実⾏ステータスに応じて分岐処理も可能です。それに加え、Lambda FunctionまたはECS Taskで作成された複数のプログラムを実⾏する必要があったため、AWS Step Functionsが良いと考えました。
AWS Batchは、大量データの処理が効率的に行えることと、既存のシェルスクリプトをそのまま流用できるため候補としていました。しかしながら、ジョブ管理システムからジョブを実行した際に起動リードタイムにより瞬時に実行できない点、シェルスクリプトから呼び出された実⾏プログラムそれぞれで完了ステータスを確認したいという点において利⽤できませんでした。
クラウド上のバッチジョブフローを制御する仕組み
バッチジョブフローのクラウド移行は、クラウドに移行したバッチとオンプレミス環境に留まっているバッチが混在する段階(フェーズ1)と、クラウドへの移行が完了した段階(フェーズ2)の2段階で進むと想定します。この時、それぞれの段階で最適なジョブ管理システムは異なるものになります。
フェーズ1ではオンプレミス環境に留まっているバッチジョブフローがあり、その部分の制御には既存のジョブ管理システムを継続するのが合理的です。
このような条件下で下表に示すように三案を比較検討しました。
# | クラウド上のバッチジョブフロー制御の仕組み案 | 評価 |
---|---|---|
1 | 既存のジョブ管理システムにクラウド上のバッチジョブフローを制御させる | バッチジョブのシェルスクリプトはオンプレミス環境での実行を前提に、シェルスクリプト内からクラウド上のバッチジョブ(Step Functionsステートマシン)を起動して完了を検知する仕組み(連携機構)をカスタムで実装する必要がある。 既存のバッチジョブフロー管理担当者にとって、運用の変化が最も小さく、移行のハードルが最も低い。 オンプレミス環境のバッチジョブを削減しようとしている中で、既存のジョブ管理システムへの投資を最小限に抑えられる。 カスタムな実装が簡単に実現できるならば、最も現実的と考える。 |
2 | オンプレミス環境のジョブ管理システムをクラウド上のバッチジョブフローを制御可能なシステムに切り替える | ジョブ管理システム更改への投資規模が案1(カスタム連携機構の追加)に比べて大きなものになり得る。 クラウド移行開始の時期はジョブ管理システムの選定が完了するまで待たされることになる。フェーズ1が既存のジョブ管理システムのバージョンアップ予定がある場合は、既存のジョブ管理システムの更改が必要となるので、投資規模はデメリットではなくなる。 |
3 | クラウドだけでバッチジョブフローを制御する | バッチの移行方針で示した要件を満たすクラウドサービスは存在しないため、クラウド上でバッチジョブフローを制御するためには、カスタムのジョブ管理システムを構築する必要がある。 オンプレミス環境とクラウド上のジョブ管理システム間で連携する仕組みもカスタムで開発する必要がある。 クラウド移行開始時期はカスタムのジョブ管理システムのリリースまで待たされることになる。 近い将来マネージドサービスとしてジョブ管理システムが提供される見通しがあるなら、マネージドサービスのリリースを待ってもよい。 クラウド上のバッチジョブフローが、オンプレミス環境に依存せずに制御できるという点で、この方式がバッチのクラウド移行のゴールになり得る。 |
バッチはアプリの一部であり、バッチのクラウド移行を遅らせることはアプリのクラウド移行を遅らせることになるので、その観点で案2と案3は望ましくありません。直近のフェーズ1ではアプリのクラウド移行を妨げない案1を採用し、クラウド移行のゴールとしての案3の実現をフェーズ2で目指すのが現実的かつ理想的と考えました。以下の章で案1と案3についてもう少し掘り下げて説明します。更にプロトタイプを作成して期待通り動作することを確認したのですが、その詳細については別のブログ「オンプレミス環境のバッチジョブフローのAWS移行方法検討事例」でご紹介いたします。
既存のジョブ管理システムにクラウド上のバッチジョブフローを制御させる方法
この仕組みの構成を下図に示します。左側のオンプレミス環境の枠が、現行のジョブ管理システムとバッチジョブのスコープを表しています。ジョブ管理システムのエージェントが、バッチジョブフローに従ってバッチジョブ(ここではシェルスクリプト)を起動し完了を確認します。シェルスクリプトはエージェントと同じサーバで実行し、内部でJavaプログラムや、その前処理・後処理のためのプログラム等を呼び出しています。
シェルスクリプトの内部でクラウド上のバッチジョブ(ここではStep Functionsステートマシン)を呼び出し、その完了を検知してシェルスクリプトを終了させることができれば、このシェルスクリプトを通してオンプレミス環境のジョブ管理システムがクラウド上のバッチジョブフローを制御できます。
この方式の最大の利点は、既存のジョブ管理システムをそのまま継続使用できる点にあります。ジョブ管理システムからは、クラウド上に移行したバッチジョブもオンプレミス環境のシェルスクリプトとして扱えるので、ジョブ管理システムへの機能追加も、バッチ運用担当者の再教育も基本的に不要です。クラウドに移行したバッチジョブとオンプレミス環境に残るバッチジョブが混在するバッチジョブフローの制御も問題ありません。
シェルスクリプト内部でクラウド上のバッチジョブを起動し完了を検知する仕組みを開発・維持する必要がありますが、すべてのバッチジョブに応用できる仕組みが1つあればいいので、開発・維持の負担は比較的軽微だと考えます。
弱点としては、クラウド上のバッチジョブフローの制御を、オンプレミス環境のインフラに依存しなければならない点が挙げられます。アプリのクラウド移行プロジェクトの過程で、バッチジョブフローがオンプレミス環境とクラウドにまたがって実行されている状況ではオンプレミス環境のインフラへの依存はいたしかたありませんが、バッチジョブフローがクラウドだけで実行できるようになっても、バッチジョブフローの制御をオンプレミス環境のインフラに依存していると、クラウドの俊敏性や柔軟性が十分に享受できないかもしれません。
この方式は、アプリのクラウド移行の初期段階で移行負荷を軽減するための暫定策と位置づけ、クラウド移行のゴールにおいてはクラウドだけでバッチジョブフローを制御する仕組みがあることが理想です。これにあたるのが前述の案3です。
クラウドだけでバッチジョブフローを制御する方法
「バッチの移行方針」の章でバッチジョブフローの特徴を3点挙げましたが、このブログ執筆時点では残念ながらAWS Step Functionsであってもこれらをすべて受け入れることはできていません。そこでAWS Step Functions以外のサービスも組み合わせることでこれらの特徴に適合するジョブスケジューラの構築を目指しました。これを本ブログではカスタムジョブスケジューラと呼ぶことにします。バッチジョブフローの各特徴に対するカスタムジョブスケジューラの対応方針を以下に整理します。
# | バッチジョブフローの特徴 | AWS Step Functions単体の適合性 | カスタムジョブスケジューラの対応方針 |
---|---|---|---|
1 | バッチジョブは複数の先行ジョブを持つことができる。先行ジョブがすべて完了してからバッチジョブが起動する。 | ステートマシンは必ず単一のStartから開始することになっている。開始点として複数のStartを設定し、それぞれに始動条件を設定するようなことはできない。 | Lambda関数にバッチジョブを起動させ、起動する前に先行ジョブの完了状況をチェックさせる。 先行ジョブの完了状況はDBで管理する。 |
2 | バッチジョブは複数の後続ジョブを持つことができる。また複数に分岐したフローが1つに収束しなくてもよい。 | 並列ステートとして複数の後続ステートを並列実行させることは可能だが、複数のステートがすべて完了してから後続のステートが起動する必要がある(分岐したフローが1つに収束する)。 | 上記の先行ジョブと同様に、後続ジョブの有無もDBで管理し、それに従ってLambda関数がバッチジョブを起動する。 |
3 | 他のアプリに属するバッチジョブを先行ジョブまたは後続ジョブとすることができる。他のアプリはオンプレに残留している場合もある。 | あるステートマシンに属するステートが、他のステートマシンに属するステートと先行・後続の関係を持つことはできない。 | Amazon EventBridgeを利用し、オンプレで実行されるものを含め、先行バッチ完了や後続バッチ起動をイベントで通知する。 |
このカスタムジョブスケジューラの仕組みを図示すると以下のようになります。この仕組みの詳細は別のブログ「オンプレミス環境のバッチジョブフローのAWS移行方法検討事例」にて説明します。
最後に
本ブログでは、あるクライアントにおいてオンプレミス環境のバッチジョブをクラウドに移行方針を検討し、移行後に必要となるバッチジョブフロー管理の仕組みを考案してプロトタイプを検証した事例を紹介しました。
まず、バッチジョブフローを構成する個々のバッチジョブは、現行ではJava言語で開発されたプログラムをシェルスクリプトから呼び出しているという前提で、移行後のJavaプログラムの実行環境はLambda関数とECSタスクを使い分けることとし、これらをAWS Step Functionsステートマシンから呼び出す方針としました。
バッチジョブフローを制御するジョブスケジューラはバッチ移行の段階によって使い分ける方針とし、フェーズ1ではオンプレミス環境のジョブスケジューラを使ってクラウド上のステートマシンを制御する方法、フェーズ2ではオンプレミス環境に依存しないカスタムジョブスケジューラを開発・運用する方針としました。各フェーズの詳細については別のブログ「オンプレミス環境のバッチジョブフローのAWS移行方法検討事例」にて詳細を紹介していますので、興味のある方はそちらもご一読ください。
様々なプロジェクトによって検討事項は異なるかとは思いますが、この記事を通じて検討における一つの参考になりますと幸いです。
著者について
杉本 優里 アクセンチュア株式会社 |
|
竹内 誠一 アクセンチュア株式会社 |