This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned on this page are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.
StatusAuthorsCoachDRIsOwning StageCreated
proposed -

このドキュメントは作業中のものであり、セルズの設計のごく初期の状態を表しています。重要な点は文書化されていませんが、将来的には追加される予定です。これはCellsの可能性のあるアーキテクチャの一つであり、どのアプローチを実装するか決める前に、代替案と比較検討するつもりです。この文書化は、このアプローチを選ばなかった理由を文書化できるよう、これを実装しないと決めた場合でも残しておきます。

提案ステートレス・ルーター

gitlab_users,gitlab_routes,gitlab_admin の関連テーブルを分解して、すべてのセル間で共有できるようにし、どのセルでもユーザーを認証してリクエストを正しいセルにルーティングできるようにします。セルは自分が所有していないリソースに対するリクエストを受け取るかもしれませんが、正しいセルにリダイレクトする方法を知っています。

ルータはステートレスで、routes データベースから読み取ることはありません。つまり、データベースとのやり取りはすべて Rails モノリスから行われます。このアーキテクチャは、トラフィックの少ないデータベースを地域間で複製できるようにすることで、地域もサポートしています。

ユーザーは直接Cellsの概念に触れることはありませんが、代わりに選択したOrganizationsによって異なるデータを見ることができます。Organizationsはアプリケーションの分離を強化するために導入される新しいエンティティで、Organizationは1つのCellにしか存在できないため、どのリクエストをどのCellにルーティングするかを決めることができます。

相違点

この提案とリクエストをバッファリングする提案の主な違いは、この提案がリクエストボディを正しいCellにリダイレクトするためにプリフライトAPIリクエスト(/api/v4/cells/learn)を使うことです。つまり、各リクエストは正確に一度だけ送られて処理されますが、URIはどのCellに送られるべきかをデコードするために使われます。

図でのまとめ

これは、ユーザーのリクエストがDNS経由で最も近いルーターにルーティングされ、ルーターがリクエストを送信するセルを選択する様子を示しています。

graph TD; user((User)); dns[DNS]; router_us(Router); router_eu(Router); cell_us0{Cell US0}; cell_us1{Cell US1}; cell_eu0{Cell EU0}; cell_eu1{Cell EU1}; user-->dns; dns-->router_us; dns-->router_eu; subgraph Europe router_eu-->cell_eu0; router_eu-->cell_eu1; end subgraph United States router_us-->cell_us0; router_us-->cell_us1; end

詳細

これは、ルーターが実際にどのセルにもリクエストを送信できることを示しています。ユーザーは地理的に最も近いルーターを取得します。

graph TD; user((User)); dns[DNS]; router_us(Router); router_eu(Router); cell_us0{Cell US0}; cell_us1{Cell US1}; cell_eu0{Cell EU0}; cell_eu1{Cell EU1}; user-->dns; dns-->router_us; dns-->router_eu; subgraph Europe router_eu-->cell_eu0; router_eu-->cell_eu1; end subgraph United States router_us-->cell_us0; router_us-->cell_us1; end router_eu-.->cell_us0; router_eu-.->cell_us1; router_us-.->cell_eu0; router_us-.->cell_eu1;

さらに詳細

これはデータベースを示しています。gitlab_usersgitlab_routes は米国リージョンにのみ存在しますが、他のリージョンにもレプリケートされます。レプリケーションに矢印がないのは、図を読むのが難しいからです。

graph TD; user((User)); dns[DNS]; router_us(Router); router_eu(Router); cell_us0{Cell US0}; cell_us1{Cell US1}; cell_eu0{Cell EU0}; cell_eu1{Cell EU1}; db_gitlab_users[(gitlab_users Primary)]; db_gitlab_routes[(gitlab_routes Primary)]; db_gitlab_users_replica[(gitlab_users Replica)]; db_gitlab_routes_replica[(gitlab_routes Replica)]; db_cell_us0[(gitlab_main/gitlab_ci Cell US0)]; db_cell_us1[(gitlab_main/gitlab_ci Cell US1)]; db_cell_eu0[(gitlab_main/gitlab_ci Cell EU0)]; db_cell_eu1[(gitlab_main/gitlab_ci Cell EU1)]; user-->dns; dns-->router_us; dns-->router_eu; subgraph Europe router_eu-->cell_eu0; router_eu-->cell_eu1; cell_eu0-->db_cell_eu0; cell_eu0-->db_gitlab_users_replica; cell_eu0-->db_gitlab_routes_replica; cell_eu1-->db_gitlab_users_replica; cell_eu1-->db_gitlab_routes_replica; cell_eu1-->db_cell_eu1; end subgraph United States router_us-->cell_us0; router_us-->cell_us1; cell_us0-->db_cell_us0; cell_us0-->db_gitlab_users; cell_us0-->db_gitlab_routes; cell_us1-->db_gitlab_users; cell_us1-->db_gitlab_routes; cell_us1-->db_cell_us1; end router_eu-.->cell_us0; router_eu-.->cell_us1; router_us-.->cell_eu0; router_us-.->cell_eu1;

変更の概要

  1. ユーザーデータ(プロファイル設定、認証情報、個人アクセストークンを含む)に関連するテーブルが、gitlab_users スキーマに分解されました。
  2. routes テーブルはgitlab_routes スキーマに分解されます。
  3. application_settings (およびおそらく他のいくつかのインスタンスレベルのテーブル)は、gitlab_admin スキーマに分解されます。
  4. 新しいカラムroutes.cell_idroutes テーブルに追加されます。
  5. どのセルにリクエストをルーティングするかを選択する新しいルーターサービスが存在します。
  6. ルーターが新しいリクエストを受信すると、/api/v4/cells/learn?method=GET&path_info=/group-org/project
  7. GitLabに組織という新しい概念が導入されます。
  8. 既存のすべてのエンドポイントをURIでルーティングできるようにするか、処理のために特定のCellに固定する必要があります。そのためには、/dashboard のような曖昧なエンドポイントを次のようなスコープに変更する必要があります。/organizations/my-organization/-/dashboard
  9. /admin のようなエンドポイントは常に特定のセルにルーティングされます。cell_0
  10. 各セルは/api/v4/cells/learn に応答し、各エンドポイントを分類することができます。
  11. gitlab_usersgitlab_routes への書き込みはUS リージョンのプライマリ PostgreSQL サーバに送信されますが、読み込みは同じリージョン内のレプリカから行うことができます。このため、これらの書き込みにはレイテンシが発生しますが、GitLabの他の部分と比較すると発生頻度は低いと思われます。

飛行前のリクエスト学習

リクエストを処理している間、URIはデコードされ、プリフライトリクエストが各非キャッシュエンドポイントに対して送信されます。

エンドポイントを要求するとき、GitLab Railsはルーティング可能なパスに関する情報を返します。GitLab Railsはpath_info をデコードして既存のエンドポイントとマッチさせ、ルーティング可能なエンティティ(プロジェクトのような)を見つけます。ルータはこれを短命のキャッシュ情報として扱います。

  1. プレフィックスマッチ:/api/v4/cells/learn?method=GET&path_info=/gitlab-org/gitlab-test/-/issues

    {
       "path": "/gitlab-org/gitlab-test",
       "cell": "cell_0",
       "source": "routable"
    }
    
  2. エンドポイントによっては完全一致が必要な場合があります:/api/v4/cells/learn?method=GET&path_info=/-/profile

    {
       "path": "/-/profile",
       "cell": "cell_0",
       "source": "fixed",
       "exact": true
    }
    

最初の反復におけるデフォルトの構成についての詳細な説明

すべてのユーザーは、ユーザー設定でコントロールできる新しいカラムusers.default_organizationGitLab.com Public 組織という概念を導入します。これは、すべての既存ユーザーのデフォルトの組織として設定されます。この組織は、Cell US0 (つまり、私たちのオリジナルのGitLab.comインスタンス)のすべての名前空間のデータをユーザーに見せることができます。この振る舞いは、/dashboard のようなグローバルページを表示しているときに、それが組織にスコープされていることすら知らされないように、既存のユーザーには見えないようにすることができます。

GitLab.com Public 以外のデフォルト組織を持つ新規ユーザーは、異なるユーザーエクスペリエンスを持つことになり、読み込むすべてのページが単一の組織にのみスコープされていることを完全に認識することになります。このようなユーザーは、/dashboard のようなグローバルページを読み込むことができず、/organizations/<DEFAULT_ORGANIZATION>/-/dashboard にリダイレクトされてしまいます。これはレガシーAPIの場合も同様で、このようなユーザーは組織にスコープされたAPIしか使用できない可能性があります。

管理エリア設定の詳細

私たちは、管理エリアの設定を維持したり同期させたりすることは、イライラさせ、苦痛を伴うと信じています。そのため、これを避けるために、すべての管理エリアの設定を分解し、gitlab_admin スキーマで共有します。このスキーマは書き込みトラフィックがほとんどないため、(他の共有スキーマと同様に)安全です。

異なるセルが異なる設定を必要とする場合(例えばElasticsearchのURL)、関連するapplication_settings の行でテンプレート化されたフォーマットを使用することにします。また、それが難しい場合は、per_cell_application_settings という新しいテーブルを導入し、セルごとに異なる設定を行えるようにします。このテーブルもgitlab_admin スキーマの一部として共有され、一元的に管理することができます。

長所

  1. ルーターはステートレスで、多くの地域に住むことができます。エニーキャストDNSを使用して、ユーザーに最も近い地域に解決します。
  2. セルは間違ったセルの名前空間に対するリクエストを受信しても、ユーザーは正しいレスポンスを得ることができます。また、次のリクエストが正しいセルに送信されるようにするルータでのキャッシュにより、次のリクエストは正しいセルに送信されます。
  3. コードの大部分はまだgitlab Rails コードベースにあります。ルーターは GitLab の URL がどのように構成されているかを理解する必要はありません。
  4. gitlab_usersgitlab_routesgitlab_admin を読み書きする責任はまだ Rails にあるので、ドメインモデルを分離して新しいインターフェースを構築する必要があるサービスを抽出するのに比べて、Rails アプリケーションには最小限の変更で済むことになります。
  5. 別個のルーティングサービスと比べて、RailsアプリケーションはURLを正しいセルにマッピングする方法についてより複雑なルールをエンコードすることができ、既存のAPIエンドポイントでも機能する可能性があります。
  6. 新しいインフラ (ルーターだけ) はすべてオプションで、シングルセルのセルフマネージドインストールではルーターを実行する必要すらなく、他に新しいサービスもありません。

短所

  1. gitlab_users gitlab_routesgitlab_admin データベースはリージョンをまたいで複製する必要があり、書き込みはリージョンをまたぐ必要があるかもしれません。実現可能かどうかを判断するために、関連テーブルの書き込みTPSを分析する必要があります。
  2. 多くの異なる Cell からデータベースへのアクセスを共有するということは、すべての Cell が Postgres スキーマレベルで結合されるということであり、これはデータベーススキーマの変更をすべての Cell のデプロイと同期して慎重に行う必要があることを意味します。このため、私たちがコントロールする API を持つ共有サービスによるアーキテクチャと比較して、Cell を密接に類似したバージョンに保つことが制限されます。
  3. ほとんどのデータは適切なリージョンに保存されますが、別のリージョンからプロキシされるリクエストもあり、これはある種のコンプライアンスにとってイシューになる可能性があります。
  4. gitlab_usersgitlab_routes データベースのデータは、すべてのリージョンで複製される必要があり、これは特定の種類のコンプライアンスにとってイシューとなる可能性があります。
  5. 多種多様なURL(つまりロングテール)を取得する場合、ルーターキャッシュは非常に大きくする必要があるかもしれません。そのような場合、ユーザークッキーに第2レベルのキャッシュを実装し、頻繁にアクセスされるPagesが常に最初に正しいセルに行くようにする必要があるかもしれません。
  6. 複数のセルからgitlab_usersgitlab_routes 、共有データベースアクセスを持つことは、複数のセルから呼び出されるサービスを抽出することと比べると、珍しいアーキテクチャの決定です。
  7. GraphQL URLのキャッシュ可能な要素を見つけることができない可能性が非常に高く、既存のGraphQLエンドポイントはroutes テーブルにないidに大きく依存していることが多いため、セルはどのセルがデータを持っているかを必ずしも知ることができません。そのため、/api/organizations/<organization>/graphql のようにパスに組織のコンテキストを含めるようにGraphQLコールを更新する必要があるでしょう。
  8. このアーキテクチャは、実装されたエンドポイントが、与えられたセル上で容易にアクセスできるデータにのみアクセスできることを意味し、多くのセルからの情報を集約することは考えにくい。
  9. 未知のルートはすべて最新のデプロイに送信されます。Cell US0 と仮定します。これは、新しく追加されたエンドポイントは最新のセルにしか解読できないためです。これは/cells/learn にとって問題ではなさそうですが、処理が軽量であるため、パフォーマンスへの影響はないはずです。

データベースの設定例

gitlab_usersgitlab_routesgitlab_admin の共有データベースを扱いながら、gitlab_maingitlab_ci の専用データベースを持つことは、config/database.ymlを使用する方法ですでに処理できるはずです。また、gitlab_usersgitlab_routesに対して単一の米国プライマリを持つ一方で、EU専用のレプリカを扱うこともできるはずです。以下は、上記のCellアーキテクチャのデータベース設定の一部のスニペットです。

セルUS0

# config/database.yml
production:
  main:
    host: postgres-main.cell-us0.primary.consul
    load_balancing:
      discovery: postgres-main.cell-us0.replicas.consul
  ci:
    host: postgres-ci.cell-us0.primary.consul
    load_balancing:
      discovery: postgres-ci.cell-us0.replicas.consul
  users:
    host: postgres-users-primary.consul
    load_balancing:
      discovery: postgres-users-replicas.us.consul
  routes:
    host: postgres-routes-primary.consul
    load_balancing:
      discovery: postgres-routes-replicas.us.consul
  admin:
    host: postgres-admin-primary.consul
    load_balancing:
      discovery: postgres-admin-replicas.us.consul

セル EU0

# config/database.yml
production:
  main:
    host: postgres-main.cell-eu0.primary.consul
    load_balancing:
      discovery: postgres-main.cell-eu0.replicas.consul
  ci:
    host: postgres-ci.cell-eu0.primary.consul
    load_balancing:
      discovery: postgres-ci.cell-eu0.replicas.consul
  users:
    host: postgres-users-primary.consul
    load_balancing:
      discovery: postgres-users-replicas.eu.consul
  routes:
    host: postgres-routes-primary.consul
    load_balancing:
      discovery: postgres-routes-replicas.eu.consul
  admin:
    host: postgres-admin-primary.consul
    load_balancing:
      discovery: postgres-admin-replicas.eu.consul

リクエストフロー

  1. gitlab-org はトップレベルの名前空間で、GitLab.com Public 組織のCell US0 に存在します。
  2. my-company はトップレベルの名前空間で、my-organization 組織のCell EU0 に存在します。

の一部である有料ユーザーのエクスペリエンスです。my-organization

このようなユーザーは、デフォルトの組織が/my-organization に設定され、この組織以外のグローバルルートを読み込むことができません。他のプロジェクト/ネームスペースをロードすることはできますが、ページ上部のMR/ToDo/イシューのカウントは最初の反復では正しく入力されません。ユーザーはこの制限を認識します。

  1. ユーザーはヨーロッパにいるため、DNSはヨーロッパのルーターに解決します。
  2. ルーターのキャッシュなしで/my-company/my-projectCell EU1
  3. /cells/learnCell EU1 に送られ、 はリソースが次の場所にあることを応答。Cell EU0
  4. Cell EU0 に保存されている正しいレスポンスを返します。
  5. ルータは/my-company/* にマッチするリクエストパスをキャッシュし、覚えています。Cell EU0
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 participant cell_eu1 as Cell EU1 user->>router_eu: GET /my-company/my-project router_eu->>cell_eu1: /api/v4/cells/learn?method=GET&path_info=/my-company/my-project cell_eu1->>router_eu: {path: "/my-company", cell: "cell_eu0", source: "routable"} router_eu->>cell_eu0: GET /my-company/my-project cell_eu0->>user: <h1>My Project...
  1. ユーザーはヨーロッパにいるため、DNSはヨーロッパのルーターに解決します。
  2. ルーターは/my-company/* をまだキャッシュしていないので、ランダムに選択します。Cell EU1
  3. /cells/learnCell EU1 に送られ、 はリソースが次の場所にあることを応答。Cell EU0
  4. Cell EU0 ログインフローを経由して
  5. ユーザーが/users/sign_in 、ランダムなCellを使用して実行するように要求します。/cells/learn
  6. Cell EU1 は固定ルートとしてcell_0 で応答。
  7. ログイン後のユーザーは/my-company/my-project をリクエストします。Cell EU0
  8. Cell EU0 に保存されている正しいレスポンスを返します。
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 participant cell_eu1 as Cell EU1 user->>router_eu: GET /my-company/my-project router_eu->>cell_eu1: /api/v4/cells/learn?method=GET&path_info=/my-company/my-project cell_eu1->>router_eu: {path: "/my-company", cell: "cell_eu0", source: "routable"} router_eu->>cell_eu0: GET /my-company/my-project cell_eu0->>user: 302 /users/sign_in?redirect=/my-company/my-project user->>router_eu: GET /users/sign_in?redirect=/my-company/my-project router_eu->>cell_eu1: /api/v4/cells/learn?method=GET&path_info=/users/sign_in cell_eu1->>router_eu: {path: "/users", cell: "cell_eu0", source: "fixed"} router_eu->>cell_eu0: GET /users/sign_in?redirect=/my-company/my-project cell_eu0-->>user: <h1>Sign in... user->>router_eu: POST /users/sign_in?redirect=/my-company/my-project router_eu->>cell_eu0: POST /users/sign_in?redirect=/my-company/my-project cell_eu0->>user: 302 /my-company/my-project user->>router_eu: GET /my-company/my-project router_eu->>cell_eu0: GET /my-company/my-project router_eu->>cell_eu0: GET /my-company/my-project cell_eu0->>user: <h1>My Project...
  1. ユーザーはヨーロッパにいるため、DNSはヨーロッパのルーターに解決します。
  2. ルーターのキャッシュには/my-company/* => Cell EU0 があるので、ルーターは以下を選択します。Cell EU0
  3. Cell EU0 は正しいレスポンスとキャッシュヘッダを返します。
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 participant cell_eu1 as Cell EU1 user->>router_eu: GET /my-company/my-project router_eu->>cell_eu0: GET /my-company/my-project cell_eu0->>user: <h1>My Project...
  1. ユーザーはヨーロッパにいるため、DNSはヨーロッパのルーターに解決します。
  2. ルーターにはこのURLのキャッシュ値がないため、ランダムにCell EU0
  3. Cell EU0 にリダイレクトします。Cell US0
  4. Cell US0 は正しいレスポンスとキャッシュヘッダを返します。
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 participant cell_us0 as Cell US0 user->>router_eu: GET /gitlab-org/gitlab router_eu->>cell_eu0: /api/v4/cells/learn?method=GET&path_info=/gitlab-org/gitlab cell_eu0->>router_eu: {path: "/gitlab-org", cell: "cell_us0", source: "routable"} router_eu->>cell_us0: GET /gitlab-org/gitlab cell_us0->>user: <h1>GitLab.org...

この場合、ユーザーは「デフォルトの組織」ではないので、TODOカウンターには典型的なTODOは含まれません。このことをUIのどこかで強調表示することもできます。将来的には、デフォルトの組織からTODOを取得できるようになるかもしれません。

  1. ユーザーはヨーロッパにいるため、DNSはヨーロッパのルーターに解決します。
  2. ルーターに/ ルート用のキャッシュがない(特にRailsがこのルートをキャッシュするように指示したことがない)。
  3. ルータはCell EU0 をランダムに選択します。
  4. Railsアプリケーションは、ユーザーのデフォルト組織が/my-organization であることを知っているので、ユーザーを次のようにリダイレクトします。/organizations/my-organization/-/dashboard
  5. ルータは/organizations/my-organization/* のキャッシュ値を持っているので、リクエストをPOD EU0
  6. Cell EU0 にリクエストを送ります。/organizations/my-organization/-/dashboard は現在あるのと同じダッシュボードビューですが、UIで明確に組織にスコープされています。
  7. ユーザーには(オプションで)、このページのデータはデフォルトの組織のものであり、デフォルトの組織が正しくない場合は変更できるというメッセージが表示されます。
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 user->>router_eu: GET / router_eu->>cell_eu0: GET / cell_eu0->>user: 302 /organizations/my-organization/-/dashboard user->>router: GET /organizations/my-organization/-/dashboard router->>cell_eu0: GET /organizations/my-organization/-/dashboard cell_eu0->>user: <h1>My Company Dashboard... X-Gitlab-Cell-Cache={path_prefix:/organizations/my-organization/}

Railsアプリケーションはすでに/ 、ダッシュボードのページにリダイレクトしているため、上記のページと同様に、/organizations/my-organization/-/dashboard

  1. ユーザーはヨーロッパにいるため、DNSはヨーロッパのルーターに解決します。
  2. ルーターは/not-my-companyCell US1 に住んでいることを知っているので、このルーターにリクエストを送ります。
  3. ユーザーはアクセスできないので、Cell US1 は 404 を返します。
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_us1 as Cell US1 user->>router_eu: GET /not-my-company/not-my-project router_eu->>cell_us1: GET /not-my-company/not-my-project cell_us1->>user: 404

新しいトップレベル・ネームスペースを作成します。

ユーザは、ネームスペースをどの組織に所属させるかを尋ねられます。ユーザが選択した場合、そのネームスペースmy-organization は .NET の他のすべてのネームスペースと同じセルに表示さ my-organizationれます。 ユーザが何も選択しなかった場合、デフォルトはGitLab.com Public になり、ユーザはこのネームスペースが既存の組織から分離され、1 つのページで両方のデータを表示できないことがわかります。

GitLabチームメンバーの経験/gitlab-org

このようなユーザーはレガシーユーザーとみなされ、デフォルトの組織はGitLab.com Public に設定されています。これは実際には存在しない「メタ」組織ですが、Railsアプリケーションはこの組織を解釈することで、/dashboard のようなレガシーなグローバル機能を使用して、Cell US0 にある名前空間全体のデータを参照することが許可されていることを知っています。Railsバックエンドは、/dashboard のような曖昧なルートをレンダリングするデフォルトのセルはCell US0であることも知っています。最後に、ユーザーは/my-organization のような別のセルにある組織に移動することができますが、移動すると、一部のデータが欠落している可能性があることを示すメッセージが表示されます(例:MRs/Issues/Todos)。

  1. ユーザーは米国にいるため、DNSは米国のルーターに解決されます。
  2. ルーターは、/gitlab-orgCell US0 に住んでいることを知っているので、このセルにリクエストを送信します。
  3. Cell US0 レスポンス
sequenceDiagram participant user as User participant router_us as Router US participant cell_us0 as Cell US0 user->>router_us: GET /gitlab-org/gitlab router_us->>cell_us0: GET /gitlab-org/gitlab cell_us0->>user: <h1>GitLab.org...
  1. ユーザーは米国にいるため、DNSは米国のルーターに解決されます。
  2. ルーターに/ ルート用のキャッシュがない(特にRailsがこのルートをキャッシュするように指示したことがない)。
  3. ルーターはCell US1 をランダムに選択します。
  4. Railsアプリケーションはユーザーのデフォルト組織がGitLab.com Public であることを知っているので、ユーザーを/dashboards にリダイレクトします(レガシーユーザーのみが/dashboard グローバルビューを見ることができます)。
  5. ルーターに/dashboard ルート用のキャッシュがない(特にRailsがこのルートをキャッシュするように指示したことがない)。
  6. ルーターはCell US1 をランダムに選択します。
  7. Railsアプリケーションは、ユーザーのデフォルトの組織がGitLab.com Public であることを知っているので、ユーザーに/dashboards (レガシーユーザーのみ/dashboard グローバルビューを見ることができます)をロードさせ、ルーターにレガシーセルをリダイレクトします。Cell US0
  8. Cell US0 はグローバルビューのダッシュボードページ/dashboard を提供します。
sequenceDiagram participant user as User participant router_us as Router US participant cell_us0 as Cell US0 participant cell_us1 as Cell US1 user->>router_us: GET / router_us->>cell_us1: GET / cell_us1->>user: 302 /dashboard user->>router_us: GET /dashboard router_us->>cell_us1: /api/v4/cells/learn?method=GET&path_info=/dashboard cell_us1->>router_us: {path: "/dashboard", cell: "cell_us0", source: "routable"} router_us->>cell_us0: GET /dashboard cell_us0->>user: <h1>Dashboard...

404が表示されます。

認証されていないユーザーの体験

/dashboard のようなグローバルルートがログインページにリダイレクトされる以外は、ログインユーザーと同様のフローです。

新規顧客がサインアップ

すでに組織に属しているのか、それとも組織を作りたいのかを尋ねられます。どちらも選択しない場合は、デフォルトのGitLab.com Public

組織は、1つのセルから別のセルに移動されます

TODO

URLに名前空間を含まないGraphQL/APIリクエスト

TODO

最近のイシュー/MRを記憶する検索バーのオートコンプリート・サジェスト機能

TODO

TODO

管理者

/admin ページを読み込みます。

  1. /admin にロックされています。Cell US0
  2. /admin /admin/cells/cell_0/projects のエンドポイントには、管理画面のプロジェクトのように、セルにスコープされているものがあり、ユーザーはドロップダウンで正しいものを選択する必要があります。

Postgres の Admin Area 設定は分岐を避けるためにすべてのセルで共有されますが、これらのページから生成される動的なデータとオペレータが特定のセルを表示したい場合があるため、どのセルが Admin Area ページを提供しているかを URL と UI で明確にします。

解決すべきその他の技術的問題

全セル間でのユーザーセッションの複製

現在、ユーザーセッションはRedisに保存されていますが、各セルは独自のRedisインスタンスを持つことになります。私たちはすでにセッション専用のRedisインスタンスを使っているので、gitlab_users PostgreSQLデータベースのように、これをすべてのセルで共有することも考えられます。しかし、同じリージョンからセッションをフェッチしたいので、レイテンシを考慮することが重要です。

代替案として、ユーザーセッションをすべてのセッションデータをエンコードするJWTペイロードに移動することもできますが、これには欠点があります。例えば、セッションがユーザーによって管理されるJWTにある場合、パスワードが変更されたときやその他の理由でユーザーセッションを失効させることは困難です。

どのように Cells 間をマイグレーションするのですか?

セル間でデータをマイグレーションするには、すべてのデータストアを要因にする必要があります:

  1. PostgreSQL
  2. Redis 共有ステート
  3. Gitaly
  4. Elasticsearch

タイミング攻撃で非公開グループの存在を漏らすことは可能ですか?

EUにルーターがあり、EUのルーターがデフォルトでEUにあるCellにリダイレクトすることを知っている場合、そのレイテンシ(仮に10msとします)を知っています。今、あなたのリクエストがバウンスバックされ、異なるレイテンシを持つUSにリダイレクトされた場合(ラウンドトリップは約60ミリ秒であると仮定します)、あなたは404がUSセルによって返されたことを推測し、あなたの404が実際には403であることを知ることができます。

このことは、実際に異なる地域のセルを実装するまで延期することができます。このようなタイミング攻撃は、今日の権限チェックの方法で理論的にはすでに可能ですが、タイミングの違いはおそらく検出するには小さすぎるでしょう。

このリスクを軽減する一つのテクニックは、ルーターがセルから404を返 すリクエストにランダムな遅延を追加することかもしれません。

ランナーはすべてのセルで共有されるべきですか?

2つの選択肢がありますが、どちらが簡単か決めましょう:

  1. ランナー登録テーブルとキューイングテーブルを分解し、すべてのセルで共有すること。これはスケーラビリティに影響を与えるかもしれません。また、グループ/プロジェクト・ランナーを含めるかどうかを検討する必要があります。これらは共有する必要がある高トラフィック・テーブルなので、スケーラビリティの懸念があるかもしれません。
  2. Runnerはセルごとに登録されますが、おそらくセルごとに別々のRunnerを持つか、あるいは多くのセルに同じRunnerを登録することになるでしょう。

すべてのセルで競合しない一意のIDを保証するには?

このプロジェクトでは、少なくともネームスペースとプロジェクトがすべてのセルで一意のIDを持つことを想定しています。これらのテーブルは異なるデータベースにまたがっているため、一意のIDを保証するには新しいソリューションが必要になります。一意なIDが必要なテーブルは他にもあるでしょうし、GraphQLや他のAPIのルーティングをどのように解決するか、また他の設計目標によっては、主キーがすべてのテーブルで一意であることが望ましいと判断されるかもしれません。