トイルのないアプリケーション開発体制を整備する
DevOpsを実現するためのアプローチのひとつに、SRE(Site Reliability Engineering)がある。エラーバジェットを加味した効率的なシステム運用という切り口で語られるSREで、一見するとDevOpsとは関係ないように思えるが、実際はDevOpsの考え方を具体化し、運用や実装に落とし込むための方法論であり、開発も深く関わる考え方とスリーシェイクのSREエンジニア、佐藤慧太氏は述べる。
そのSREを実践する上で重要な目標に、Toil(トイル)をなくすという項目がある。トイルは、労苦の意味だ。Googleでは「手作業であること」「繰り返されること」「サービスの成長に比例して増加すること」などと定義している。
アプリケーション開発・運用におけるトイルとは何か。佐藤氏は主なトイルとして以下の3点を挙げる。
複雑な処理の修正
リファクタリングされていない複雑な処理をそのまま放置することにより、開発者の認知的負担が上がり、リリースサイクルが伸びてしまう可能性がある。
環境依存
特定の場所でしか起動しないような形で実装されている場合、動作確認の時間や使えるメンバーに限りがでてしまい、開発速度が低下してしまう。
不安定なE2Eテスト
E2Eテストが不安定な場合、新しいメンバーが機能を修正をする際に、動作保証ができず、修正によるものなのかそもそもの挙動なのかが判断つきにくくなってしまう。
これらのトイルに関して「処理が複雑なものを修正するのはバグ調査コストが高くなり、環境に依存するシステムでは開発のフィードバックサイクルが長くなる恐れがある」と佐藤氏は説明する。
トイルを解決するには、設計や実装を見直すことが近道になる。しかし、特に内製開発を始めたユーザー企業では知識や経験の不足から自力で解決するのは難しい。
そこでスリーシェイクが提供するのは、SREに基づき、技術戦略やサービスの設計、構築、運用までをワンストップで支援するサービス「Sreake」だ。ヒアリングでトイルを洗い出し、優先的に進めるべきタスクを整理。そして、顧客と伴走しながら課題解決に挑み、デモやハンズオン、ペアプログラミングによるスキルトランスファーなどを通じて、自走できるように支援する。ただ現時点の課題解決ではなく、将来的な運用を見据えたトイル排除と開発・運用体制の整備が目標と佐藤氏は言う。
トイルのない開発運用環境を目指すトヨタ自動車事例
実際にどのようなことをするのだろうか。佐藤氏は、トヨタ自動車での事例を取り上げて解説した。
トヨタ自動車ではDX推進の一環で、AIを活用したWebアプリケーションの内製開発に乗り出した。インフラはGoogle Cloudを中心としたハイブリッドクラウド環境で構築し、アジャイル開発やコンテナ技術などモダンなテクノロジーでシステム環境を整えた。しかし、メンバーは当時アプリケーション開発・運用の知識や経験が少なかった。ある程度は形になったものの、このままでは自分たちの作りたいアプリケーションが開発できない上に、トイルも積み重なっていくだろう。こうして今年4月、同社はスリーシェイクの開発支援を受けることになった。
トヨタ自動車のプロダクトマネージャーを中心に、トヨタ自動車の運用担当と開発担当を、スリーシェイクのインフラ構築支援担当とアプリケーション開発支援担当でサポートする体制を構築したのち、現在の課題と改善の方向性を話し合い、大きく次の3つを実施することになった。
- 長期運用を見据えたアーキテクチャの再構成
- 開発速度向上のためのフロントエンド開発ツールの導入
- 運用作業効率化のためのアプリケーションの修正
1つめは、アーキテクチャの再構成だ。以前は、Google Kubernetes EngineのAutopilotモードでアプリケーションPodを管理しており、アプリケーションごとのページからCloud SQLへの接続やFirebaseでの認証認可処理を実行する構成だった。
「画面上の処理が多く、また、各アプリケーションでUI層を実装していたため、UIの共通化がされておらず修正に時間がかかってしまう。ジョブからデータベース接続していることも、マイグレーションを複雑にする要因」。そう述べた佐藤氏は、システムの長期運用が見えている中で、このままの設計で進めた場合、運用開発において、トイルが多くなってしまい、トヨタ自動車が本来やりたいAIプラットフォームの開発の妨げになってしまうと感じた。
そこで佐藤氏たちは、フロント用Podと認証用Podを立てて、アプリケーションPodからはAPI接続で集約。データベースもAPIからのみ参照するように変えて、通信を大幅に整理して将来的にトイルとなる要素を排除したという。これにより長期運用と開発速度向上を見越して、UIを共通化し、各WebフレームワークのUI層を切り離して整理することができた。
その上で、佐藤氏たちはメンバーに対してリファクタリングのオンライン勉強会を実施した。
「1ファイルが3000行もあり、その大半が同じ処理について書かれているものもあった」と振り返る佐藤氏。コピペにより実装を使いまわすことが多く、修正するコストが掛かっていた。また、モジュール化されていないため、他の人が見たときに、どういう処理なのかをコードを読んで理解するのに時間がかかってしまっていたという。しかも「フレームワークのバージョンアップをしても、動作確認作業やテストの修正が複雑になってしまうのが見えている」と続ける。
勉強会は定期的に開催し、リファクタリングの必要性や視点を学ぶ座学に加えて、実際に動いているコードを参照しながら何を修正できるかをハンズオンで学習。実践力の向上に努めた。
フロントエンドツールの整備とアプリケーション改修
2つめは、開発速度向上に向けたツールの導入だ。ここでは、フロントエンドのツールを整備することとした。佐藤氏いわく、JavaScriptの処理が多いのにグローバル空間に配置されており、ファイル間の依存関係も分かりづらく、ライブラリのバージョン管理もされていないので修正コストが大きく、新任のエンジニアの認知負担を上げてしまっている状況だった。だが、フロントエンドの機能は多く、一気に変更するのは危険だ。
佐藤氏たちが考えたのは、開発生産向上に主軸を置いた、フロントエンド機能のモジュール化と依存関係の整理だ。
フロントエンドツールには、JavaScriptのライブラリの依存関係を明確にするためのpnpmと、JavaScriptバージョンの変換とRollup機能による段階的な導入を実現するViteを導入した。その後、実装をモジュール構文に変更し、コード上からライブラリの依存関係が分かるように改修。認知負担を減らし、保守性を高める構成に変えた。「まだフロントエンド関係のスキルが弱いので、TypeScriptまで一気に変換をかけずに、JavaScriptのままで分かりやすく整理した」(佐藤氏)
そして3つめは、アプリケーションの修正だ。ここでは主に、監視アラートでのメトリクス取得やログの抑制を実施した。
「KubernetesのProbeリクエストがアプリケーションのアクセスログに混ざっており、デバッグがしづらく、アプリケーションのメトリクスを取得できなかった。Google CloudのLoggerでフィルタすることも考えたが、デバッグ時はアプリケーションのログを直接参照するので、選択肢から外すことにした」(佐藤氏)
最終的には、アプリケーションのヘルスチェックログを抑制してデバッグしやすく変更し、Prometheus用エンドポイントを作成してメトリクスを取得できるようにしたという。「Prometheusのメトリクスを取得するミドルウェアがDjangoにあるので、それを追加。ログの抑制については、Gunicornを使っていたので、デフォルトのLoggerに対してヘルスチェックを除外するフィルタを追加し、KubernetesのProbeのアクセスがあったときは表示しないように設定した」(佐藤氏)
その他、Gunicornのチューニングや認証認可機能の作成、Kubernetes APIを扱うアプリケーションの実装サポートなど、細かい支援を実施。トヨタ自動車は自走に向けて、一歩ずつ前進を始めた。
特に同社が効果を痛感しているのは、スキルトランスファーの支援だ。
「どう動かそうかではなく、ログをどうやって取ろうか、メモリやCPU、レプリカのバランスをどうするかといった会話ができるまでメンバーのレベルが上がったと評価いただいた」。そう明かす佐藤氏は、今後はメンバーのスキルアップを継続するほか、CI/CDの整備、ユニットテストやE2Eテストの文化の醸成、Monorepoにおけるモジュールの共通化など、より深い開発支援を行う予定と述べる。
SREの導入や開発体制の改善を検討中の人に参考になればと述べる佐藤氏。「トヨタ自動車とスリーシェイクはともに、エンジニアを絶賛募集中。トヨタ自動車については、モダンなアプリケーション構成でSREベースの開発にチャレンジできる。興味があれば、ぜひ問い合わせてほしい」と語り、講演を終えた。