はじめに
はじめまして。株式会社マネーフォワードの小笠原です。2018年に新卒として入社した後、2020年11月まで全社のインフラの改善プロジェクトのテクニカルリードを担い、現在個人向け事業を展開するホームカンパニーのカンパニーCTOを務めています。
マネーフォワードは2012年に創業し、今年で10年目を迎える会社です。個人向けお金の見える化サービス「マネーフォワード ME」や事業者向けバックオフィスSaaS「マネーフォワード クラウド」を始めとする、30以上の幅広いサービスを展開しています。年々提供サービスは増え続け、それに伴い組織も急激に拡大しています。
本記事ではマネーフォワードが急成長するにつれ、次々と多数のサービスを展開していくようになった中で生じたインフラの課題と、その課題をどのように解決しようとしているかについて紹介します。
マネーフォワードの事業拡大に伴うインフラの課題
マネーフォワードは創業当初より、物理サーバーを調達するオンプレミス環境を利用してサービスを提供してきました。物理サーバーのセットアップから構成管理、デプロイパイプライン、監視などは全て単一のインフラチームが全てのサービスに対して行います。図1のように、サービス開発チームはアプリケーションコードを管理し、インフラチームは実行環境を全て管理する責務を分担する形です。そのため、新規サービスのリリースはもちろんのこと、日々の運用で必要なRubyのバージョンアップやNginxの設定変更、ユーザー数増に伴うリソース追加などは全て中央のインフラチームが動く必要がありました。
また、創業当初に、サービス間のID共有やデータ共有は単一のMySQLサーバーを複数のサービスで共有して実現する方式をとりました。これにより、我々が展開しているサービスの多くはアプリケーション的な結合度も高い上に、ネットワークなどのインフラ的な結合度も極めて高いものになっています。現在でこそマネーフォワードIDというIdPや、アカウントアグリゲーションデータを取得するためのマイクロサービスなどを作成し共有DBを無くす活動をしていますが、まだ道のりは長いのが現状です。
このような環境で、全てのアプリケーションの実行環境および共有DBを含めた全てのインフラをインフラが得意なメンバーが管理し、アプリケーションコードをサーバーサイドが得意なメンバーが管理していく形になっていきました。創業から数年は得意な人が得意な領域を責任持って行う役割分担により、迅速に数多くのサービスをリリースすることができました。しかしながら、先述の通りマネーフォワードは急速に事業を拡大しています。事業拡大に伴いサービス数は急速に増加し、インフラチームの負荷も増大していきました。
すると、いつの間にか図2のようにインフラチームは多数のサービスの運用を一手に引き受ける状態となってしまい、運用の中で生じる緊急な課題に対応しつつ、新規サービスの構築作業をなんとか行うというギリギリの状態に陥ってしまったのです。
同時に、サービスチームはインフラ周りの変更を行いたくてもインフラチームが多忙かつ、インフラチームにしか権限が無い部分が多く、変更を加えたくても待つしか無いといった状況が続いていました。また、権限をサービスチームに渡していこうにも、オンプレミス環境では単一のインフラチームが全てを見る形での権限設計が行われていたため、簡単にサービスチームに対して権限を渡していくことも困難でした。
つまり、インフラチームしか触ることができない部分が多く、適切に権限を渡すことができないことによってインフラチームがサービス開発のライフサイクルの中に深く入り込み、その上インフラチームが忙しすぎることによりボトルネックになる。さらに、多忙ゆえにインフラの改善もなかなか行うことができないという悪循環に陥っていました。
今後の事業展開や組織の拡大を考えると、中央の単一インフラチームが全てを見る状態はスケールせず、全社の開発組織としてのアジリティが低下していくのは明らかでした。
組織と事業が拡大してもスケールするインフラを目指す
先述の課題から、開発組織が拡大してもアジリティが低下しないインフラを目指す必要がありました。これを実現するには、中央のインフラチーム規模自体がサービスチームの規模に応じてスケールするようにするか、インフラチームがサービス開発のサイクルに入らずに済む仕組みを作り、サービスチームが増えればインフラタスクを担うエンジニアも増えるというどちらかの選択肢を取る必要があります。
前者に関しては、そもそもサービスチームに比べてインフラチームのメンバーは増えにくい現状があり、インフラチームの数で戦うのは現実的ではありませんでした。そのため、後者のインフラチームの規模は大きくせずともサービスチーム内でインフラのタスクが完結し、サービスチームの数に応じてスケールする形を目指すことにしました。
サービスチーム内でインフラを含めた開発ライフサイクルを完結させるためには、サービスチームがインフラを変更できるように、インフラに関する権限を移譲していくことが必要になります。具体的にどのような権限を移譲していけば、開発ライフサイクルをチーム内で完結させることができるのでしょうか。我々はまず以下の3つのタスクを実施できる権限を移譲し、図1の責務範囲を図3のように変えることから始めようとしました。
1.アプリケーションの実行環境の管理
- ランタイムのバージョンアップや、必要なライブラリのインストールがチーム内でできるようにする
2.サーバーリソースの管理
- 新規プロセスの追加や、スケールアウト/インなどがチーム内で実施できるようにする
3.ミドルウェアの管理
- DBやKVSなどの作成や設定変更、スケールアップ/ダウンなどがチーム内で実施できるようにする
これらの権限を移譲していくために、Docker、Kubernetes、そしてAWSを利用しています。アプリケーションの実行環境を変更するためにはDockerfileを変更すればよく、サーバーリソースおよびミドルウェアの変更にはKubernetesのマニフェストやTerraformのコードを変更することで、インフラチームに依頼せずともインフラに変更を加えることができるようになりました。AWSには豊富なマネージドサービスがあり、特にMySQLなどの高可用構成を簡単に組むことができるのはインフラを移譲していく中で大きな魅力でした。
これらを利用することで、インフラチームとサービスチームの責務の境界を変更することはできそうですが、サービスチーム間の独立性をどのようにして保つかについても考えなくてはなりません。インフラに変更を加える際に、ある変更が他のサービスに影響を与えうるものになってしまうと、変更に対する調整コストや心理的ハードルが跳ね上がってしまいます。そのため、徐々に権限を移譲していく中で、サービス間の独立性をどのようにして保つかについても考えなければなりませんでした。