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.
Status Authors Coach DRIs Owning Stage Created
accepted @grzesiek @marshall007 @fabiopitino @hswimelar @andrewn @sgoldstein devops enablement 2022-09-08

다음 요금 제한 아키텍처

요약

합리적인 응용프로그램 제한을 도입하는 것은 어떤 SaaS 플랫폼의 확장 전략에서 매우 중요한 단계입니다. SaaS 플랫폼의 사용자가 많을수록 합리적인 속도 제한과 정책 시행을 도입하는 것이 더욱 중요하며, 이는 가용성 목표를 달성하고 사용자에게 더 나은 환경을 제공하며 플랫폼을 성공적으로 사용할 수 있도록 돕습니다.

이는 특히 GitLab.com의 경우에 매우 중요합니다. 저희의 목표는 합리적이고 투명한 응용프로그램 제한을 시행하여 이를 책임 있는 사용의 정의로 삼아 우리의 가용성과 사용자 만족도를 원하는 수준으로 유지하는 데 도움이 되기를 바랍니다.

우리는 이미 많은 해동안 다양한 응용프로그램 제한을 도입해왔지만, 이를 하는 일관된 전략이 없었습니다. 우리가 지금 하려는 것은 엔지니어와 제품 관리자들이 사용하는 일관된 프레임워크를 구축하여 응용프로그램 스택 전체에서 한곳에 정의하고 노출하며 제한과 정책을 시행하는 것입니다.

제한을 정의하는데 일관성이 없고, 사용자나 지원 엔지니어, 위성 서비스에 노출시키는 것이 어려웠기 때문에 우리는 생산성에 부정적인 영향을 끼쳤으며, 새로운 제한을 도입하는 데 어려움을 겪었으며 결국 우리를 응용프로그램 스택의 모든 계층에서 책임 있는 사용을 시행하지 못하게 만들었습니다.

이 설계안은 우리의 제한을 종합하고 다음 요금 제한 및 정책 시행 아키텍처의 비전을 설명하기 위해 작성되었습니다.

목표

다음 아키텍처를 구현하여 요금 제한 및 정책을 정의합니다.

도전과제

  • 응용프로그램 제한을 정의하는 많은 방법이 있습니다. 그리고 그것이 다양한 곳에 있습니다.
  • 요청에 적용된 제한을 이해하는 것이 어렵습니다.
  • 새로운 제한을 도입하는 것은 어렵고, 정책을 정의하는 것은 더욱 어렵습니다.
  • 정의된 제한을 찾는 것은 코드베이스 감사를 수행해야 합니다.
  • 우리는 사용자, 지원 엔지니어 및 위성 서비스에 제한을 노출시키는 좋은 방법이 없습니다.
  • 우리는 파이프라인 검증 서비스, 바운서, 왓치타워, 클라우드플레어, HAProxy 등을 통해 다양한 정책을 불투명한 외부 시스템으로 시행합니다.
  • 제한 정의에 일관된 방법이 없습니다.
  • 사용자가 제한 임계값에 접근하는 것을 이해하는 것이 어렵습니다.
  • 사용자가 임계값에 접근할 때 자동으로 알리는 방법이 없습니다.
  • 네임스페이스/프로젝트/사용자/고객의 제한을 변경하는 단일 방법이 없습니다.
  • 리얼타임 지표를 통해 제한을 모니터링하는 단일 방법이 없습니다.
  • 계층적 제한 구성을 위한 프레임워크가 없습니다(인스턴스/네임스페이스/서브그룹/프로젝트).
  • 우리는 어떤 특별한 SaaS 고객을 위해 요금 제한 시스템을 비활성화시킬 수 있지만, 이는 동일한 고객에 대한 위험을 증가시킵니다. 우리는 대신 더 높은 제한을 설정할 수 있어야 합니다.

기회

우리는 새로운 프레임워크를 구축하여 정의, 할당량 및 정책을 더 쉽게 정의하고, 강화/조정되면서 강력한 모니터링 기능을 통해 제어된 방식으로 도입하는 것을 원합니다.

  1. GitLab Rails에 제한을 정의하고 강제하는 프레임워크를 구축합니다.
  2. 위성 서비스에서 제한을 사용하고 노출시키기 위한 API를 구축합니다.
  3. 이 프레임워크의 일부분을 별도의 GitLab Limits 서비스로 추출합니다.

가장 중요한 기회는 여러 수준에서 발생하는 통합입니다.

  1. GitLab Rails에서 사용하는 응용프로그램 제한 도구 통합.
  2. 응용프로그램 제한을 추가하고 관리하는 프로세스 통합.
  3. 제한과 재정의의 계층적 연쇄 행동 통합.
  4. 응용프로그램 스택 전체에서 사용하는 응용프로그램 제한 도구 통합.
  5. 회사 전반에서 사용하는 정책 시행 도구 통합.

이를 통해 우리는 또 다른 기회를 발견할 것입니다: 새로운 프레임워크/도구를 GitLab 기능으로 제공하여 이러한 통합 혜택을 우리의 사용자, 고객 및 전체 커뮤니티 관객에게 제공하는 것입니다.

제한, 할당량 및 정책

본 문서는 GitLab.com의 다음 요금 제한 아키텍처를 구축하기 위한 기술적 비전을 설명합니다. 이를 “다음 요금 제한 아키텍처”라고 하지만, 이는 심리적으로 손쉬워 사용하는 것이며, 실제로 우리는 속도 제한 뿐만 아니라 할당량과 정책을 관리하기 쉽게 만드는 더 좋은 프레임워크를 구축하고자 합니다.

아래에서 우리는 제한, 할당량 및 정책을 어떻게 이해하는지에 대한 간단한 정의를 찾을 수 있습니다.

  • 제한: 응용프로그램 사용에 대한 제약 조건으로 일반적으로 성능, 안정성 및 보안 문제를 완화하기 위해 사용됩니다.
    • 예시: 주어진 IP 주소당 API 호출/초
    • 예시: 특정 사용자의 git clone 이벤트/분
    • 예시: 최대 아티팩트 업로드 크기 1GB
  • 할당량: 청구 주기 동안 네임스페이스 전체에 걸쳐 집계된 응용프로그램 사용에 대한 전체 제약 조건.
    • 예시: 네임스페이스 당 한달 동안 400분의 컴퓨팅 시간
    • 예시: 네임스페이스 당 한달 동안 10GB 전송
  • 정책: 응용프로그램 코드에서 분리된 비즈니스 로직의 표현. 분리된 정책 정의는 로직을 여러 서비스 간에 공유하고/또는 런타임에서 새로운 버전을 릴리스하지 않고 사용할 수 있게 합니다.
    • 예시: JWT를 해석하고 확인하여 JWT 범위 및 클레임에 기반하여 사용자의 리소스 접근 여부를 결정합니다.
    • 예시: 그룹 수준 제약에 따른 액세스 거부(Such as IP 허용 목록, SSO 및 2FA)를 모든 서비스에서 시행합니다.

기술적으로 모든 이것들은 제한입니다. 왜냐하면 속도 제한이 여전히 “제한”이며, 할당량은 일반적으로 비즈니스 제한이고, 정책은 특정 규칙을 시행하기 위해 응용프로그램을 사용하는 것을 제한합니다. 이 문서에서 “제한”이라고 말할 때 기업, 가용성 및 보안을 보호하기 위해 정의된 제한을 의미합니다.

제한 사항을 정의하고 강제하는 프레임워크

우리는 먼저 GitLab Rails 프로젝트 컨텍스트에서 애플리케이션 제한 사항을 일관되고 확립된 방식으로 보다 구체적으로 정의하고 강제할 수 있는 새로운 프레임워크를 구축하려고 합니다. 이를 위해 구조화된 방법으로 제한을 정의하는 새로운 추상화를 구축하고(아마도 YAML 또는 Cue 형식을 사용) 그런 다음 애플리케이션 자체에서 제한을 어떻게 사용할지 엔지니어들에게 알려줄 필요가 있습니다.

우리는 이미 응용 프로그램에 많은 제한이 정의되어 있으며, 이를 사용하여 어떻게 제한을 정의하고 사용하고 강제할지를 통합하는 합리적인 추상화를 찾을 수 있습니다.

여기에 새로운 Ruby 라이브러리(우리는 LabKit에 추가할 수 있음)를 구축하여 엔지니어가 특정 제한이 초과되었는지 여부를 확인하는 것이 간단해지도록 할 계획입니다.

name: my_limit_name
actors: user
context: project, group, pipeline
type: rate / second
group: pipeline::execution
limits:
  warn: 2B / day
  soft: 100k / s
  hard: 500k / s
Gitlab::Limits::RateThreshold.enforce(:my_limit_name) do |threshold|
  actor   = current_user
  context = current_project

  threshold.available do |limit|
    # ...
  end

  threshold.approaching do |limit|
    # ...
  end

  threshold.exceeded do |limit|
    # ...
  end
end

위의 예에서 YAML에 my_limit_name이 정의된 경우, 엔지니어는 현재 상태를 확인하고 사용 과거 및 리소스 소비에 따라 적절한 코드 블록을 실행할 수 있습니다.

우리가 기본적으로 구축하고 지원하려는 것들:

  1. 얼마나 자주 제한이 적용되는지 보여주는 포괄적인 대시보드.
  2. 제한을 넘을 위험에 대한 통지.
  3. 제한 정의가 적절하게 강제되는지를 자동으로 확인.
  4. 시간 제한 / 리소스 당 수 등 다양한 유형의 제한.
  5. 계획 / 네임스페이스별로 제한을 재정의하기 쉽게 하는 패널.
  6. Kibana에서 적용된 제한을 노출하는 로깅.
  7. 자동으로 생성된 문서 페이지에서 모든 제한을 설명하는 문서.

사용된 리소스를 기반으로 한 속도 제한 지원

우리의 속도 제한 시스템의 한 문제점은 값이 정적이며(예: 분당 100개 요청), 연산의 복잡성이나 사용된 리소스와는 무관하다는 것입니다. 예를 들어:

  • 간단한 리소스를 가져오기 위해 분당 100개 요청을 보내는 것은 CI 파이프라인을 만드는 것과는 매우 다른 영향을 줄 수 있습니다.
  • 각 파이프라인 생성 작업은 만들어지는 파이프라인에 따라 매우 다르게 작동할 수 있습니다(작은 MR 파이프라인 대 대규모 예약 파이프라인).
  • 1000 오프셋 이후에 리소스 페이징을 하는 것은 데이터베이스에 대해 점점 비싸질 수 있습니다.

우리는 일부 속도 제한을 ‘연산 점수 / 기간’으로 정의할 수 있도록 하는 것이 좋을 것입니다. 여기서 연산 점수는 주어진 기간(예: 1분) 내에서 누적된 밀리초를 계산합니다.

이렇게 하면 사용자가 비용이 많이 드는 요청을 보낼 경우 속도 제한에 더 일찍 도달할 수 있습니다.

제한 및 정책 노출을 위한 API

애플리케이션 제한을 정의하기 위한 일관된 방법을 확립하면 사용자, 고객 및 기타 위성 서비스에게 이를 노출할 수 있는 몇 가지 API 엔드포인트를 구축할 수 있습니다.

사용자는 API에게 그들을 위해 설정된 제한 / 한계에 대해 묻거나, 얼마나 자주 그 한계를 넘는지, 그것이 사업에 미칠 영향에 대해 물을 수 있습니다. 이러한 투명성은 사용자들이 GitLab의 고객 성공 팀에 대해 그들의 요구사항을 전달할 수 있도록 도와줄 수 있으며, 우리는 주어진 시점에서 책임있는 사용이 어떻게 정의되는지를 전달할 수 있을 것입니다.

GitLab의 아키텍처로 인해 대부분의 경우 GitLab Rails 응용 프로그램은 중앙 엔터프라이즈 서비스 버스(ESB)처럼 작동하며 몇 가지 위성 서비스가 이와 통신합니다. 컨테이너 레지스트리, GitLab 러너, Gitaly, Workhorse, KAS와 같은 서비스들은 이러한 API를 사용하여 강제해야 할 애플리케이션 제한 집합을 수신할 수 있습니다. 이렇게 하면 우리는 모든 제한을 한곳에서 정의할 수 있게 될 것입니다.

그러나 단계적으로 트래픽이 증가할 때 GitLab Rails에 추가적인 부하를 줄 수 있는 부정적인 피드백 루프를 피해야 합니다. 이는 대량 트래픽으로 인해 처음에는 레일 응용 프로그램에 부수적인 영향을 줄 수 있는 큰 고객이 새로운 자동화를 시작하거나 서비스 거부 공격일 수 있습니다. 이러한 경우에는 추가 트래픽이 GitLab Rails에 도달하고 이어서 다른 위성 서비스들에도 도달할 수 있습니다. 그런 다음 위성 서비스들은 레일에게 새로운 요청율 또는 이러한 API 엔드포인트에서 레일 측의 요청률 또는 리소스 소비 증가에 대한 사용 지침 / 정책을 얻기 위해 상의할 수 있습니다. 이는 레일 응용 프로그램에 추가적인 부하를 줄 수 있으며 결국 성능을 더욱 저하시킬 수 있습니다. 따라서 이 문제를 피하기 위해 트래픽 양에 따라 API 엔드포인트를 별도의 서비스로 추출할 필요가 있습니다(아래 섹션 참조). 또는 레일에서 이러한 엔드포인트를 유지해도 되지만, 증가된 트래픽이 요청률 증가로 변환되지 않거나 레일 측에서 이러한 API 엔드포인트에 대한 리소스 소비 증가로 변환되지 않는 경우에는 레일에 유지할 수 있습니다.

Decoupled Limits Service

언젠가는 메타데이터를 저장하고 모든 카운터와 상태를 노출하며 API를 제공하는 stateful 백엔드를 추출하는 시기가 왔을지도 모릅니다. 하지만 Rail 밖으로 이러한 분리된 한계 서비스를 추출할지에 대한 결정은 아직 내리기 어렵습니다. 왜냐하면 더 많은 개념 증명 작업과 구체적인 반복이 필요하며, 우리에게 그것을 언제, 어떻게 해야 하는지 더 잘 알려주기 위해 진화 아키텍처 실천에 따라야 할 것입니다.

이 청사진을 진화시키면서, 우리는 이 서비스가 어떻게 보이는지에 대한 우리의 발견과 통찰을 이 문서의 이 섹션에 기록할 것입니다.

GitLab 정책 서비스

면책 조항: GitLab 정책 서비스를 추출하는 것은 현재 이 청사진을 구현하는 주요 작업을 중심으로 한 워크스트림의 범위를 벗어날 수 있습니다.

모든 한계를 YAML로 쉽게 설명할 수 있는 것은 아닙니다. 좀 더 복잡한 정책들이 있으며, 이러한 정책들을 시행하는 데 조금 더 정교한 접근과 선언적 프로그래밍 언어가 필요합니다. 그 중 한 예로 Rego 언어가 있습니다. 이는 OPA - Open Policy Agent에서 정책을 정의하는 표준화된 방법입니다. GitLab에서 이미 OPA를 일부 부서에서 사용하고 있습니다. 우리는 GitLab 내부에서 사용 중인 도구를 통합하고, Next Rate Limiting Architecture를 제품 자체의 일부로 변형하는 데 추가적인 통합이 필요하다고 생각합니다.

지금, 이미 우리는 파이프라인이 생성될 수 있는지 여부를 결정하기 위해 사용하고 있는 정책 서비스가 있습니다. 파이프라인 유효성 검사 서비스에 정의된 많은 정책들이 있습니다. 이를 일반적인 용도의 GitLab 정책 서비스 / GitLab 정책 에이전트로 변환하는 데 상당한 기회가 있습니다.

파이프라인 유효성 검사 서비스를 일반적인 GitLab 정책 서비스로 범용화할 경우 몇 가지 흥미로운 이점이 있을 수 있습니다:

  1. 회사 전반에 걸쳐 도구를 통합하여 효율성을 향상시킵니다.
  2. 정책 서비스를 사용하여 정책을 해결하기 위해 GitLab Rails 한계 프레임워크를 통합합니다.
  3. YAML에서 복잡한 정책을 정의하고 루비에서 그것을 평가하는 것을 간단하게하십시오.
  4. GraphQL 쿼리 실행 비용 산정을 사용하는 정책을 빌드합니다.
  5. “계층적 한계” 구조가 필요하지 않은 정책을 해결하는 것을 더 쉽게합니다.
  6. GitLab 정책 서비스를 제품의 일부로 통합합니다.

우리는 GitLab 정책 서비스를 사용하여 이러한 계층 구조에 대해 알 필요가 없는 정책을 정의하는 장소로 사용할 것으로 예상합니다. 이러한 정책은 IP 주소 허용 목록, 스팸 확인, 구성 유효성 검증 등과 같이 이 계층 구조를 필요로하지 않는 한계가 있습니다.

우리는 “정책”을 상태 없는, 함수 스타일의 한계로 정의했습니다. 그것은 입력 매개 변수를 사용하고 true 또는 false 중 하나를 평가합니다. 이를 평가하기 위해 전역 카운터나 다른 변동성이있는 전역 상태가 필요하지 않아야합니다. 여전히 전역으로 정의된 규칙 / 구성이 필요할 수는 있지만, 이 상태는 평가 용량 한계를 평가하기 위한 메가바이트 소비 또는 평가에 사용되는 카운터와 같은 방식으로 변동하지는 않습니다.

내부 및 외부에서 사용하는 정책

GitLab 정책 서비스는 두 가지 다른 방식으로 사용될 수 있습니다:

  1. Rails 한계 프레임워크는 내부에서 적용되는 정책의 소스로 사용합니다.
  2. 정책 서비스 기능은 사용자가 정의하는 정책을 저장하는 백엔드로 사용됩니다.

이러한 두 가지 약간 다른 사용 사례가 있습니다. 첫 번째는 GitLab 인스턴스(GitLab.com 또는 Self-Managed 인스턴스)의 안정성/가용성을 보장하기 위해 내부에서 정의된 정책을 사용하는 것입니다. 두 번째 사용 사례는 사용자가 위에 구축할 수 있도록하는 기능으로 GitLab 정책 서비스를 만드는 것입니다.

두 사용 사례는 모두 유효하지만, 이에 대한 기술적인 결정을 내려야 할 필요가 있습니다. 두 가지를 하나의 서비스로 구현하기로 결정한다 해도, 두 가지 간의 강력한 경계를 그어야 할 것입니다.

한계 서비스 추출된 한계 서비스에 설명된 것과 동일한 원칙이 적용될 수 있습니다.

두 가지 한계 / 정책 서비스

GitLab 정책 서비스와 분리된 한계 서비스가 사실상 동일한 것일 수 있습니다. 그러나 아직 예측할 수없는 구현 세부 정보에 따라 이에 대한 결정은 후속 반복의 피드백에 따라야 합니다.

계층적 한계

GitLab 애플리케이션은 사용자, 프로젝트, 그룹 및 이름 공간을 계층 구조적으로 집계합니다. 이 계층 구조는 권한을 관리하고, 워크플로를 최적화하며, 사용자 및 고객이 관련 프로젝트, 저장소 및 기타 아티팩트를 함께 저장할 수 있도록 설계되었습니다.

기존 권한 구조 내에서 한계가 어떻게 적용, 시행 및 재정의되는지를 이해하는 데 필요한 인지적 부하를 줄이는 것이 중요합니다. 특정 요청에 대한 적용 가능한 한계와 임계치를 결정하는 우리의 애플리케이션이 간단하고 이해하기 쉬운 공식을 구축할 필요가 있을 수 있습니다.

GitLab은 모든 작업에 대한 기본 한계를 읽고, 구성된 모든 재정의를 선택하며, 구성된 가장 높은 우선순위의 한계를 선택합니다. 각 재정의에 대해 우선순위를 명시적으로 구성해야하며, 기본 한계의 우선순위는 100입니다.

일반적으로 한계 관리를 단순화 할 수 있는 한 가지 방법은 다음과 같습니다:

  1. YAML 파일에 기본 한계/임계치를 정의하고 기본 우선순위 100을 부여합니다.
  2. API를 통해 한계를 재정의 할 수 있도록하고, 재정의를 데이터베이스에 저장합니다.
  3. 각 한계/임계치 재정의는 제공된 정수 우선순위 값을 가져야 합니다.
  4. 특정 사용자를 위해 적용 가능한 한계를 사용자가 공개할 API를 빌드합니다.
  5. 비표준 한계/재정의를 사용하는 사용자를 보여주는 대시 보드를 빌드합니다.
  6. 이러한 비표준 한계가 사용될 때 Kibana에서 표시하는 가시성을 빌드합니다.

위의 점들은 우선 순위 점수(또는 한계에 대한 Z-인덱스)를 사용하는 아이디어를 나타냅니다. 하지만 우선 순위가 더 낮은 한계가 항상 계층 구조에서 더 높게 정의된 한계를 재정의 함을 설명하는 것과 같이, 더 나은 해결 방법이 있을 수 있습니다. 적절한 솔루션을 선택하기 위해서는 신중한 연구가 필요할 것입니다.

원칙

  1. 밀접하게 결합된 방식으로 속도 제한 프레임워크를 구축하는 것을 피하려고 노력하세요.
  2. API를 구축하여 쉽게 별도 서비스로 추출할 수 있는 방식으로 응용 프로그램 제한을 설정하세요.
  3. 레일즈 응용 프로그램과 독립적인 방식으로 응용 프로그램 제한 정의를 구축하세요.
  4. 프로그래밍 언어 간에 일관된 동작과 결과를 생성하는 도구를 구축하세요.
  5. 새로운 프레임워크를 확장할 수 있도록 자체 관리형 관리자가 제한을 사용자 정의할 수 있도록 구축하세요.
  6. SaaS 및 자체 관리형 코드베이스 전체에서 일관된 기능과 동작 유지하세요.
  7. 계층 제한으로 인한 인지 부하를 염두에 두고, 이를 줄이도록 노력하세요.

단계 및 반복

  1. 현재 가장 중요한 응용프로그램 제한의 예제 모음 작성 (소유 팀)
    • 소유 팀(단계 그룹과 협력)이 오늘날 레일즈에서 사용되는 가장 중요한 응용프로그램 제한 목록을 작성합니다.
  2. 레일즈에서 속도 제한 프레임워크 구현 (소유 팀)
    • 1단계에서 수집한 데이터를 기반으로 한 속도 제한 추상화를 삼각측량합니다.
    • 제한을 위한 YAML 모델 개발
    • Rails SDK 구축
    • 새로운 속도 제한 SDK 사용 예제를 생성합니다.
  3. 레일즈 SDK의 팀 전체 사용 (단계 그룹)
    • 각각의 단계 그룹은 2단계에서 구축된 SDK를 사용하여 새로운 제한과 정책을 시작합니다.
    • 단계 그룹은 SDK로 역사적인 임시 제한 구현을 대체하기 시작합니다.
    • (소유 팀) 대체 작업의 진행 상황을 모니터링하고 관찰하는 수단을 제공합니다. 이상적으로는 그룹 수준의 찬성을 유도하기 위해 feature_category 수준으로 세분화됩니다.
  4. 위성 서비스가 속도 제한 프레임워크를 사용하도록 활성화 (소유 팀)
    • 4단계의 목표가 가장 잘 충족되는지 여부를 결정하세요:
      • 레일즈 속도 제한 서비스를 분리된 서비스로 추출하기
      • 예를 들어, Redis와 같은 백엔드를 사용하는 별도의 Go 라이브러리 구현하기.
  5. 위성 서비스용 SDK (소유 팀)
    • Go SDK 구축
    • 새로운 속도 제한 SDK 사용 예제를 생성합니다.
  6. 위성 서비스 팀 전체에 대한 전개 (단계 그룹)
    • 각 단계 그룹은 5단계에서 구축된 SDK를 사용하여 새로운 제한과 정책을 시작합니다.
    • 단계 그룹은 SDK로 역사적인 임시 제한 구현을 대체하기 시작합니다.

상태

의견 요청 중

일정

  • 2022-04-27: 속도 제한 아키텍처 워킹 그룹 시작.
  • 2022-06-07: 워킹 그룹 구성원들이 다음 속도 제한 아키텍처를 위한 기술 제안을 시작했습니다. (https://gitlab.com/gitlab-org/gitlab/-/issues/364524)
  • 2022-06-15: 워킹 그룹 구성원들이 제출한 제안서를 점수 매기기 시작했습니다.
  • 2022-07-06: 통합 제안이 제출되었습니다.
  • 2022-07-12: 아키텍처 진화 워크플로에 따라 설계 문서 작업 시작.
  • 2022-09-08: 청사진의 초기 버전이 병합되었습니다.