はじめに
こんにちは、自作の水やり機が安定稼働したことで毎日の水やりから解放され植物をめでるだけになった@fukajunです。
ロコガイドでは、プッシュ配信やメール配信/集計処理など多くのバッチ用インスタンスが動いています。
今回は、ロコガイドのバッチ実行をEC2からfargateに切り替えてみてどのような効果があったかを書きたいと思います。
ロコガイドのバッチ基盤について
本題に入る前にすこしロコガイドにおけるバッチ基盤の簡単な説明をしたいと思います。
弊社では、ほとんどのバッチ処理がkuroko2というバッチ基盤上で管理されています。
kuroko2は、Webの管理画面からYAML形式でジョブ定義を書いて、順次実行/並列実行/リトライなどバッチ処理のワークフローを作れます。
作ったワークフローはcron書式で設定した時間に定期実行してくれたり、ボタン「ポチッ」でワンタイムで実行してくれたりします。
そして、kuroko2から実行されたバッチのほとんどは、ECSのいくつかのバッチ用クラスタでコンテナタスクとして動きます。
fargate移行ビフォーアフター
それでは、バッチ処理関連の運用がfargateへの移行前どんな課題があり、移行後どのように改善したかを紹介したいと思います。
その1 インスタンスをスケジューリングして増やす必要がなくなった
メール配信やプッシュ配信など、並列化したいバッチ処理があったときに、ジョブ定義で並列数を増やしても、
それを実行するインスタンスも必要なため、特定の時刻に数十台のインスタンスを予め用意しておくなど、
ジョブ定義の更新と足並みを揃えてクラスター側も準備しておく必要がありました。
これには、開発チーム側とインフラチーム側双方で作業を行う必要がありました。
fargate化後は、開発チーム側でワークフローを更新して並列数を増やし、 インフラチームには、共有程度に「増やしたよ〜」くらいの声がけで完了となりました。
その2 バッチ個別にメモリー使用量/コア数を気軽に調整できるようになった
各バッチの処理に合わせてメモリサイズの異なるインスタンスを数パターン用意していました。
それでも、新なバッチの追加や、既存バッチ処理のチューニングのためにすこし多めのメモリーを
割り当てたい場合や、コア数を増やしたい場合は新たなバッチ用クラスターを追加し、
EC2インスタンスを追加する作業する必要がたびたびありました。
fargate化後は、これらの作業はほぼなくなりデフォルトから変えたい場合は、 ジョブ定義の環境変数に使いたいメモリー量とコア数の組み合わせを設定するだけでジョブ毎に細かく調整できるようになりました。
その3 バッチインスタンスのホストOSのことを忘れさせてくる
ロコガイドでは、多くのEC2インスタンスが稼働していますが、 定期的にOSの更新やミドルウェアの更新を計画して進めていく必要があります。 コンテナを実行するバッチ用インスタンスに頻繁な更新が必要なミドルウェアが含まれているかどうかは別として、管理インスタンス全体で見たときに、何割かのインスタンスがfargete化されたことで 日々のメンテナンスを考えるときに、その対象範囲を減らせることはとても嬉しいことです。
移行作業時の問題点
ほとんどの移行作業はスムーズに進めることができましたが、そうでない部分もありました。 ここからは、移行時にハマったことを紹介したいと思います。
fargateでは起動できないコンテナ
あるサービスのバッチがEC2では起動していたものの、fargateで動かすと起動しないということがありました。
ログを確認するとAWS-SDKを使っている箇所で落ちている事がわかりました。
IAM関連かなと思いインスタンスロールに付与している権限を一時的に緩めに設定してみましたが解決しませんでした。
これについて、調査をすすめる中でアプリケーション起動時に必要な設定値を取得している部分で落ちていることがわかりました。
設定値は、DynamoDBに保存したものをKMSで復号し利用しています。
さらに試行錯誤の末、そのサービスが扱う設定値の数が他サービスよりかなり多く、それが影響しているとわかりました。
最終的に、EC2使用時はメタデータエンドポイントへのアクセス頻度の制限を、ecs-agentの ECS_TASK_METADATA_RPS_LIMIT
という設定で、
緩和できていたが、fargateを利用する場合、その設定ができないため制限にかかるようになったということがわかりました。
この問題の原因は、設定値の取得に使っていたライブラリが取得のたびにAPIクライアントを再作成していたことにあり、 それを再利用するように修正することでメタデータエンドポイントへのアクセス回数を減らすことで解決できました。
fargate特有の問題になると、サーバーに乗り込んでデバッグできないので手間がかかります。 また試行錯誤するにもイメージの作り直しが必要で時間もかかります。 おかげでバッチ起動コマンドの前に、sedコマンドを実行することでライブラリの特定行にデバッグ文を差し込むという荒業を身につけることができました(笑)。
デバッグ文を追加後バッチを走らせるコマンド例
10行目と2行目にデバッグ文を挿入してから、バッチを実行するコマンド
後ろの行番号から記述すると、狙った行にデバッグ文を差し込みやすいです。
$ sed -i -e '10i puts "line10"' -e '2i puts "line2"' library.rb && rails runner Batch::Updater.run
固定IPを持つインスタンスがいた
一部メール配信用のバッチインスタンスもfargate化しようとしました。
しかし、それらのインスタンスはメール配信のために固定IPを必要としていました。
現時点でfargateにElasticIPを割り当てることができないため、今回はfargateへの移行を見送りました。
まとめ
ということで、バッチ用インスタンスをfargate化したときのことについて書いてきましたが、
まとめると「管理コストを圧倒的にさげることができてよかった!」と言えるのではないかと思います。
ロコガイドインフラチームでは、引き続きインフラの管理コストを下げるためのプロジェクトを進めています。
効率化によって限られたのリソースのなかで、大きな価値を生み出すための作業に集中できる環境をを作っていきたいですね。