2021年9月2日 | Tomas Soukup | 製品とテクノロジー
前回のブログ記事では、OneLoginにとって信頼性がいかに重要であるか、そしてそれをどのように測定しているかをご紹介しました。
今回のブログ記事「スケーラビリティと信頼性のためのOneLoginの設計」では、信頼性とスケーラビリティの高い製品を実現するために、私たちがどのようにOneLoginを設計したかをご紹介していきます。
OneLoginは約10年前にスタートしました。スタートアップ時の成長過程で、多くのヒストリカルなお荷物、設計が不十分な(または全く設計されていない)コンポーネント、多くのボトルネック、「レガシー」なインフラなど、一般的に会社が成長し、雇用が加速し、管理が不足したときに形成されるものを構築しました。
1年半ほど前、私たちは信頼性と信頼性とスケーラビリティに焦点を当てた「Hydra」イニシアチブを立ち上げ、さらに「Hydra Cloud Infrastructure」の大規模な再設計プロジェクトを開始しました。
優れた製品設計や再設計は、目標から始まります。目標は、新しいデザインは何を満たすべきか、さらに重要なこととして、ソリューションの過剰設計を避けるために、何が必要でないかを把握するために重要です。
私たちの目標は次のとおりです。
メモ:
信頼性の定義と測定方法については、前回のブログ記事をご参照ください。
OneLoginでは、1秒間に数千件のリクエストを処理しています。
OneLogin Hydra Cloud Infrastructureの設計を始める前に、私たちは新しいアーキテクチャの主な原則と、必要とする制約条件をいくつか定義しました。
セキュリティが第一 - ソフトウェアシステムの設計は多くのトレードオフが含まれています。私たちはセキュリティを犠牲にしたくありません。
信頼性は重要な機能 - 高い信頼性は単なる非機能要件の一つではありません。我々のプラットフォームの重要な機能であり、差別化要因でもあります。
製品よりもプラットフォーム - IdaaSは歴史的に製品やサービスとして認識されてきましたが、私たちは最終的に大規模なアイデンティティプラットフォームを構築します。
単一障害点の排除 - エンドユーザーフローの経路上にあるアーキテクチャのどのレイヤーにも、単一障害点(またはコンポーネント)があってはなりません。
マスターまたはレプリカDBストレージ - Postgresが主なDBストアであり、これを他のものに置き換えることは現実的ではありません。Postgresのマスタースレーブモデルのような制約を用います。
コードとしてのイミュータブルインフラストラクチャ - すべてのインフラはコードで完全に記述され、Gitに保管されています。すべてのプロセスは自動化されており、オペレーターによる手動の変更(Click-Ops)やペットはありません。すべてのデプロイされたアーティファクト(サーバー、サービスなど)はイミュータブル(不変)です
最新のサイトの信頼性とスケーラビリティ技術は、万能のソリューションを提供するものではありません。サービスやシステムの種類によって、アプローチは異なります。重要なのは、問題を解決するために必要な要素を見つけ、それを用いることです。
以下は、OneLoginを運用してきた経験から、OneLogin Hydra Cloud Infrastructureの意思決定、トレードオフ、そして最終的な設計において重要な要素となったキーインサイトです。
テナントは相互に接続されていない
当社のテナント(顧客企業)は相互に接続されていません。データを共有することも、相互に作用することもありません。
本製品は、基礎となるリソースをより効率的に使用するためにマルチテナントとして設計されています。しかし、より高いスケーラビリティ、独立性、セキュリティ、異なるコンプライアンス要件、低レイテンシーを達成するために、テナントを自由に分離することができます。
アドミニストレーションとエンドユーザーのオペレーションは大きく異なり、本質的に独立している
オペレーションには大きく分けて3つのグループがあります。
これら3つのオペレーションでは、異なるレベルのSLA、重要性、スケール要件、対象者などが含まれます。
エンドユーザーのログインは、私たちにとって最も重要な機能であり、基本的に読み取り専用の操作です
OneLoginの主な機能は、エンドユーザーのログインです。
エンドユーザーログインとは、OneLogin UX、サポートされているプロトコル、またはAPIを通じて、OneLoginへのアクセス、OneLoginへの認証、OneLoginを介したアプリへの認証またはアクセスを試みるエンドユーザーに代わって、OneLoginにリクエストすることです
エンドユーザーのログインは、ほとんどの場合、(サブセットの)データを読み取るリードオンリーの操作ですが、それらを書き込む必要はほとんどありません。
補完的なエンドユーザーログイン操作は迅速に行なわれる必要がありますが、ただちに行う必要はありません
エンドユーザーログインには、サービスが完全に機能するために多くの補完的な操作が含まれています。これらの操作は迅速に行われる必要がありますが、必ずしもただちにまたは同期して行われる必要はありません。
次のセクションに移る前に、私たちのオペレーションについて少し説明します。
OneLoginは、マルチテナント型の製品として設計されています。Amazon Web Services(AWS)のクラウドコンピューティングプラットフォーム上に展開され、シャードに分割されています。各シャードは数万人のお客様に対応しています。シャードは最も高いレベルで分離されています。独立したデータストレージを持ち、完全に独立し分離され展開されています。
現在、EUシャードとUSシャードの2つのシャードがあり、FedRampでの使用を目的とした政府シャードの構築を進めています。
各シャードには、複数のアクティブなAWSリージョンに配置されています(単一障害点はありません)。
各リージョンでは、プラットフォームのすべてのサービスが、複数のアベイラビリティーゾーンに均等に分散されています。
図 - シャードとリージョン
少し寄り道をしました。本題に戻りましょう。
原理原則、目標、キーインサイトをまとめると、信頼性、スケーラビリティ、使用方法などの目的や要件が異なる、異なる対象者を含む、主に2つの層を扱っていることが明らかになりました。この2つの層をそれぞれ独立して運用することが可能だと思われました。
私たちはそれらを、「ログイン」と「アドミン」と呼ぶことにしました。
主な違いをまとめてると、以下の通りになります。
ログイン
アドミン
これは、私たちが必要とするスケーラビリティと信頼性のレベルを達成するための重要なデザイン方式でした。
DBのトポロジーがマスター・スレーブであることを考えると、(マスターDBが単一障害点であり、フェイルオーバーが瞬時に行われないため)書き込み処理でファイブナインの信頼性を得ることや、非常に高いスケーラビリティを実現することは非常に難しい(あるいは不可能)でしょう。しかし、ログイン操作を完全に分離すると、(ログイン操作はほとんどが読み取り専用であることを認識した上で)読み取り専用のレプリカ(またはその他のバックエンドのリソース)を「無制限に」割り当てることができ、極めて高い信頼性とスケーラビリティを実現することができます。
アドミンの部分は、まだいくつかの重要な限定されたリソース(マスターDBなど)に依存しています。しかし、その部分にはそのような極端に高い信頼性の要求は必要ありません。また、操作は大部分が非同期で行えるため、必要なレベルまでのスケールアップが非常に容易です。
私たちは、ファイブナインの信頼性を得るという目標(そして私たちが最も重視していること)を、最も重要な機能であるログイン層に適用することにしました。アドミン層にも十分な信頼性が必要ですが、この分野では、ログインとジョブのすべての操作に対応できるようにスケーリングすることに主眼を置いています。
そうして、私たちはクラスターの設計を始めました。
クラスタ ーとは、専用の機能を持つステートレスな(マイクロ)サービスのバンドルセットです。現在、2種類のクラスターがあります。
アドミンクラスターとログインクラスターは、主にマスター・スレーブDBアーキテクチャに従っています。
常に各シャード内の1つのリージョンがプライマリです。他のリージョンはセカンダリです。
プライマリリージョンには、アクティブなアドミンクラスターとマスター(読み書き可能な)Postgresデータベースがあります。
管理クラスターでは、管理タスク、イベント、バッチジョブ処理などの書き込み操作が処理され、操作結果がマスターデータベースに保存されます。
これで、ログインクラスターの設計を始めるための情報が揃いました。
プライマリではないリージョンは、セカンダリリージョンと呼ばれます。セカンダリリージョンには、読み取り専用のデータベースレプリカのみが含まれます(マスターデータベースは含まれません)。
エンドユーザーのフローは、ログインクラスターにルーティングされ、処理されます。エッジプロキシでは、ログイン層とアドミン層を決定する一連のルールを設定します。
ログインクラスターは、プライマリとセカンダリの両方のリージョンに配置されているため、スケーラビリティと信頼性が向上し、エンドユーザーのオペレーションをユーザーに近づけることができます。ログインクラスターはアドミンクラスターから完全に切り離され、隔離されています(プライマリリージョンであっても、それぞれのレプリカから読み取っています)。これにより、アドミンクラスターでの障害がエンドユーザーに影響を与えることを確実に妨げることができます。
図 - エッジプロキシからクラスターへのルーティング
ログインクラスターは、地域および地域間のアクティブ・アクティブな冗長性を備えています。
図 - ログインクラスター間の半々のトラフィック分割
この設計により、トラフィックの一部をリダイレクトする、または、不健全なクラスター(リージョン内)やリージョン全体から完全なフェイルオーバーを実行することができます。
エッジプロキシは、クラスター内で実行されている各サービスに対してサービス固有のバックエンドを登録します。1つのログインクラスター内のサービスのいずれかが不健全であると検出された場合、トラフィックは地域内の2つ目のログインクラスター内の健全なバックエンドに完全に切り替えられます。
クラスターフェイルオーバーは、通常はオペレーターの明示的な操作としてログインクラスター全体に対して実行することもでき、その結果、特定の地域のすべてのユーザートラフィックを利用可能なログインクラスターの1つのみに送ることができます。
完全なフェイルオーバーの前に、ターゲットクラスターが過負荷にならないように、ターゲットクラスターを現在の容量にスケールアップするためのチェックが行われます。
図 - 不健全なログインクラスターのフェイルオーバー
同じ部分的または完全なフェイルオーバーをリージョン全体で実行することができます!
リージョン全体のフェイルオーバーは、通常、インシデントの緩和または復旧措置として実行されます。リージョンフェイルオーバー時には、まず対象となるリージョンの容量がチェックされ、追加された負荷を処理するためにスケールアップされます。その後、新しいリクエストがフェイルオーバーリージョンにルーティングされます。
AWS Global AcceleratorとAWS Global networkを使用して、ユーザーのリクエストを最も近いリージョンにルーティングします。Global Acceleratorにより、トラフィックを整形し、不健全なリージョンからトラフィックの一部または全部をリダイレクトすることができます。
図 - 事前の容量調整によるリージョンフェイルオーバー
各ログインクラスターは、3つの読み取り専用のデータベースレプリカに接続されています。すべてのログインサービスは、読み取り・書き込み可能な(マスター)データベースに直接アクセスせずに操作することができます。エンドログインフロー中のほとんどの操作はリードオンリーですが、すべてではありません。ログインクラスターから書き込み操作を実行する方法はいくつかあります。
図 - 書き込み操作を非同期に処理
図 - DynamoDBのグローバルテーブルと(リージョナル)Elasticacheの利用
図 - クロスクラスター同期操作の実行
スケーラビリティとは、システムにリソースを追加することで、増大する作業量を処理するシステムの特性です。作業負荷が急激に増加しても、効果的なパフォーマンスを維持するためにシステムを再設計する必要がない場合、そのシステムはスケーラブルであると言うことができます。
スケーラビリティを実現するには2つの戦略があります。
ログインクラスター(およびOneLogin Hydraインフラ全体)は、完全な水平スケーラビリティのために設計されています。複数のアーキテクチャレベルでスケールアウトし、このコンセプトをさらに推し進めることができます。
この追加されたスケールアウトクラスターデザインは、1つのクラスターで数千のノードにスケールアウトする際に課される可能性のある制限にも対処します。さらに、このログインクラスターは、それぞれが他のクラスターから負荷を受けたり、クラスター間でトラフィックを再分配したりすることができるため、信頼性と耐障害性を高めることができます。
マルチテナントの設計と組み合わせることで、どのログインクラスターからでも、どのテナントに対しても「無制限」のリソースを効率的に提供することができます。
ここで示されたシステムにより、大規模かつ効率的でメンテナンス性に優れたIDaaSプラットフォームを実現することができますが、最上位のシャーディングを分離することで、スケールアウトを活用することもできます。各シャードは完全に独立し隔離されているため、新しいシャードを追加することで、理論的には任意の数のテナントにスケールアウトすることができます。
クラスターは、スタンドアロンのKubernetes(AWS EKS)クラスターとして実装されています。
そのアーキテクチャ、デザイン、展開は複雑であるため、ブログ記事でより深く説明する価値があります。
スケーラビリティと信頼性のためのシステム設計には複数の方法があり、その他と同様に唯一の方法はありません。
自分たちの製品がどのように使われているかを調べ、主なユーザーを分類し、何に重点を置くべきか、(もしかしたらさらに重要かもしれない)何に重点を置かないかを決めることで、将来のソリューションのキーコンセプトが見えてきました。
そのコンセプトを書き出し、その道のりに沿って一つ一つ設計上の決定を行った結果、スケーラブルで信頼性の高い製品を構築することができ、私たちはそれをとても誇りに思っています(信頼性への道のりを参照)。
自分の製品がどのように使われているかを見て、自分なりのキープリンシプル、制約そしてインサイトを見つけてください。このブログが、その道のりの手助けとなれば幸いです!