クラウド基盤本部のPlatformチームの昆野です。
私たちPlatformチームでは、サイボウズが提供するクラウドサービス「cybozu.com」が安定稼働するためのプラットフォームの開発/運用に取り組んでいます。
今回の記事では、私たちのチームがプラットフォームの安定稼働に向けて取り組んでいる内容をご紹介します。ただし、私たちの取り組みは多岐にわたっており、すべての取り組みを説明するのは難しいため、今回はこれまでに取り組んできた「リソースの収容効率を改善するためのアーキテクチャ改修」について、重点的にご紹介します。
まず、cybozu.comとはどのようなサービスであり、またその内部構成がどのようになっているのかについて説明します。
私たちが提供している「cybozu.com」について、簡単に説明します。cybozu.comではkintoneやGaroon、Office、Mailwiseといったアプリケーションをサービスとしてお客様に提供しています。
お客様はcybozu.comのサービスを利用するにあたり、cybozu.com Storeを通じて利用申し込みを行います。この時、お客様は自身でサービスへアクセスする際に使用するサブドメイン(「(指定したサブドメイン).cybozu.com」でサービスにアクセスできるようになります)を指定します。
cybozu.com側ではこの申し込みを受理すると、バックエンドのシステムで各サービスのセットアップ(ミドルウェアの初期化など)を行い、サービスを利用可能な状態にします。すべてのサービスのセットアップが完了するとその旨がお客様にメールで通知され、通知を受け取ったお客様は事前に指定したサブドメインを使用してサービスにアクセスできるようになります。
cybozu.comでは複数のアプリケーションをサービスとして提供していることを説明しましたが、各製品のアプリケーションサーバ(AP)単体でサービスを提供することはできません。cybozu.comのクラウド基盤上にはAPの他にデータベース(DB)やElasticsearchなどのミドルウェアコンポーネントが稼働しており、各サービスはAPとこれらのミドルウェアが協働することによって利用できるようになります。
各製品のAPや各種ミドルウェアなど、サービスを構成するコンポーネントはVMやコンテナの形式で稼働しています。私たちは1つ1つのVMまたはコンテナをインスタンスと呼称しています。cybozu.comは大規模なサービスであり、各コンポーネントごとに大量のリソース(CPU、メモリ等)が必要となることから、基盤上には各コンポーネントのインスタンスが多数稼働しています。
そして、cybozu.comではこれらのインフラリソースをお客様が共有するモデルによってマルチテナントSaaSを実現しています。マルチテナントというのは単一のシステムを複数のテナント(=お客様)が使用できることを意味します。また、マルチテナントなサービスは複数のテナントが利用する一方で、各テナントからの視点では自身が使用している環境は独立であるように見える(他のテナントが使用している環境を参照したり、操作することはできない)という特徴があります。
cybozu.comでは複数のテナントが単一のAPやDBのインスタンスを使用するアーキテクチャにすることでインフラリソースを分配しています。また、このようなアーキテクチャにすることで基盤上のリソースを有効活用したり、各コンポーネントのセットアップ時間を短縮することを実現しています。

従来のアーキテクチャでは、サービスの提供に必要なコンポーネント(各製品のAPやDBなど)のインスタンスを特定の構成で一組にまとめたサービスセットというアプリケーションプレーンの単位が定義されています。言い換えると、サービスセットが一組あればcybozu.comの各アプリケーションを動作させることができます。実際にはcybozu.comの稼働に必要なリソースを単一のサービスセットのみで補うことはできないため、私たちは基盤上に多数のサービスセットを構築してサービスをスケールしています。
私たちは個々のサービスセットに対して下記の制約を設けています。
そして、cybozu.comでは各テナントに付与したID(以降、テナントIDと呼びます)にサービスセットをマッピングしており、各テナントはマッピングされたサービスセットのインスタンス(が持つリソース)を使用するアーキテクチャとなっています。そのため、複数のテナントに一つのサービスセットをマッピングすることで、サービスセット内のリソースをテナント間で共有させることができます。

この方式には、各サービスのセットアップにかかる時間を短縮できるというメリットがあります。お客様はcybozu.comの契約後、いずれかの稼働中のサービスセットを使用することになるため、新たにサーバやインスタンスを起動・構築することなくサービスのセットアップが行われます。そのため、お客様がサービスを契約してから実際に利用できるまでの時間を短縮することができます。
サービスセットを導入したアーキテクチャでは、個々のサービスセットの構成を自由に変更できないことによって、特定コンポーネントのリソースを柔軟に調整することが難しくなっています。例として、あるサービスセットではAPインスタンスのリソースは余っているのに、DBインスタンスのリソースだけが不足しているというケースについて考えます。この時、DBのリソースを増強する方法として下記の案などが挙げられますが、いずれも十分な対策にはなり得ません。
こうなると新たなサービスセットを構築してDBインスタンスの数を増やすといった方法でしかDBのリソースを補えません。しかし、サービスセットの構築時にはリソースが余っているAPなどのコンポーネントも一緒に構築することになるため、ピンポイントでDBのリソースのみを増強することはできません。このように、サービスセットを導入したアーキテクチャでは、特定コンポーネントのリソースを増強しようとすると、結果的に他のコンポーネントのリソースも余分に増強されてしまいます。
そして、cybozu.comではこのような特徴によって運用コストが上昇してしまうという課題がありました。従来のアーキテクチャでは上記のケースのように、リソースがひっ迫しそうになると新たにサービスセットを構築してサービスをスケールさせてきました。ここで、cybozu.comはオンプレミスのサービスなので、サービスセットの構築時には物理サーバを購入することになります。この時、全コンポーネント分のリソースを確保できるように、リソースが余っているコンポーネントの分まで余分に物理サーバを購入することになります。
さらに、私たちはこれまでに多数のサービスセットを構築してきました。そのため、かなりの数の物理サーバを余分に購入してきたことになり、運用コストもそれだけ増大してしまいました。もしもサービスセットをまるごと構築せずにDBのリソースを柔軟に調整できるようなアーキテクチャになっていれば、基盤上の物理サーバの数を減らすことができ、運用コストの上昇幅も抑えられたと考えられます。
cybozu.comのクラウド基盤はNecoプロジェクトにより大幅に刷新されることになりました。これに伴い、私たちは従来の課題を解消できるようにアーキテクチャの改修を進め始めました。
私たちは各コンポーネントのリソース調整を柔軟に行えるように、サービスセットの制約が取り除かれた新しいアーキテクチャを設計しました。新しいアーキテクチャの特徴は以下の通りです。
構成を柔軟に変更できる
依存関係を動的に変更できる

このようなアーキテクチャでは、インスタンス数を自由に増減させることで、各コンポーネントのリソースを柔軟に調整できるようになります。
新しいアーキテクチャではインスタンス間の依存関係を管理する仕組みが必要になりました。例えばあるAPがあるテナントのデータが入ったDBにクエリを投げたいケースについて考えます。このときAPはどのDBインスタンスに接続すればよいでしょうか?サービスセットの場合、答えは自明です。サービスセット内にはDBインスタンスは一つしかないためです。しかし新しいアーキテクチャではそうはいかないため、何らかの方法でこのDBを特定できるようにしなければなりません。
そこで、新しいアーキテクチャではサービスセットに代わってテナントIDを用いて依存関係を管理することを考えました。具体的には各コンポーネントのインスタンスやクラスタ(=同じ機能を提供するインスタンスの集合)は同一テナントIDが紐づいたものにのみ依存するようなアーキテクチャにしたいと考えました。そして、これを実現する手段として、サービス間通信(=インスタンス同士が行う通信)の仕組みを導入することを検討し始めました。私たちが検討してきた方式および、それぞれの方式を採用した場合のメリット・デメリットを説明します。
クライアントがゲートウェイにリクエストを送ると、ゲートウェイが適切なサーバにリクエストをプロキシする方式です。
メリット
デメリット
サーバのホスト名とエンドポイントのIPアドレスがマッピングされたDNSレコードが各サーバについて作成されており、クライアントは名前解決によって接続先のIPアドレスを取得できる方式です。
メリット
デメリット
HTTPやgRPCなどのプロトコル経由で、各サーバの接続先の情報を保持しているサービスディスカバリから独自の形式で接続先を取得する方式です。クライアントはサービスディスカバリからサーバ側の接続先を取得することができ、その接続先へリクエストを送ることで通信が行えます。
メリット
デメリット
私たちは「サービスの可用性をなるべく落とさず」「スキームやポートの情報も返せる」方式を導入したいと考えていました。そのため、サービスディスカバリ方式(独自プロトコル)を導入することにしました。
cybozu.comのサービスディスカバリには下記の要件が求められていました。
これを踏まえて、下記のソフトウェアがcybozu.comのサービスディスカバリとして使用できるかを考えました。
KVS(Key-Value Store)はユニークなキーとバリュー(値)のペアでデータを保持するデータストアです。具体的なソフトウェアとしてはRedisやValkeyなどが存在します。KVSではキーを使ってバリューのデータを引き出すことができます。そのため、各データのキーにテナントID・依存先のコンポーネント名・アプリケーション名を含めたデータを、バリューにサーバ側の接続先を登録しておけば、KVSをサービスディスカバリとして使用することができます。
しかし、KVSでは要件として挙げた「独自のロジックを組み込む」ことは難しかったため、cybozu.comのサービスディスカバリとして使用することは難しいと判断しました。
HashiCorp社のConsulなどのソフトウェアでは各サービスの接続先を登録および取得できるAPIが提供されているため、これらのソフトウェアはそのままサービスディスカバリとして使用することができます。しかし、このようなソフトウェアでもKVSと同様に「独自のロジックを組み込む」ことは難しく、cybozu.comのサービスディスカバリとして使用することは難しいと判断しました。
cybozu.comのサービスディスカバリとして使用できるソフトウェアを見つけられなかったため、私たちはサービスディスカバリに使えるサービスを自分たちで開発しました。
私たちが開発したサービスではテナントID・依存先のコンポーネント名・アプリケーション名などの情報を入力パラメータとして与えると、インスタンスやクラスタの接続先を取得できるAPIを提供しています。そして、各クライアントはこのAPI経由で取得したサーバ側の接続先を使用してサービス間通信を行うことができます。
このサービスを使って行われるサービス間通信の具体例を示します。ここではテナントAがkintoneにアクセスしたときに、APがDBに接続するケースについて考えます。このケースではAPインスタンスはサービスディスカバリサービスのAPIを呼び出し、自身が依存するDBの接続先を取得します。APIの入力パラメータは下記のように設定します。

APはこうして取得したDBの接続先の情報を使用して、DBへの接続を実現します。
また、上記にてAPがDBに接続するケースについて紹介しましたが、APが他のミドルウェア(Elasticsearchなど)を使用する際や、ロードバランサがAPにリクエストをプロキシする際にも同様の接続先の解決が行われます。つまり、このサービスは実際の運用環境において、数多くのインスタンスから高頻度に使用される、コアなサービスとなっています。
このサービスではバックエンドにMySQLを使用してDBにデータを永続化しています。具体的には、サービスのAPIが呼び出されると、バックエンドではMySQLを使って各インスタンス/クラスタの接続先データをDBに読み書きします。私たちはcybozu.comで長らくMySQLを運用してきたため、今後も安定して運用できそうだと考えてこのようなアーキテクチャを採用しています。実際にこのサービスは本番環境で数年間稼働していますが、以下のような工夫により継続的に安定したパフォーマンスを出せています。
今回はcybozu.comにおけるマルチテナントの考え方、および内製サービスディスカバリサービスの導入によるアーキテクチャの改修について紹介しました。これによりcybozu.comのクラウド基盤では柔軟なリソース調整が行えるようになり、運用コストを抑えられるようになりました。今回の記事がマルチテナントアーキテクチャに対する考え方の一助となれば幸いです。
また、これはクラウド基盤の成長に向けて大きな一歩となりましたが、新しいアーキテクチャにも課題はいくつか存在します(例えば、サービスディスカバリサービスは多数のインスタンスからリクエストが大量に来るため負荷が上昇しやすく、負荷対策が必要であることなど)。そのため、私たちは今後も継続的なプラットフォームの改善に向けて様々な取り組みを行うつもりですが、その際に得られた知見なども皆様に共有できれば幸いです。
長文となりましたが、ここまで読んでくださりありがとうございました!
*1:SRVレコードではポートの情報も返すことができるが、クライアントの実装変更が必要となる
【協賛レポート】Waffle Collegeで女子…引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。