マイクロサービスで管理画面が乱立する問題と対策

qsona
FiNC Tech Blog
Published in
13 min readSep 6, 2019

こんにちは、qsona (twitter) です。

マイクロサービスアーキテクチャを指向するとき、(主に社内向け)管理画面をそのままサービスごとに作っていくと、マイクロサービスの数だけ管理画面が乱立するという課題があります。FiNC においては、それにより実際に以下のような問題が発生しました。

  • ユーザの追加/削除や権限管理がとても大変
  • ユーザ(CS対応者)がどこの管理画面を使えばわかりにくい

本記事では、 FiNC においてこれらの問題に対してどう対処してきたか、歴史とともに紹介します。

tl;dr

  • 各マイクロサービスで管理画面を作ること自体はよい。統一管理画面は開発のコストがかかりワークしなかった
  • 認証を中央管理にする
  • 権限管理は各サービス固有のドメイン知識だが、中央で一覧/変更できる状態になっていると便利
  • マイクロサービスの横断的関心事への対処は、「標準」を意識する

黎明期から、問題が起こるまで

FiNCのバックエンドは、(2019/9 現在) 約40個の Ruby on Rails で書かれたマイクロサービスから成っており、APIを通して相互に連携しています。

私が入社した2016年にはすでにFiNCはマイクロサービスを指向しはじめていたものの、実際にはまだ多くの機能がメインの1サービス(巨大なモノリス)に集中していました。このとき、管理画面もそのモノリスに存在していました。

その後、新しいマイクロサービスが多く立ち上がっていくとき、管理画面をどうするかという問題が生まれました。

  • 画面は既存のモノリスに相乗りし、マイクロサービスのAPIを利用する
  • (採用) マイクロサービスに新しく管理画面を作る

前者は、開発速度の面で2つ問題があります。1つは、大抵管理画面向けのAPIはユーザ向けのAPIとは別にせざるを得なくなり、わざわざAPIを作成する手間がかかることです。もう1つは、モノリスに追加開発しなければならないことです。モノリスは非常に大規模で起動やテストに時間がかかるため、できるかぎり新規の実装を入れたくないという問題がありました。

したがって、多くの開発者は自分の開発するマイクロサービスにそのまま新しく管理画面を作る選択をしていました。

しかし、これにより新たな問題が起こります。

最も重大な問題は、ユーザの管理でした。モノリスの管理画面はまだ利用者数が少なかったので、なんとかなっていました。しかし、マイクロサービス数が増え(典型的には plataformatec/devise というライブラリを利用し独自で認証を実装している)、かつ管理画面の利用ユーザ(基本的に社員)が増えるにしたがって、管理コストが増大します。しっかり管理していかないと、退職者が管理画面をしばらく使えてしまう状況が起こりやすくなります。

また副次的問題として、管理画面がURLドメインではっきり分離されたものの相互にリンクされておらず、利用者が全部ブックマークせざるを得なかったり、どの情報がどの管理画面から見れる/操作できるのか分かりにくいという問題も起きます。

管理画面大統一構想と失敗

サービス数が10を超えてきていよいよ問題が顕在化してきた頃、ビジネスサイドからこの問題に切り込もうとする猛者が現れました。新しい管理画面を一つ作り、そこに機能も認証も権限管理もすべて集中させようとしたのです。

チャレンジは良かったと思うのですが、結論から言うとこの試みは失敗しました。理由は、デメリットが多すぎてプロダクト開発の現場にうまく受け入れられなかったことだと思います。

上でも述べましたが、我々がマイクロサービスアーキテクチャを採用している大きな理由の一つは、開発速度の向上です。それに対し、統一管理画面サービスを作ると、たいていは各マイクロサービスに管理画面のための API を新しく作るコストが発生してしまいます(API は呼び出し元を意識せずに作るのが理想ですが、一般ユーザ向けと管理画面向けでは用途が違いすぎて、同じ API を使い回すのは非常に困難です)。また、管理画面は Rails が最も得意とする分野だと思いますが、そのメリットも享受できなくなります。さらに、統合レイヤーが存在することで、マイクロサービスの依存元が増え、自律性を奪ってしまうことに繋がります。

そのような失敗もあり、開発の現場に負担をかけない形で、むしろ現場が楽になるような方向性で少しずつ問題を解決できないか、と考えました。

フェーズ1: 認証と認可を支援するライブラリ finc_admin_sso の開発と導入

最初のステップ: Active Directory への SSO

FiNCの社員アカウントは Azure Active Directory (Azure AD) で管理されています。この AD と各サービスを連携し Single Sign-On (SSO) を実現するのが良いのではないかと思いました。実際にCS対応のチームや情報システム部にヒアリングし、管理画面を利用するユーザは全員 Azure AD のアカウントを持っている状態であることがわかりました。

手始めに、新しいサービスにて AD への SSO を実装してみました。

ADとSSOをするには SAML というプロトコルを利用します。ライブラリは onelogin/ruby-saml を利用しました。また、Rails アプリ向けのサンプル onelogin/ruby-saml-example を参考にしました。

実はなかなかうまく動かず、かなり苦戦しました。その問題の一つが、 SAML に関連する用語の定義の曖昧さです。読むドキュメントによって同じ意味なのに違う言葉で説明されていることが多く、それに苦戦しました。また、SAML のプロトコル自体がやや複雑で、デバッグのしにくさも時間をかける一因になりました。

社内向けSSOライブラリの作成

SAML を正しく理解して ruby-saml を利用してSSOを実装するのはなかなか骨の折れる作業でした。そこで、Rails アプリに管理画面のSSOを実装するときにすぐに使える社内向けライブラリ finc_admin_sso を作成しました。これは ruby-saml のラッパーです。

SAML プロトコルを実装するにはいくつかのHTTPエンドポイントを実装する必要があります。(これは ruby-saml-example に例があります。)今回はライブラリをインストールするだけでエンドポイントが生えるようにしたいため、 Rails Engine (mountable) として作成しました。(参考: Rails エンジン入門 — Rails ガイド )

ここで一点注意があります。一般的に、マイクロサービスの横断的関心事を特定言語のライブラリとして実装するのは、マイクロサービスの技術異質性を失う危険性があります。今回はあくまで SAML という標準のプロトコルを利用しており、その上で利便性をさらに上げるためにライブラリを作成しました。そのため、仮にRuby 以外の言語で実装されたマイクロサービスにSSOを導入するときも、SAML を正しく実装したライブラリがその言語に存在していれば、問題なく導入できます。(Rails であれば上記の社内ライブラリを導入するだけ良いので、それよりは大変ですが。)

このように、マイクロサービスにおいて横断的な関心事に対処するときは、常に標準の規格を意識することが大切です。そして、社内向けのライブラリを作るときは、その標準の規格に乗った形で実装するのがポイントです。

認可 (権限管理) の設計

上までで、Azure AD を利用した Single Sign-On という形で認証が解決しました。これで、ユーザの作成/削除が面倒という問題、特に退職者問題は解決したことになります。Azure AD は社内の情報システム部が管理してくれているので、退職すればアカウント削除が必ず行われ、管理画面にもログインできなくなります。

次に解決したいのが、認可 (権限管理) です。誰が何をすることができるのか、というのを管理します。

認可、すなわち「どんな権限があり、それぞれの権限で何ができるのか」は、認証とは違い、各サービスごとで考えるべきドメイン知識です。そこまではプロトコルやライブラリでは対処できません。したがって、認可に関しては、便利に使える統一的な方法を用意するにとどめました。

以下の2つの方法が考えられました。

  • Active Directory のユーザグループを利用する
  • (採用) 各サービスで独自の権限を定義する

ADのユーザグループは、役職やチーム等で作られるのが一般的です。社内のチームや役職によって権限が明確に定義されるのであれば、非常に便利だと思います。しかし、ADは情報システム部で管理している関係上、プロダクト開発の部門側のシステムとあまり密結合にしたくありませんでした。また、役職やチームと権限の関係もあまり強くなく、社内の実情にも合っていなかったので、特に使う強い理由もありませんでした。

したがって、各サービスごとに権限を定義し、ユーザを割り当てられるような設計が好ましいと判断しました。

最終的に、ライブラリが提供する機能は、以下のようになりました。

  • SAML 認証用のエンドポイント, 設定(トップページのpathなど)
  • 認証用ヘルパーメソッド (authenticate_admin! , current_admin など)
  • ユーザテーブル(AD上の情報(email)と突合する), 認可タグのテーブル, 認可用ヘルパーメソッド (has_tag?)
  • スーパーユーザー用の、ユーザ/認可タグを管理する画面

Authenticated Guest

これは余談です。

上の設計だと、あるユーザを認可するには認可タグをつける必要があり、そのためには必ずユーザテーブルにレコードを作成しなければなりません。しかし、まれに「ADアカウントさえ持っていれば、何の認可も不要で一定レベルまでは利用できるようにしたい」という要求がありました。これを Authenticated Guest と呼ぶことにし、ライブラリ側で解決しました。具体的にはヘルパーメソッドとして authenticate_admin! とは別に authenticate_guest! メソッドを用意し、上の要件のときはそのメソッドを使って認証するようにしました。

フェーズ1で達成したこと

  • 社内において情報システム部が管理している Active Directory のアカウントを利用し、SAML プロトコルを使うことで各サービスの管理画面で認証(SSO)できるようにした。これにより、アカウント管理を各サービスでやる必要がなくなり、負担の軽減につながった。
  • ruby-saml をラップしたライブラリ finc_admin_sso を作成した。これにより、Rails を利用するマイクロサービスはこの社内ADを使ったSSOを簡単に導入できるようになった。
  • finc_admin_sso に、簡易的な認可(権限管理)の機能を追加した。

フェーズ2: すべての管理画面やその権限の状況を一覧・変更できる admin_portal の開発と導入

残っていた課題

フェーズ1を達成した後も、以下の問題は依然として残っていました。

  • 管理画面がURLドメインではっきり分離されており、利用者が全部ブックマークせざるを得ないなど、使いにくさがある
  • 権限管理は各サービスごとの責務になっているので、一覧性がなく、中央で管理するのが難しい

前者だけであればただのリンク集のようなページがあればよく、実際それで運用されていました。

問題は後者です。管理画面にも種々のものがあり、中には「要配慮個人情報の閲覧」や「ポイントの付与」など、非常に厳格に権限を管理しなければならないものがあります。このような重要な権限はサービス側の独断では発行すべきではなく、情報システム部が管理している社内の申請フローを通す必要があります。したがって、全サービスのユーザと権限の種別が横断的に一覧でき、情報システム部にて管理されている状態にしたいという要求がありました。

それを解決するために作られたのが admin_portal です。

admin_portal の設計と実装

admin_portal は Rails アプリケーションとして作成されていますが、その役割は非常に薄く、特定のドメイン知識を持ちません。

各マイクロサービスは、ユーザと権限の一覧および更新の API エンドポイント群を提供します。これはドキュメント化されており、かつ、上の finc_admin_sso ライブラリを導入するだけで生えるようになっています。これは、上でも説明した「標準プロトコル」と「ライブラリ実装」の関係になっています。今回の標準プロトコルは社内向けのものになってしまいますが、十分シンプルであり他言語で実装するのも容易なレベルになっています。

admin_portal には、まず各サービスのURLドメインを登録しておきます。そして、上記の API を利用し、ユーザや権限に関する情報を収集し更新します。

やや話が飛びますが、この関係は、サービスメッシュの Control Plane と Data Plane の関係と同じようなものです。サービスメッシュでは、各サービスに Data Plane と呼ばれるコンポーネントがあり(例: Envoy)、API を提供します (Envoy であれば xDS API)。そして、その API を中央管理している Control Plane が利用し、各サービスのヘルス状態を確認して一覧にしたり、設定を注入したりします。このパターンは、マイクロサービスの自律性への影響を最小限にしながら中央管理するための方策であると言えます。

さて、admin_portal のユーザ・権限管理の更新の機能は、情報システム部の限られたユーザだけが利用可能です。一方で、単にマイクロサービスの管理画面を一覧する画面として見れば、CS対応をするユーザなども利用することができるでしょう。admin_portal 自身も、「FiNC 社内の管理画面全体を統括する」ことを対象ドメインとする一つのマイクロサービスであると考えて運用していくのが良いと考えています。

admin_portal は、近々運用が開始される予定です。

まとめ

マイクロサービスにおいて、管理画面が分散してしまうという課題に対して、一つの考え方を示しました。

マイクロサービスの横断的な問題への対処では、できるかぎり各サービスの自律性を奪わずにやるのが鉄則ですが、目の前の問題だけを見て対処していると、気づいたらがんじがらめになっていた、ということがあり得ます。そうならないように、マイクロサービスの基本思想に立ち返りながら、全体を見据えて設計していくのが重要だと考えています。特に、さまざまなものを中央管理したくなる欲求は常に存在するので、分散していることの良さを殺さない形で実現するように設計するのが重要ではないかと思います。

謝辞

フェーズ2のadmin_portal の設計は Fumiya Shinozuka (twitter: shinofumijp) のリードで行われています。彼にはフェーズ1の finc_admin_sso の設計や進め方にもかなり相談に乗ってもらいました。

また、finc_admin_sso および admin_portal の実装にはそれぞれインターン生が関わって進めてくれました。すでにインターン生の2人はFiNCを卒業され新たな道に進まれていますが、在籍中の活躍に敬意を表したいと思います。

--

--

qsona
FiNC Tech Blog

株式会社FiNC所属, WebエンジニアNode.js/Ruby, Rails