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. The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
rejected -

이 제안은 routing service proposal에 의해 대체되었습니다.

이 문서는 작업 중이며 Pods 설계의 초기 단계를 나타냅니다. 중요한 측면들은 문서화되지 않았으나, 향후 추가할 예정입니다. 이는 Pods의 한 가지 가능한 아키텍처이며, 우리는 구현할 접근 방식을 결정하기 전에 대안과 대조할 것을 의도하고 있습니다. 이 접근 방식을 선택하지 않기로 결정해도 이 문서는 보관될 것이며, 우리가 이 접근 방식을 선택하지 않은 이유를 문서화할 수 있게 될 것입니다.

제안: 요청 버퍼링을 사용하는 상태 없는 라우터

gitlab_users, gitlab_routes, gitlab_admin 관련 테이블을 분해하여 모든 셀 간에 공유할 수 있도록하여 사용자를 인증하고 요청을 올바른 셀로 라우팅할 수 있게 합니다. 셀은 자신이 소유하지 않은 리소스에 대한 요청을 받을 수 있지만, 올바른 셀로 리디렉션하는 방법을 알고 있습니다.

라우터는 상태를 유지하지 않으며 routes 데이터베이스에서 읽지 않으므로 모든 데이터베이스와의 상호작용은 여전히 Rails 모놀리스에서 발생합니다. 이 아키텍처는 지역을 지원하여 지역 간에 트래픽이 적은 데이터베이스가 복제될 수 있도록 합니다.

사용자는 셀의 개념에 직접 노출되지 않지만 대신 사용자가 선택한 조직에 따라 다른 데이터를 볼 것입니다. 조직은 응용 프로그램에서 격리를 강화하고 어떤 요청이 어떤 셀로 라우팅될 지 결정할 수 있도록하는 새로운 엔터티가 될 것입니다. 왜냐하면 조직은 단일 셀에만 있을 수 있기 때문입니다.

차이점

이 제안과 학습 라우트를 사용한 제안 간의 주요 차이점은 이 제안은 항상 모든 셀 중 하나로 요청을 보낸다는 것입니다. 요청이 처리되지 않을 경우 관련 헤더와 함께 다시 보내질 것입니다. 이를 위해 요청이 버퍼링되어야 합니다. 이를 통해 요청 디코딩은 URI나 Rails에 의한 요청 본문으로 모두 가능합니다. 이는 각 요청이 한 번 이상 보내지고 결과적으로 여러 번 처리될 수 있다는 것을 의미합니다.

학습 라우트를 사용한 제안은 라우터가 항상 URI에 라우팅 가능한 정보가 인코딩되어 있어야 하고 라우터가 사전 전송 요청을 보내야 한다는 것을 요구합니다.

다이어그램에서 요약

사용자 요청이 DNS를 통해 가장 가까운 라우터로 라우팅되고 라우터는 셀로 요청을 보내는 방법을 보여줍니다.

미국
유럽
셀 US0
라우터
셀 US1
셀 EU0
라우터
셀 EU1
사용자
DNS
더 많은 세부 정보 라우터는 실제로 어떤 셀에든 요청을 보낼 수 있음을 보여줍니다. 사용자는 지리적 위치에 따라 가장 가까운 라우터를 받게 됩니다. ```mermaid graph TD; user((사용자)); dns[DNS]; router_us(라우터); router_eu(라우터); cell_us0{셀 US0}; cell_us1{셀 US1}; cell_eu0{셀 EU0}; cell_eu1{셀 EU1}; user-->dns; dns-->router_us; dns-->router_eu; subgraph 유럽 router_eu-->cell_eu0; router_eu-->cell_eu1; end subgraph 미국 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_users`와 `gitlab_routes`는 미국 지역에만 있지만 다른 지역으로 복제됩니다. 복제는 다이어그램을 읽기 어려우므로 화살표는 따로 표시하지 않습니다. ```mermaid graph TD; user((사용자)); dns[DNS]; router_us(라우터); router_eu(라우터); cell_us0{셀 US0}; cell_us1{셀 US1}; cell_eu0{셀 EU0}; cell_eu1{셀 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 유럽 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 미국 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_id라는 새로운 열이 routes 테이블에 추가됩니다.
  5. 새로운 라우터 서비스가 도입되어 요청을 라우팅할 셀을 선택합니다.
  6. GitLab에 조직이라는 새로운 개념을 도입하고 사용자는 “기본 조직”을 선택할 수 있습니다. 이것은 사용자 수준의 설정입니다. 기본 조직은 /dashboard와 같은 모호한 경로에서 사용자를 /organizations/my-organization/-/dashboard와 같이 조직 범위의 경로로 리디렉션하는 데 사용됩니다. 기존 사용자는 Cell US0의 글로벌 리소스를 계속 사용할 수 있는 특별한 기본 조직을 가져게 됩니다. 모든 기존 네임스페이스는 초기에 이 공용 조직으로 이동합니다.
  7. 셀이 routes.cell_id에 대한 요청을 소유하지 않은 경우 302X-Gitlab-Cell-Redirect 헤더로 routes.cell_id에 대한 올바른 셀로 요청을 보낼 수 있습니다. 올바른 셀은 이 요청이 어떻게 캐싱되어야 하는지를 나타내는 X-Gitlab-Cell-Cache 헤더를 설정할 수 있습니다. 예를 들어, 요청이 /gitlab-org/gitlab였다면 헤더는 /gitlab-org/* => Cell US0 (예: /gitlab-org/로 시작하는 모든 요청은 항상 Cell US0로 라우팅될 수 있음)를 인코딩합니다.
  8. 셀이 (캐시로부터) 요청을 보낼 셀을 모르는 경우 해당 지역 내에서 무작위 셀을 선택합니다.
  9. gitlab_usersgitlab_routes에 대한 쓰기는 미국 지역의 주 PostgreSQL 서버로 전송되지만 읽기는 동일한 지역의 복제본에서 올 수 있습니다. 이는 기존 GitLab의 나머지에 비해 드믄 빈도로 발생되기 때문에 이러한 쓰기에는 지연이 추가될 것으로 예상됩니다.

첫 번째 반복의 기본 조직에 대한 상세 설명

모든 사용자는 사용자 설정에서 제어할 수 있는 users.default_organization이라는 새로운 열을 받게 됩니다. 우리는 GitLab.com Public 조직이라는 개념을 도입할 것입니다. 기존 사용자의 기본 조직으로 설정될 것입니다. 이 조직은 사용자가 Cell US0 (예: 원래의 GitLab.com 인스턴스)의 모든 네임스페이스의 데이터를 볼 수 있게 할 것입니다. 기존 사용자에게는 이 동작이 보이지 않을 수 있어서 그들은 심지어 /dashboard와 같은 글로벌 페이지를 볼 때 조직 범위로 제한된 것도 알려주지 않을 것입니다.

GitLab.com Public 외의 다른 기본 조직이 있는 모든 새로운 사용자는 별도의 사용자 경험을 받게 되며 로드하는 모든 페이지가 항상 하나의 조직 범위로만 제한됨을 완전히 인식하게 될 것입니다. 이러한 사용자는 /dashboard와 같은 글로벌 페이지를 로드할 수 없으며 항상 /organizations/<DEFAULT_ORGANIZATION>/-/dashboard로 리디렉션됩니다. 이것은 레거시 API에도 적용될 수 있으며 해당 사용자는 조직 범위에 한정된 API만 사용할 수 있을 것입니다.

관리자 영역 설정의 상세 설명

관리 및 동기화되는 Admin Area 설정은 번거로우며 고통스러울 것으로 생각되어 분해하고 모든 Admin Area 설정을 gitlab_admin 스키마에서 공유할 것으로 믿고 있습니다. 이것은 여러 셀에서 공유되기 때문에 안전할 것으로 생각되며 (다른 공유 스키마와 유사) 이는 이러한 설정이 매우 적은 쓰기 트래픽을 받기 때문입니다.

다른 셀이 다른 설정이 필요한 경우(예: Elasticsearch URL 등) 관련 application_settings 행에서 동적으로 변환되도록 템플릿 형식을 사용하거나 그것이 어려운 경우 per_cell_application_settings라는 새로운 테이블을 도입할 것입니다. 이는 셀당 1행씩 각 셀에 대해 다른 설정을 가능하도록 하기 위함입니다. 이것은 여전히 gitlab_admin 스키마의 일부이며 관리도 가능하며 모든 셀에 대해 동일하게 설정을 유지하는 것을 단순화할 수 있게 될 것입니다.

장점

  1. 라우터는 무상태이며 여러 지역에서 운영될 수 있습니다. Anycast DNS를 사용하여 사용자에게 가장 가까운 지역으로 해결합니다.
  2. 셀은 잘못된 셀에 대한 네임스페이스의 요청을 받을 수 있으며 해당 사용자는 올바른 응답을 받게 되며 라우터에서의 캐싱은 다음 요청이 올바른 셀로 전송되도록 보장합니다. 다음 요청은 올바른 셀로 이동합니다.
  3. 코드의 대부분은 여전히 gitlab 레일 코드베이스에 존재합니다. 라우터는 실제로 GitLab URL이 어떻게 구성되는지를 이해할 필요가 없습니다.
  4. gitlab_users, gitlab_routes, gitlab_admin을 읽고 쓰는 책임은 여전히 레일에 있기 때문에 도메인 모델을 격리하고 새로운 인터페이스를 구축하는 서비스를 추출하는 것에 비해 레일 애플리케이션에는 최소한의 변경이 필요할 것으로 예상됩니다.
  5. 별도의 라우팅 서비스와 비교했을 때, 이것은 레일 애플리케이션에서 URL을 올바른 셀로 매핑하는 복잡한 규칙을 인코딩할 수 있으며 일부 기존 API 엔드포인트에도 작동할 수 있을 것입니다.
  6. 모든 새 인프라(단순히 라우터만)는 선택 사항이며 단일 셀의 Self-managed 설치는 라우터를 실행할 필요가 없으며 다른 새로운 서비스도 없습니다.

단점

  1. gitlab_users, gitlab_routes, gitlab_admin 데이터베이스는 여러 지역에 복제되어야하며 쓰기는 여러 지역으로 이동해야합니다. 관련 테이블에 대한 쓰기 TPS를 분석하여 이것이 실행 가능한지 여부를 결정해야합니다.
  2. 여러 다른 셀에서 데이터베이스에 대한 공유 액세스는 모든 셀이 Postgres 스키마 수준에서 결합되어 있음을 의미하며 따라서 데이터베이스 스키마의 변경은 모든 셀의 배포와 함께 주의깊게 이뤄져야 합니다. 이는 API를 제어하는 공유 서비스를 가진 아키텍처와 비교하여 셀이 밀접하게 유사한 버전으로 유지되도록 제한되어 있음을 의미합니다.
  3. 대부분의 데이터가 올바른 지역에 저장되지만 다른 지역에서 프록시로 전송될 수 있으며 이는 특정 유형의 규정적 문제가 될 수 있습니다.
  4. gitlab_usersgitlab_routes 데이터베이스의 데이터는 모든 지역에 복제되어야 하며 이는 특정 유형의 규정적 문제가 될 수 있습니다.
  5. 광범위한 URL(예: long tail)의 다양한 경우 라우터 캐시가 매우 크기가 커야 할 수 있습니다. 이런 경우에는 사용자 쿠키에서 두 번째 수준의 캐싱을 구현해야할 수 있으며 사용자의 빈번한 액세스 페이지가 항상 처음에 올바른 셀로 이동하게 할 것입니다.
  6. 여러 셀에서 gitlab_usersgitlab_routes에 대한 공유 데이터베이스 액세스는 여러 셀에서 호출되는 서비스를 추출하는 것과 비교하여 일반적으로 이상한 아키텍처의 결정입니다.
  7. 아마도 GraphQL URL의 캐시 가능한 요소를 찾을 수 없을 것으로 예상되며 기존의 GraphQL 엔드포인트는 일반적으로 routes 테이블에 없는 id에 매우 의존하기 때문에 셀은 해당 데이터를 가지고 있는 셀을 알지 못할 수 있습니다. 따라서 우리는 아마도 기존의 GraphQL 호출을 경로에 조직 컨텍스트를 포함하도록 업데이트해야 할 것입니다. 예를 들어, /api/organizations/<organization>/graphql와 같이.
  8. 이 아키텍처는 구현된 엔드포인트가 특정 셀에서 쉽게 액세스할 수 있는 데이터만 액세스할 수 있지만 여러 셀로부터 정보를 집계할 가능성은 낮습니다.
  9. 알려지지 않은 경로는 최신 배포로 보내지며 우리는 이것이 Cell US0임을 가정합니다. 나중에 요청 처리가 무거울 수 있으므로 일부 셀이 해당 트래픽의 상당한 양을 받게 될 수 있습니다.

데이터베이스 구성 예시

공유된 gitlab_users, gitlab_routesgitlab_admin 데이터베이스를 처리하면서 gitlab_maingitlab_ci 전용 데이터베이스를 사용하는 방식은 이미 config/database.yml을 사용하여 처리되어야 합니다. 또한, gitlab_usersgitlab_routes의 단일 미국 본사와 전용 EU 복제본을 처리할 수 있어야 합니다. 위에서 설명한 Cell 아키텍처의 데이터베이스 구성 부분의 일부로 아래에 해당하는 데이터베이스 구성의 일부분이 나와 있습니다.

Cell US0 ```yaml # 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 ```
Cell EU0 ```yaml # 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/Issue 카운트가 처음에는 올바르게 채워지지 않을 것입니다. 사용자는이 제한을 알고 있을 것입니다.

로그인한 상태에서 /my-company/my-project로 이동

  1. 사용자는 유럽에 있으므로 DNS가 유럽의 라우터로 해석됩니다.
  2. 라우터 캐시 없이 /my-company/my-project를 요청하므로 라우터는 무작위로 Cell EU1을 선택합니다.
  3. Cell EU1/my-company가 없지만 Cell EU0에 존재한다는 것을 알기 때문에 라우터를 Cell EU0로 리디렉션합니다.
  4. Cell EU0은 적절한 응답 및 라우터 /my-company/* => Cell EU0에 대한 캐시 헤더 설정을 반환합니다.
  5. 이제 라우터는 /my-company/*에 일치하는 모든 요청 경로를 Cell EU0로 가야한다고 캐시하고 기억합니다.
Cell EU1Cell EU0Router EUUserCell EU1Cell EU0Router EUUserGET /my-company/my-projectGET /my-company/my-project302 /my-company/my-project X-Gitlab-Cell-Redirect={cell:Cell EU0}GET /my-company/my-project<h1>My Project... X-Gitlab-Cell-Cache={path_prefix:/my-company/}

로그인하지 않은 상태에서 /my-company/my-project로 이동

  1. 사용자는 유럽에 있으므로 DNS가 유럽의 라우터로 해석됩니다.
  2. 라우터에는 아직 /my-company/*가 캐시되어 있지 않으므로 무작위로 Cell EU1을 선택합니다.
  3. Cell EU1은 로그인 흐름을 통해 사용자를 리디렉션합니다.
  4. 여전히 라우터 캐시 없이 /my-company/my-project를 요청하므로 라우터는 무작위 셀 Cell EU1을 선택합니다.
  5. Cell EU1/my-company이 없지만 Cell EU0에 존재한다는 것을 알기 때문에 라우터를 Cell EU0로 리디렉션합니다.
  6. Cell EU0은 적절한 응답 및 라우터 /my-company/* => Cell EU0에 대한 캐시 헤더 설정을 반환합니다.
  7. 이제 라우터는 /my-company/*에 일치하는 모든 요청 경로를 Cell EU0로 가야한다고 캐시하고 기억합니다.
Cell EU1Cell EU0Router EUUserCell EU1Cell EU0Router EUUserGET /my-company/my-projectGET /my-company/my-project302 /users/sign_in?redirect=/my-company/my-projectGET /users/sign_in?redirect=/my-company/my-projectGET /users/sign_in?redirect=/my-company/my-project<h1>Sign in...POST /users/sign_in?redirect=/my-company/my-projectPOST /users/sign_in?redirect=/my-company/my-project302 /my-company/my-projectGET /my-company/my-projectGET /my-company/my-project302 /my-company/my-project X-Gitlab-Cell-Redirect={cell:Cell EU0}GET /my-company/my-project<h1>My Project... X-Gitlab-Cell-Cache={path_prefix:/my-company/}

마지막 단계 후 /my-company/my-other-project로 이동

  1. 유저가 유럽에 있으므로 DNS는 유럽의 라우터로 해석됩니다.
  2. 라우터 캐시에는 이제 /my-company/* => Cell EU0가 있으므로 라우터는 Cell EU0을 선택합니다.
  3. Cell EU0은 올바른 응답 및 캐시 헤더를 다시 반환합니다.
Cell EU1Cell EU0Router EUUserCell EU1Cell EU0Router EUUserGET /my-company/my-projectGET /my-company/my-project<h1>My Project... X-Gitlab-Cell-Cache={path_prefix:/my-company/}

마지막 단계 후 /gitlab-org/gitlab로 이동

  1. 유저가 유럽에 있으므로 DNS는 유럽의 라우터로 해석됩니다.
  2. 이 URL에 대한 라우터에 캐시된 값이 없으므로 무작위로 Cell EU0을 선택합니다.
  3. Cell EU0은 라우터를 Cell US0로 리디렉션합니다.
  4. Cell US0은 올바른 응답과 함께 다시 캐시 헤더를 반환합니다.
Cell US0Cell EU0Router EUUserCell US0Cell EU0Router EUUserGET /gitlab-org/gitlabGET /gitlab-org/gitlab302 /gitlab-org/gitlab X-Gitlab-Cell-Redirect={cell:Cell US0}GET /gitlab-org/gitlab<h1>GitLab.org... X-Gitlab-Cell-Cache={path_prefix:/gitlab-org/}

이 경우 유저는 “기본 조직”에 있지 않으므로 TODO 카운터에 일반적인 할 일이 포함되지 않습니다. 우리는 UI 어딘가에 이것을 강조하기로 선택할 수 있습니다. 향후 반복에서 그들을 위해 기본 조직에서 해당 내용을 가져올 수 있을 것입니다.

/로 이동

  1. 유저가 유럽에 있으므로 DNS는 유럽의 라우터로 해석됩니다.
  2. 라우터는 / 경로에 대한 캐시를 가지고 있지 않습니다(특히 Rails는 이 경로를 캐시하도록 지시하지 않음).
  3. 라우터는 무작위로 Cell EU0을 선택합니다.
  4. Rails 애플리케이션은 유저의 기본 조직이 /my-organization임을 알고 있으므로 유저를 /organizations/my-organization/-/dashboard로 리디렉션합니다.
  5. 라우터는 /organizations/my-organization/*에 대한 캐시된 값이 있으므로 요청을 POD EU0로 보냅니다.
  6. Cell EU0은 UI에 명확하게 표시된 조직으로 범위가 지정된 현재 대시보드 뷰와 같은 새로운 페이지 /organizations/my-organization/-/dashboard를 제공합니다.
  7. 유저에게 이 페이지의 데이터가 기본 조직에서만 제공되며, 기본 조직이 올바르지 않다면 기본 조직을 변경할 수 있다는 메시지가 (선택사항으로) 표시됩니다.
routerCell EU0Router EUUserrouterCell EU0Router EUUserGET /GET /302 /organizations/my-organization/-/dashboardGET /organizations/my-organization/-/dashboardGET /organizations/my-organization/-/dashboard<h1>My Company Dashboard... X-Gitlab-Cell-Cache={path_prefix:/organizations/my-organization/}

/dashboard로 이동

위와 같이 Rails 애플리케이션은 이미 /를 대시보드 페이지로 리디렉션합니다.

로그인한 상태에서 /not-my-company/not-my-project로 이동 (그러나 프로젝트/그룹이 비공개이므로 액세스할 수 없음)

  1. 유저가 유럽에 있으므로 DNS는 유럽의 라우터로 해석됩니다.
  2. 라우터는 /not-my-companyCell US1에 있다는 것을 알고 있으므로 이에 대한 요청을 해당 셀로 보냅니다.
  3. 유저는 액세스 권한이 없기 때문에 Cell US1이 404를 반환합니다.
Cell US1Router EUUserCell US1Router EUUserGET /not-my-company/not-my-projectGET /not-my-company/not-my-project404

새로운 최상위 네임스페이스 생성

유저에게 해당 네임스페이스가 어떤 조직에 속하는지 묻습니다. my-organization을 선택하면 다른 my-organization 내의 모든 네임스페이스와 동일한 셀에 끝납니다. 아무것도 선택하지 않으면 GitLab.com Public로 기본 설정되며, 유저에게 두 조직의 데이터가 단일 페이지에서 보이지 않으므로 각각이 격리됨을 명확하게 설명합니다.

/gitlab-org의 일부인 GitLab 팀 멤버의 경험

이러한 유저는 레거시 유저로 간주되며, 기본 조직이 GitLab.com Public으로 설정되어 있습니다. 이 조직은 실제로 존재하지 않는 “메타” 조직이며, Rails 애플리케이션은 이 조직을 해석하여 /dashboard 등의 레거시 글로벌 기능을 사용할 수 있음을 알고 있습니다. Rails 백엔드는 또한 /dashboard와 같이 애매한 경로의 기본 셀을 Cell US0으로 렌더링할 수 있음을 인지합니다. 마지막으로 유저는 /my-organization과 같은 다른 셀의 조직으로 이동할 수 있지만, 이때 유저는 일부 데이터가 누락될 수 있다는 메시지를 볼 수 있습니다(예: MR/이슈/할 일 카운트).

로그인하지 않은 채 /gitlab-org/gitlab로 이동

  1. 유저가 미국에 있으므로 DNS는 미국 라우터로 해석됩니다.
  2. 라우터는 /gitlab-orgCell US0에 있다는 것을 알고 있으므로 이 셀로 요청을 보냅니다.
  3. Cell US0은 응답을 제공합니다.
Cell US0Router USUserCell US0Router USUserGET /gitlab-org/gitlabGET /gitlab-org/gitlab<h1>GitLab.org... X-Gitlab-Cell-Cache={path_prefix:/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를 제공합니다.
Cell US1Cell US0Router USUserCell US1Cell US0Router USUserGET /GET /302 /dashboardGET /dashboardGET /dashboard302 /dashboard X-Gitlab-Cell-Redirect={cell:Cell US0}GET /dashboard<h1>Dashboard...

/my-company/my-other-project로 로그인한 상태에서 이동(하지만 해당 프로젝트에 접근할 수 없음)

404 오류가 발생합니다.

인증되지 않은 사용자의 경험

전역 경로인 /dashboard와 같은 경로는 기본 조직을 선택할 수 없기 때문에 로그인 페이지로 리디렉션됩니다.

새로운 고객이 가입합니다

이들은 이미 조직에 속해 있는지 또는 새로운 조직을 만들고 싶은지 묻힙니다. 둘 중 어느 것도 선택하지 않으면 기본적으로 GitLab.com Public 조직에 속하게 됩니다.

조직이 다른 셀로 이동합니다

TODO

URL에 네임스페이스가 포함되지 않은 GraphQL/API 요청

TODO

검색 표시줄의 자동 완성 제안 기능으로 최근 이슈/MR을 기억

TODO

글로벌 검색

TODO

관리자

/admin 페이지를 로딩합니다

  1. 라우터가 무작위 셀 Cell US0을 선택합니다.
  2. Cell US0은 사용자를 /admin/cells/cellus0로 리디렉션합니다.
  3. Cell US0은 관리자 영역 페이지를 렌더링하고 또한 /admin/cellss/cellus0/* => Cell US0를 캐시하기 위한 캐시 헤더를 반환합니다. 관리자 영역 페이지에는 다른 선택할 수 있는 셀을 보여주는 드롭다운 디렉터리이 있으며, 쿼리 매개변수가 변경됩니다.

Postgres의 관리 영역 설정은 발산을 피하기 위해 모든 셀에서 공유되지만, URL 및 UI에서 어떤 셀이 관리 영역 페이지를 제공하는지 명확히 표시됩니다. 이 페이지들에서 동적 데이터가 생성되고 운영자가 특정 셀을 볼 수 있어야 하기 때문입니다.

해결해야 할 더 많은 기술적 문제

모든 셀 간에 사용자 세션을 복제하는 방법

현재 사용자 세션은 Redis에 저장되지만 각 셀은 자체적인 Redis 인스턴스를 갖게 됩니다. 이미 세션을 위해 전용 Redis 인스턴스를 사용하고 있기 때문에 gitlab_users PostgreSQL 데이터베이스와 마찬가지로 이를 모든 셀과 공유할 수 있도록 고려할 수 있습니다. 그러나 중요한 고려사항은 대부분의 경우 세션을 동일한 지역에서 가져오기를 원하기 때문에 지연 시간입니다.

대안은 사용자 세션이 사용자가 제어하는 JWT 페이로드로 이동하는 것입니다. 그러나 이에는 단점이 있습니다. 예를 들어, 사용자 세션이 JWT에서 제어되기 때문에 사용자의 비밀번호가 변경되었을 때 또는 기타 이유로 사용자 세션의 만료를 어렵게 만듭니다.

셀 간 데이터 마이그레이션

셀 간 데이터를 마이그레이션하려면 모든 데이터 리포지터리를 고려해야 합니다:

  1. PostgreSQL
  2. 공유 상태의 Redis
  3. Gitaly
  4. Elasticsearch

타이밍 공격을 통해 개인 그룹의 존재를 노출시킬 수 있는 가능성은 여전히 있나요?

EU에 라우터가 있다고 가정하고, EU 라우터가 기본적으로 EU 위치에 있는 셀로 리디렉션한다는 것을 알고 있다면, 해당 셀의 지연 시간을 알 수 있습니다(가정: 10ms). 지금, 요청이 되돌아와 US로 리디렉션된다면 다른 지연 시간(왕복이 약 60ms라고 가정)을 가지고 있기 때문에 404가 US 셀에서 반환되었음을 유추할 수 있습니다. 그러면 여러분의 404가 실제로 403이었다는 것을 알 수 있습니다.

여러분은 이러한 공격을 이미 현재의 권한 확인 방식으로 이론적으로 가능하지만, 타이밍 차이가 너무 작아서 실제로는 감지하기 어렵다고 결론짓습니다.

이러한 위험을 완화하기 위한 기술적 방법 중 하나는 라우터가 셀로부터 404를 반환하는 요청에 대해 임의의 지연을 추가하는 것일 수 있습니다.

모든 셀에서 실행자를 공유해야 할까요?

두 가지 옵션이 있으며, 어떤 것이 더 쉬울지 결정해야 합니다:

  1. 실행자 등록 및 대기열 테이블을 분해하고 모든 셀 간에 공유합니다. 이것은 확장 가능성에 영향을 미칠 수 있으며, 이는 그룹/프로젝트 실행자를 포함할지 여부도 고려해야 합니다. 왜냐하면 이러한 테이블은 규모에 대한 우려가 있기 때문입니다.
  2. 실행자는 셀당 등록되며, 아마도 모든 셀에 대한 별도의 실행자 집단이 있거나 많은 셀에 동일한 실행자를 등록하는 것이고, 이것은 대기열에 영향을 미칠 수 있습니다.

모든 셀 간에 충돌할 수 없는 것들을 위해 고유 ID를 보장하는 방법은 무엇인가요?

이 프로젝트는 적어도 네임스페이스와 프로젝트가 모든 셀에서 고유한 ID를 가지고 있어야 한다는 가정을 전제로 합니다. 그러므로 고유한 ID를 보장하기 위해서는 새로운 솔루션이 필요할 것입니다. 아마도 다른 테이블에서도 고유한 ID가 필요하고, GraphQL 및 기타 API 라우팅 및 기타 설계 목표에 따라 요청을 라우팅하기 위해 기본 키를 모든 테이블에서 고유하게 해야 한다는 것이 밝혀질 수도 있습니다.