メルカリは開発組織を拡大するためにマイクロサービスアーキテクチャを採用した(前編)。Mercari Tech Conf 2018
メルカリは現在300人程度の開発者を1000人規模にする目標を掲げており、それに合わせてパフォーマンスを発揮させるためにマイクロサービスアーキテクチャを1年前から採用し始めました。
同社がこの1年、マイクロサービスアーキテクチャにどう取り組み、実現のためになにをしてきたのか。技術面と組織面 の双方に関する興味深い取り組みが、10月4日に都内で行われた同社主催の技術カンファレンス「Mercari Tech Conf 2018」のセッション「Microservices Platform at Mercari」で紹介されました。
この記事はその内容をダイジェストでまとめたものです(本記事は前編と後編に分かれています)。
Microservices Platform at Mercari
マイクロサービスプラットフォームチームでTech Leadを務めています、中島です。
この1年でメルカリに起きた大きな変化のひとつは、モノリシックなアーキテクチャからマイクロサービスアーキテクチャへの移行です。
このセッションではメルカリのインフラや組織のデザインをどのように行っているかを紹介していきたいと思います。
メルカリがマイクロサービスに舵を切った大きな理由は組織をどんどん拡大していくためです。現時点でのメルカリのエンジニアは300人程度ですが、われわれはその3倍程度の1000人規模の組織を目指しています。
そしていままで以上のスピードとパフォーマンスで開発をし、お客様によりよいサービスを提供することを目指しています。
これは今年の3月に発売された「Accelerate」という本です。
2013年から2017年のあいだ、スタートアップを含む2000以上の組織に対して、いかに組織のパフォーマンスを加速するかという聞き取り調査を行い、その調査結果をまとめたものです。
その調査結果のひとつにこのグラフがあります。
これは組織のエンジニアの人数とそのパフォーマンスを、組織の違いによって示したものです。
横軸がエンジニアの人数、縦軸はエンジニアあたりの1日のデプロイ数を指標としたパフォーマンスです。
これによると、パフォーマンスの低い組織はエンジニアが増えるとデプロイ数も減少しています。普通のパフォーマンスの組織はエンジニアが増えてもデプロイ数に変化はありません。
一方でパフォーマンスの高い組織はエンジニアが増えるほど指数関数的にデプロイ数が増えていきます。メルカリが目指しているのはここです。
これは単純にアーキテクチャをモノリシックからマイクロサービスへ移行するだけでは実現できません。アーキテクチャに合わせて、そのアーキテクチャにあわせてもっともパフォーマンスが発揮できるチーム構成や組織のデザインをすることが大切です。
そこで、私たちがどのようにチーム構成や組織をデザインしているかを、まずお話します。
専門性でチームを分けるとサイロ化が進む
ソフトウェアのライフサイクルは大きく4つに分かれています。開発し、テストし、デプロイし、運用する、これを繰り返します。
モノリシックなアーキテクチャでよく見られるのは、専門性でチームを分けるやり方です。
開発を行うバックエンドチーム、テストを行うQAチーム、そしてデプロイや運用を行うSREチームもしくはオペレーションチームに分けられます。
この組織のことを考えずにアーキテクチャのみをマイクロサービスに変えると、マイクロサービスの利点を失ってしまいます。
例えば、バックエンドチームをそのままにすると、マイクロサービスのサービスごとのオーナーが不明瞭になってしまいいます。その結果、誰が責任者か分からない、誰にもさわれないサービスができてしまいます。
また、QAチームやSREチームをそのままにすると、サービスが増えれば増えるほど、これらのチームの作業が追いつかず、ボトルネックになってしまいかねません。するとマイクロサービスの開発のスピードを失ってしまいます。
専門性でチームを分けることを続けていると、チーム間のコミュニケーションや知識の共有が薄くなってなサイロ化が進み、サイロ化はチーム間のコラボレーションを妨げてしまって、効率的に開発効率を改善することができなくなってしまいます。
サービスごとにチームを構成し、開発から運用までをそこで行う
これらの課題を解決する、マイクロサービスアーキテクチャにおける理想の組織構造は、サービスAのためのチーム、サービスBのためのチームのように、サービスごとにチームを構成して、チーム内で開発、テストからデプロイ、オペレーションまでを行うことです。こうすると、先ほど挙げたようなボトルネックは存在しません。
各チームは自律的に独立して意思決定を行って、効率的な開発を自分たちで回すことができるようになります。
またチーム内でソフトウェアライフサイクルのすべてを担うことで、チーム内で各領域、開発やデプロイやオペレーションなどの知識共有もできます。
よって、よりよいサービスの開発や問題の解決をチーム内でできることになります。
これが、われわれの考える、マイクロサービスに対応した理想的な組織構造です。
開発者が開発だけでなくさまざななスペシャリストにならなくては
一方でこの組織は、新しい課題も生み出しています。
これまでは開発のみに集中していればよかった開発者が、自分たちでデプロイや運用までやらなくてはならなくなった。
つまりマイクロサービスアーキテクチャにおける開発者の役割というのは、開発だけでなくソフトウェアのテストのスペシャリストとして、運用のスペシャリストとしても行動する必要があります。
これをいきなりやれといわれて、すぐできる人はいないと思いまし、これはなかなか難しい要求だと思います。
そこで、これを助けるために設立されたのが「Microservices Platform Team」(マイクロサービスプラットフォームチーム)です。
マイクロサービスプラットフォームチームは、開発者が自分たちでマイクロサービスの開発からデプロイ、運用を行うことを助けます。
mercari.jpがマイクロサービスへの移行を始めたのは、ちょうど1年前でした。このグラフは、マイクロサービスの数を示していて、赤い線がすでに本番で動いているサービス、青い線が開発中のサービスを示しています。
1年前はひとつしかありませんでしたが、今日本番で動いているのは19、開発中は73あります。
ここに至るまでにマイクロサービスプラットフォームチームがなにをしてきたかについて、紹介していきます。
APIゲートウェイアーキテクチャへの移行
われわれが達成してきたことを一言で言うと、なにもないところにベースとなる道を整えた、ということです。
具体的に言うと、基礎となるマイクロサービスのためのアーキテクチャの構築。そして基本的なDevOps文化の醸成といったことです。
アーキテクチャとして整えたことは大きく次の4つです。
- APIゲートウェイアーキテクチャへの移行
- サービス間コミュニケーションプロトコルの統一化。
- 新規のマイクロサービスを作るためのテンプレートプロジェクトの提供
- そして開発者のインフラへのアクセス制限の管理
まずはAPIゲートウェイアーキテクチャへの移行について紹介します。
これが1年前のメルカリのメインのアーキテクチャです。モノリスのAPIとそれが使うデータベースがあり、すべての開発がこの中で行われていました。
これに対してまず、この全体に自分たちで内製したAPIゲートウェイを配置しました。
これによってメルカリへのすべてのリクエストがこのAPIゲートウェイ経由になりました。新しいサービスを作るときには、そのサービスをAPIゲートウェイ配下に作ることができるようになります。
これによってモノリスのコードとはある程度独立して新規のマイクロサービスの開発を行えるようになります。
また既存の機能をマイクロサービス化してモノリスと切り離していくときも、この新しいAPIゲートウェイ配下に配置し、APIゲートウェイレベルでリクエストの振り替えを行うことで、段階的にマイクロサービスへ移行できるようになりました。
このAPIゲートウェイはGoogle Cloud Platform上にデプロイしました。こうすることでクラウドへの移行も開始しています。
これによって、例えばサービスAがなにかデータベースを使いたいときには、クラウドのマネージドサービスのデータベースを使えるようになりました。
また、新しいサービスはコンテナとしてKubernetes上にデプロイしています。Kubernetesを使うことで、コンテナがしんでしまったときに自動的に再起動してくれるセルフヒーリングの機能や、リクエストがたくさんきたときにコンテナを自動的に増やしてくれるオートスケール機能などを使うことができ、オペレーションのコストを劇的に減らすことができるようになりました。
gRPCをコミュニケーションプロトコルに採用
次にサービス間のコミュニケーションプロトコルの統一です。
APIゲートウェイとサービスのあいだ、サービスとサービスのあいだのコミュニケーションプロトコルとして、われわれは「gRPC」を採用しています。
GRPCではProtocol Buffers(プロトコルバッファ)というIDL(インターフェイス定義言語)を使って、サービスのインターフェイスを定義します。それをもとにあらゆる言語のライブラリを生成できます。
これによって初期の実装コストを減らしたり、インターフェイスの定義の効率化を図れます。
各マイクロサービスのプロトコルバッファの定義などを簡単にできるように、私たちは「platform-proto」というリポジトリを作成しました。各サービスの開発チームは、自分たちのサービスのプロトコルバッファの定義を書いて、このリポジトリにプルリクエストできます。
プルリクエストがマージされると、Go、Python、Java、Node.jsといったメルカリでよく使われている言語のクライアントやサーバをCIツールで自動生成できるようになります。
この仕組みによってマイクロサービスを提供する側も、使う側も、すぐに実装をはじめられます。
また、プロトコルバッファの定義をすべて一箇所にまとめているので、これがドキュメント的な役割も果たしています。
例えば、サービスAを使いたいときにはこのリポジトリでプロトコルバッファの定義を見れば、どうやってサービスAを呼び出せばいいかが簡単に分かるからです。
マイクロサービスのためのテンプレートを提供
次に私たちが整えたのは、新規にマイクロサービスを作るためのテンプレートプロジェクトの提供です。
これまでメルカリのメインの言語はPHPでした。マイクロサービスではメインの言語としてGo言語を採用しています。
しかしすべてのエンジニアがGo言語を得意としているわけではありません。
すぐにマイクロサービスの開発をはじめられるように用意したのが「mercar-echo-jp」というテンプレートです。
これはアプリケーションとしては非常にシンプルで、受け付けたリクエストをそのまま返すだけなのGRPCアプリケーションですが、このなかに標準のGoのパッケージ構成だったり、本番運用で必要なモニタリング、エラーレポート、ヘルスチェックなども実装しています。
またコンテナ化のための標準的なDockerfileや最低限必要なCIの設定ファイルなども含んでいます。
マイクロサービスの開発者はこのリポジトリをコピーするだけで、すぐに開発をはじめられます。
Kubernetesを名前空間でチームごとに切り分け
最後は、開発者のインフラへのアクセス制御の整備です。
以前は、インフラに触れるのはSREチームだけでした。ですのでインフラへのアクセス制御はすごくシンプルで、SREだけが触れる、というものでした。
しかしマイクロサービスでは、各チームが自分たちのサービスを自分たちで管理運用するようになります。
つまり各チームが自分たちで管理しているサービスのインフラも自由に触れるようになる必要があります。そのためのアクセス権限の設計を行いました。
まず、いちばんの基礎となるKubernetesは、マイクロサービスプラットフォームチームがクラスタアドミンとして安定運用に責任を持ちます。ですのでマイクロサービスの開発者はKubernetesクラスタそのものへのアクセス権限は持っていません。
例えば、サービスAチームが新しいマイクロサービスをリリースしたい、というとき。
まずサービスA専用のネームスペース(名前空間)をKubernetes上に作ります。これはKubernetesの機能で、仮想的にクラスタを分離する機能です。Kubernetesクラスタの中にサービスA専用の部屋を作るようなものです。
そしてKubernetesのRBAC(Role-based access control)を使って、サービスAの開発チームをそのネームスペースの管理者として登録します。この部屋の鍵を渡すようなものです。
これでサービスAの開発チームは、このネームスペースに自由にアクセスできるようになります。例えば、ここにデプロイしたコンテナになにか問題が起きたときには、コンテナのログを見たり再起動するなどのオペレーションを自分たちで行うことができます。
サービスAの開発チームがGoogle Cloud Platform(GCP)のサービス、例えばCloud Spanner(グローバルに分散したリレーショナルデータベース)などを使いたいときには、サービスA専用のGCPプロジェクトを作って、サービスAチームをその管理者に登録することで、自身のプロジェクトとしてGCPのサービスをそこに登録し、使うことができます。
サービスBの開発チームが新しいサービスを作りたいときも、また同様のことを行います。
≫後編に続きます。後編では開発者がインフラのプロビジョニングや運用まで行う環境を整えるなど、DevOps文化の醸成について紹介します。
Mercari Tech Conf 2018
あわせて読みたい
メルカリは開発組織を拡大するためにマイクロサービスアーキテクチャを採用した(後編)。Mercari Tech Conf 2018
≪前の記事
ビルドパック(Buildpacks)がCloud Native Computing Foundationのプロジェクトに。HerokuやCloud Foundryなどが開発