はじめに
LegalOn Technologiesのプロダクト開発基盤チームでPlatform Engineerをしている Saso (@rendaman0215) です。
弊社では、全社的にProtocol Bufferを使って製品のAPIスキーマの管理をしており、BSR(Buf Schema Registry)を使ってProtocol Buffersを管理していましたが、自社製の管理基盤に移行しました。
本記事では、なぜ移行したのかの背景からどう移行したかのプロセス、その過程で苦労したことや気づきについてご紹介します。
なぜ移行したか
もともとBSRを使っていた理由
BSR(Buf Schema Registry)を採用した主な理由は以下の3点でした。
- 管理コストの低減:protoをアップロードした際にプラグインやパッケージングを一手に引き受けてくれて、構築・メンテナンスコストが小さくなります。
- Protocol Buffersの一元管理:複数のプロダクト、複数のチームで使用するprotoファイルを一箇所で管理でき、バージョン管理や整合性の担保が容易になります。
- コード自動生成の優れた開発体験:BSRは豊富なプラグインを提供しており、Go、TypeScript、Java、Python、Rubyなど様々な言語に対応したコード生成が簡単に導入できます。プラグインの品質も高く、設定も比較的シンプルで、開発者はprotoファイルをpushするだけで各言語のコードが自動生成される快適な体験を得られました。
依存関係の整理
BSR採用当初は複数プロダクトを強く想定しておらず、特定プロダクトのリポジトリ内でprotoを管理していました。その結果、複数プロダクトから利用される共通領域も同居し、依存関係がいびつになってしまっていました。自社基盤への移行では、マルチプロダクトで共通利用されるスキーマを中立な場所で集中管理することで、プロダクト間の依存が歪まない状態を作ることも狙いのひとつでした。
コスト
BSRの課金体系はProtocol Buffers内のType数に連動します。弊社はマルチプロダクト戦略で複数のプロダクトを開発しており、プロダクトが増えるたびにType数が増え、コストが膨らんでいました。
プラグイン管理の簡素化
BSRは膨大な種類のプラグインを提供しており、様々な言語・フレームワークに対応できる柔軟性があります。しかし裏を返せば、どのプラグインのどのバージョンを使うべきか、組み合わせが爆発するということでもあります。
自社基盤では選択肢を意図的に絞り、カオスになりがちなプラグイン管理をコントロール可能な範囲に収めることを目指しました。
何を作ったか
全プロダクトのprotoファイルを一箇所で管理し、統一的な方法でコード生成を行う機能を持ったリポジトリを作りました。
主に、Buf社が提供する proto 管理エコシステムのツールである Buf CLI を中心に開発を行っており、BSR 利用時代からローカル開発における生成コードの確認や CI での lint など、重要な役割を担うツールとして活用してきました。
今回作ったリポジトリでは、これらの仕組みを GitHub Actions 上で組み合わせ、全プロダクト共通の proto 管理・コード生成フローとして再構成しています。
全体構成
開発者がprotoファイルをpushすると、GitHub ActionsがBuf CLIの生成コマンド( buf generate )を実行し、各言語のパッケージをGitHub Packagesに配布します。各プロダクトはGitHub App経由でこれらのパッケージを参照します。
また、BSR採用時にはBSR本体だけでなく、ローカル開発とCIの要となる buf CLI もセットで採用しており、開発者体験の中核を担っていました。
コード生成にはBSRのリモートプラグインを採用しました。protocプラグインを自前で管理するのは運用負荷が高いためです。リモートプラグインであればバージョン指定だけで利用でき、BSRの課金対象はType数なので追加コストもかかりません。
主な機能
| 機能 | 内容 |
|---|---|
| PR時の検証 | lint、format、Breaking Change検知 |
| Preview版配布 | PRごとにユニークなバージョンでパッケージを配布し、マージ前に動作確認可能 |
| profile | 言語ごとのプラグイン設定セットをバージョン管理し、プロダクトごとに柔軟に適用 |
どう移行したか
移行戦略
いきなり既存の大規模プロダクトを移行するのはリスクが高いため、段階的に進めました。
1. 新規プロダクトでPoC
ちょうど新たに開発が始まったプロダクトがあったので、そこで新基盤を使い始めて実績を作りました。
2. 大規模のプロダクトを含めた全体への展開
約60マイクロサービスを持つ最大のプロダクト「LegalOn」に対しては、コミュニケーションコストを少しでも減らすために、一度基盤チーム自ら全サービス分の移行を実施し「参考PR」として提供しました。AI時代だからこそできる、大胆なアプローチだったと思います。
アプリケーション側の修正を最小限に
移行のハードルを下げるため、パッケージの構造はBSRを踏襲しました。各プロダクトではimport文の変更程度で済むようにしています。
各チームへのサポート体制
| サポート | 内容 |
|---|---|
| ドキュメント | Notionに移行ガイドを作成(概要、手順、FAQ) |
| 参考PR | 各プロダクトに対してCIが通る状態まで作成 |
| 質問対応 | 専用Slackチャンネル + プラットフォームチームへの意見箱 |
参考PRは、サービスごとに置き換えが必要な部分をすべて含め、CIが通る状態まで持っていきました。各チームはこのPRをベースに、必要に応じて調整を加えるだけで移行できます。
移行期間
移行期間は3ヶ月を設けました。参考PRとドキュメントを整備したこともあり、すべてのチームが期限内に移行を完了することができました。
大変だったこと
5言語の知識が求められる
対応する言語はGo、TypeScript、Java、Python、Rubyの5つ。それぞれパッケージング方法も依存解決の仕組みも異なります。
特にJavaのGradle周りの設定は複雑で、社内の有識者にかなりの時間を使って手伝ってもらいました。Go Modulesの replace ディレクティブ、npmの peerDependencies など、各言語固有の知識が求められる場面が多くありました。
一人ですべてを熟知することは難しく、各言語に詳しいメンバーに相談しながら進めることになりました。
buf generateの2分タイムアウト
BSRのリモートプラグインを使った buf generate には、サーバーサイド実行時に2分のタイムアウト制限があります。
弊社の最大プロダクト「LegalOn」は約60サービスで構成されており、Javaのような重いコード生成ではタイムアウトが発生しました。以下の対応で解決しています。
- プラグインオプションの調整による生成コードの軽量化
- サービス単位でのchunk分割実行
CIのパフォーマンス
BSRのコード生成は驚異的に速く、pushした瞬間にコードができているような体験でした。自社基盤では同等の速度は難しいため、以下の最適化を行いました。
- GitHub Actionsのmatrixによる並列実行
- Preview環境は必要な言語のみ生成
- Preview CI自体をオフにできるオプション
移行してどうなったか
成果
| 項目 | 結果 |
|---|---|
| コスト削減 | 80〜90%削減(BSR利用料 vs GitHub Actions利用料) |
| 開発期間 | 4〜5ヶ月(PoCを含む) |
| 移行期間 | 2〜3ヶ月 |
| 移行完了率 | 全チームが期限内に完了 |
今後の課題:Inner Loop開発への対応
今回作成したリポジトリのようなprotocol buffersの中央集権リポジトリにはプラグインバージョンの強制やコード生成プロセスの統一というメリットがある一方で、proto がプロダクトとは別リポジトリに分離されることで、プロダクト開発上の課題も見えてきました。
AIコーディングツールとの相性
各アプリケーションのソースコードのリポジトリとは別にprotocol buffersの中央集権リポジトリにprotoファイルがあると、AIがコンテキストを正しく理解してくれないことがあります。
現在、解決策案としてadd-dirコマンドを用いて各プロダクトのリポジトリから、このproto管理リポジトリを参照させたり、skillsを用いて適宜コンテキストを読み込ませることで対応しています。
開発サイクルのオーバーヘッド
フロントエンド〜バックエンドを一気通貫で開発する際、proto変更→パッケージ生成→依存更新のサイクルがオーバーヘッドになります。
現在、以下のアプローチを検討しています。
- 共有スキーマ(他プロダクトから参照される)→ 引き続き集中管理
- ローカルスキーマ(そのプロダクト内でしか使わない)→ 各プロダクトリポジトリで管理
まとめ
BSRから自社製のProtocol Buffers管理基盤に移行し、コストを80〜90%削減することができました。
buf generateのリモートプラグインを活用することで、プラグイン管理の負荷を抑えつつ内製化を実現しています。5言語対応やタイムアウト問題など様々な課題がありましたが、社内の有識者の協力を得ながら乗り越えることができました。
同様の課題を抱えている方の参考になれば幸いです。
謝辞
問題解決する際にアドバイスいただいた杉田さん、新しい試みを快く後押ししてくださった吉岡さん、レビューしてくださった齋藤さんはじめプロダクト開発基盤チームのメンバーの方々に深く感謝します! この記事と資料はこれらの方々の協力なしではありえませんでした。ありがとうございました。
仲間募集!
LegalOn Technologiesでは、一緒に働く仲間を募集しています! 提供しているプロダクトが増え、会社も開発組織もどんどんと拡大する中で組織の課題解決をするのはとてもやりがいがある仕事ですし、キャリアアップに繋がる経験が積める職場だと思います。Platform Engineer の経験があって次の活躍の場を探されている方だけでなく、これから Platform Engineer としてのキャリアを目指されている方も大歓迎です。 ぜひ一度お話を聞きに来ていただけると幸いです。ご興味がある方は以下のサイトからぜひご応募ください!