Photoruction工事中!

Photoructionの開発ブログです!

図面ファイル非同期処理基盤のコンテナ化でやったこと

はじめに

こんにちは。株式会社フォトラクションでSREをしている角です。 現在、SREチームではシステムのコンテナ化を方針の一つとして活動しています。その中で私は、社内で変換サーバーと呼ばれている、図面ファイルを非同期で処理するシステムのインフラ移行を実施しています。 今回は、変換サーバーのコンテナ化について取り組んできたことを紹介したいと思います。

変換サーバーは何をしているか

変換サーバーは、ユーザーがアップロードした図面ファイル(画像/PDF)を、システム内で扱いやすい形に整えるバックグラウンド処理基盤です。主な役割は、フォーマット変換・複数ファイルの結合・分解といった図面データの前処理/加工を引き受けることにあります。 処理の流れはシンプルで、キューに積まれたタスクを定期ポーリングして拾い、対象ファイルをS3からダウンロード→変換処理→S3へアップロード、というワーカー型のパイプラインになっています。 実装は Windowsサーバー+.NET(C#)で、運用面の特徴として「サーバー上で実行ファイルをクリックするとGUIが立ち上がり、並行実行数などを入力してStartを押すと処理が走る」という、手動起動・手動設定のスタイルになっています。

変換サーバーの問題点

変換サーバーは主要な機能開発が約5年前に一段落して以降、大きな改修は多くありませんでした。Photoruction本体の機能開発とのトレードオフがある中で、限られたリソースで運用を継続してきた、という背景があります。その結果、手作業や暗黙知が少しずつ積み重なり、運用負荷が高くなっていました。

現状把握や変更にかかる負荷が大きい

具体的には、新しいインスタンスへデプロイする時、インスタンスを起動して、プロセスを起動して、設定を反映して、という作業を毎回手でやる必要がありました。そのため、作業のたびにヒューマンエラーのリスクがありました。 また、ログがWindowsサーバー内のテキストファイルに出ているため、調査のたびにまず「どのサーバーの、どのログファイルを見るべきか」から始まっていました。複数台にまたがる事象だと、ログを集めて時系列を揃えて突き合わせる必要が出てきて、横断検索ができないぶん、初動がどうしても重くなりました。

変更への抵抗感が、システムの安定性を落としていた

その結果、いらなくなったシステムが止められずに残っていたり、インスタンスのスペックに応じたプロセス配置が最適化されないままになっていました。特に、スペックが足りなくなったときに既存サーバーの構成を見直して載せ替えるのではなく、既存はそのままに高スペックなサーバーを追加で立てる、という方向に寄りやすく、負荷の偏りが解消されないまま積み上がっていきました。その結果、低スペック側はCPU 70〜100%でカツカツなのに、高スペック側は30%程度で余裕がある、といった歪みが起きていました。また、古いインスタンスは1台に複数システムが同居し続ける構成になっており、どこかの負荷増加が別システムの遅延や障害に波及しやすい状態が解消されずにいました。

運用負荷を軽減するためにECS Fargateに載せることにした

変換サーバーだけ特別な運用にならないように、社内で既に利用されているECS Fargateに載せ換えることにしました。普段の運用の延長で見られる形に揃えることで、判断や引き継ぎ、障害対応のコストを下げる狙いがありました。 Fargateで運用することにすると、自然とログをCloudWatch Logsに集約することになるので、横断検索と突合がしやすい状態にもなります。 また、デプロイはGitHub Actionsをつかって自動化することにしました。それによりあいまいになっていたデプロイ方法も標準化でき、期間が空いたり人が変わっても対応可能になります。

実際にやってみると思ったようにはいかなかった

実装を初めてから、とりあえず動くまではかなり順調に行きました。生成AIを利用しているので、知らないコードでも数日でメインの機能がFargate上で動くまで持っていけました。 それよりも、一番時間を使ったのは現状把握と動作確認でした。本番に出すためには、人間がちゃんと確認して、問題ないことを説明できる必要があります。そのために、機能が正常に動いているかや、パフォーマンスが劣化していないかなどの確認を実施しました。しかし、自分はこの移行プロジェクトで初めてまともに変換サーバーにかかわったため、細かい仕様や、動作確認のノウハウみたいなものを持ち合わせていませんでした。なので、ドキュメントやソースコードを見て動作確認手順を考えて実施したり、今まで開発や運用にかかわってきた人に依頼するなどで進めました。そのたびに足りない部分が見つかっては対応しました。 例えば、アップロードされた図面をまとめてZIPにしてダウンロードできる機能があるのですが、最初はそれが本番でどのくらいの規模で動いているのか掴めていませんでした。調べてみると、1回の処理で数十GBのデータを対象にしていて、しかも完了まで数日かかるケースがあることが分かりました。想像していたよりも重い処理で、正直驚きました。加えて、この機能は他と構成が違っていたので、それ専用のインフラも用意して検証を進めました。しかし、本番と同じ環境を用意できなかったためパフォーマンスに問題がないか十分な試験ができなかったことと、リリース直後の動作確認が素早くできないことから、今回のリリースのスコープからは外すことにしました。 もう一つ印象に残っているのは、この変換サーバーを開発していた人にコードレビューをお願いしたときのことです。「Javaのランタイムが入っていないけど大丈夫なのか」という指摘が来て、C#なのに何でJavaなのかと思って調べたところ、C#の中からJavaプロセスを起動している処理が確かに入っていました。とはいえ動作確認では問題が出ていなかったので理由を追うと、過去の個別要件向けの分岐が残っていた部分で、今は使われていない機能でした。念のためDBの実行履歴も確認しましたが、Java処理が走るオプション付きのレコードは見つかりませんでした。とりあえずJavaを入れて動く状態にしたものの、利用していない機能に深入りするのを避けて、細かい動作確認はせずリリースすることにしました。

結果

本番リリースにより、運用面では次の点が変わる想定です インフラを移行することで、これまで手作業で回していた作業の多くを仕組みとして実行できる状態に寄せられました。たとえば、台数の増減のように人が手順を覚えて都度実行するタイプの作業は、サービス側のスケーリング機能に寄せることで、手動オペレーションの頻度とヒューマンエラーの余地を減らせるようになります。 また、各システムをコンテナとして分離したことで、負荷や障害の影響範囲をサービス単位に閉じ込めやすくなりました。Fargateではタスクごとにリソースの割り当てと制限を分けられるため、少なくとも 同居による道連れは起きにくい構成に寄せられています。 さらに、ログがCloudWatch Logsに集約されるようになったので、サーバーごとのローカルファイルを探しに行く必要が減り、検索や突合がしやすくなりました。加えて、ECSのメトリクスはDatadogに送っているため、監視もよりやりやすくなりました。

まとめ

今回の移行で印象的だったのは、実装そのものよりも 現状把握と動作確認が一番重いという点でした。C#未経験の私でも、生成AIの補助を借りて実装自体はスムーズに終えられました。しかし、そもそも明文化されてないことは、まず人間が情報収集する必要がありますし、情報を集めた後の意思決定も人間がするので、まだまだやることはたくさんありました。 今後も、サービスの信頼性を高める改善を継続していきます。

株式会社フォトラクションでは一緒に働く仲間を募集しています

www.wantedly.com