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
accepted @grzesiek @marshall007 @fabiopitino @hswimelar @andrewn @sgoldstein devops enablement 2022-09-08

다음 속도 제한 아키텍처

개요

합리적인 응용 프로그램 제한 도입은 SaaS 플랫폼 확장 전략에서 매우 중요한 단계입니다. SaaS 플랫폼이 더 많은 사용자를 보유할수록 합리적인 속도 제한과 정책 강제는 가능한 만들어지며, 이는 가용성 목표를 달성하고 사용자들을 위한 노이즈 이웃 문제를 줄이며 플랫폼을 성공적으로 사용할 수 있도록 도와줍니다.

특히 GitLab.com의 경우, 저희 목표는 합리적이고 투명한 응용 프로그램 제한 강제 전략을 소개하여 책임 있는 사용의 정의가되도록 하여 원하는 수준의 가용성과 사용자 만족도를 유지하는 데 도움을 주는 것입니다.

우리는 이미 여러 해 동안 다양한 응용 프로그램 제한을 소개해 왔지만, 이를 집행하기 위한 일관된 전략은 없었습니다. 지금 구축하려는 것은 엔지니어와 제품 관리자들에 의해 사용되는 일관된 프레임워크로 모든 응용 프로그램 스택에서 제한과 정책을 정의, 노출 및 집행하는 것입니다.

억지로 제한을 정의하는 일관성 부족, 사용자에게 노출하지 못함, 지원 엔지니어와 위성 서비스에 제한적인 영향을 미치는 것은 프로덕션성을 저해하며 새로운 제한을 도입하기 어렵게 만들고, 결과적으로 응용 프로그램 스택의 모든 계층에 책임 있는 사용을 집행할 수 없게 만듭니다.

이 설계도는 우리의 제한을 통합하고 다음 속도 제한 및 정책 집행 아키텍처의 Vision을 설명하기 위해 작성되었습니다.

Goals

다음 아키텍처를 구현하여 속도 제한과 정책 정의를 목표로 합니다.

Challenges

  • 여러 가지 방법으로 응용 프로그램 제한을 정의하는 방법이 많습니다.
  • 요청에 적용된 제한을 이해하기 어렵습니다.
  • 새로운 제한을 도입하기 어렵고 정책을 정의하는 것은 더 어렵습니다.
  • 어떤 제한이 정의되었는지 파악하기 위해서 코드베이스 감사를 수행해야 합니다.
  • 등록 기능과 같은 위성 서비스에 제한을 노출 할 수 있는 좋은 방법이 없습니다.
  • 우리는 외부 불투명 시스템을 통해 다양한 정책을 시행합니다(Pipeline Validation Service, Bouncer, Watchtower, Cloudflare, HAProxy).
  • 제한을 정의하는 표준화된 방식이 없습니다.
  • 사용자가 제한 임계값에 접근하는지 이해하는 것이 어렵습니다.
  • 사용자가 임계값에 접근할 위험이있을 때 자동으로 사용자에게 알릴 수 있는 방법이 없습니다.
  • Namespace / 프로젝트 / 사용자 / 고객별로 제한을 변경할 수있는 단일 방법이 없습니다.
  • 실시간으로 메트릭을 통해 제한을 모니터링하는 단일 방법이 없습니다.
  • 계층별 제한 구성에 대한 프레임워크가 없습니다(인스턴스 / 네임스페이스 / 하위 그룹 / 프로젝트).
  • 일부 주요 SaaS 고객에 대한 속도 제한을 비활성화 할 수 있지만, 동일한 고객에 대한 위험을 증가시킵니다. 대신 더 높은 제한을 설정할 수 있어야합니다.

Opportunity

우리는 새로운 프레임워크를 구축하여 제한, 할당량 및 정책을 정의하고 집행/조절하는 것을 보다 간단하게 만들고 견고한 모니터링 기능을 통해 이를 가능케 하고자 합니다.

  1. GitLab Rails에 제한을 정의하고 집행하기 위한 다음 아키텍처를 구축합니다.
  2. 위성 서비스에서 한도를 사용하고 사용자에게 노출하기 위한 API를 구축합니다.
  3. 이 프레임워크의 일부분을 전용 GitLab 제한 서비스로 추출합니다.

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

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

이후에 새로운 프레임워크/도구를 GitLab 기능으로 출시하여 사용자, 고객 및 광범위한 커뮤니티 청중에게 이러한 통합 혜택을 제공할 수 있는 기능들을 공개할 것입니다.

제한, 할당량 및 정책

이 문서는 GitLab.com을위한 다음 속도 제한 아키텍처를 구축하기 위한 기술적 비전을 설명하는 것을 목표로하며 “다음 속도 제한 아키텍쳐”라고 언급하고 있지만 실제로는 우리가 속도 제한 뿐 아니라 할당량 및 정책을 관리하기 쉽게 할 수있는 더 나은 프레임워크를 구축하고자합니다.

아래에서는 우리가 제한, 할당량 및 정책에 대한 이해를 간략히 설명하고 있습니다.

  • 제한: 성능, 안정성 및 보안에 대한 위험을 완화하기 위해 특히 응용 프로그램 사용에 대한 제약 조건.
    • 예시: 특정 IP 주소의 API 호출/초
    • 예시: 특정 사용자의 git clone 이벤트/분
    • 예시: 1GB의 최대 artifact 업로드 크기
  • 할당량: 청구주기 동안 네임스페이스 전체에서 집계되는 애플리케이션 사용에 대한 전역 제한.
    • 예시: 월별 네임스페이스 당 400개의 컴퓨팅 분
    • 예시: 월별 네임스페이스 당 10GB의 전송
  • 정책: 응용 프로그램 코드에서 분리 된 비즈니스 로직의 표현. 분리 된 정책 정의를 통해 로직을 여러 서비스 사이에서 공유하고 런타임에서 “핫-로드” 할 수 있습니다.
    • 예시: JWT 디코딩 및 확인, JWT 범위 및 클레임에 기반하여 사용자가 특정 리소스에 액세스 할 수 있는지 여부 결정
    • 예시: IP 허용 디렉터리, SSO 및 2FA와 같은 그룹 수준 제약에 따라 모든 서비스에 대한 액세스 거부

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

제한을 정의하고 집행하기 위한 프레임워크

먼저 새로운 프레임워크를 구축하여 GitLab Rails 프로젝트 맥락에서 응용 프로그램 제한을 정의하고 집행할 수 있도록 할 것입니다. 이를 위해 우리는 제한이라는 것을 어떻게 구조적으로 정의해야 하는지 엔지니어에게 알려줄 새로운 추상화를 구축할 필요가 있습니다(아마도 YAML 또는 Cue 형식을 사용하여). 그리고 이후에 응용 프로그램 자체에서 제한을 사용하고 집행하는 방법에 대해 말해주는 새로운 추상화를 만들어야 할 것입니다.

우리는 이미 응용 프로그램에 많은 제한이 정의되어 있으며, 우리는 이를 사용하여 어떻게 제한을 정의, 사용 및 집행할 수 있도록 하는 합리적 추상화를 찾을 수 있을 것입니다.

우리는 여기에 간단한 루비 라이브러리를 구축하고자 합니다(우리는 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의 오프셋 이후 리소스 분할 수행은 데이터베이스에서 점점 비용이 발생하기 시작합니다.

우리는 일부 속도 제한을 “점수 계산 / 기간”으로 정의할 수있게 해야합니다. 여기서 “점수 계산”으로는 주어진 기간동안 누적된 밀리초를 계산함으로써(실행된 모든 요청 및 수행 중인 모든 요청을 위해) 더 쉽게 속도 제한을 넘을 수도 있습니다.

이렇게하면 사용자가 비용이 많이 드는 요청을 보내게되면 속도 제한에 먼저 도달할 가능성이 높아집니다.

제한 및 정책을 노출하는 API

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

사용자는 자신을 위해 설정된 제한/임계값에 대해 API에 문의할 수 있으며, 이를 얼마나 자주 초과하고 있으며, 이로써 그들의 비즈니스에 미치는 영향을 알 수 있게 됩니다. 이러한 투명성은 GitLab의 고객 성공 팀과의 의사 소통을 돕는 데 도움이 되고, 우리는 현재 상태에서 책임 있는 사용이 어떻게 정의되는지 알릴 수 있을 것입니다.

GitLab 아키텍처의 구축 방식으로 인해 대부분의 경우, GitLab Rails 애플리케이션은 중앙 엔터프라이즈 서비스 버스 (ESB)처럼 작동하며, 이와 통신하는 몇 가지 위성 서비스가 있습니다. 컨테이너 레지스트리, GitLab 러너, Gitaly, Workhorse, KAS와 같은 서비스들은 이러한 API를 활용하여 적용해야 할 일련의 애플리케이션 제한을 받을 수 있을 것입니다. 이를 통해 우리는 모든 제한을 하나의 장소에서 정의할 수 있게 될 것입니다.

그러나 급격한 사용 증가가 발생할 때 GitLab Rails에 추가적인 부하를 주는 부정적인 피드백 루프를 피해야 합니다. 예를 들어 새로운 자동화를 시작하는 대형 고객이 우리의 API를 횡단하거나 서비스 거부 공격이 발생할 수 있습니다. 이러한 경우에 추가 트래픽은 GitLab Rails에 도달할 것이며 결과적으로 다른 위성 서비스들에도 도달하게 될 것입니다. 그럼 위성 서비스들은 다시 Rails를 상담하여 증가된 트래픽에 대한 새로운 지침/정책을 얻어야 할 수 있습니다. 이는 Rails 애플리케이션에 추가적인 부하를 주게 되어 성능을 더욱 저하시킬 수 있습니다. 이 문제를 피하기 위해 이러한 엔드포인트를 별도의 서비스로 추출해야 할 필요가 있습니다 (아래 섹션 참조)만, 이러한 엔드포인트의 요청률이 들어오는 트래픽의 양에 따라 좌우된다면 Rails에 유지하는 것이 더 나을 수 있습니다.

분리된 제한 서비스

언젠가는 제한에 관한 메타데이터를 저장하고 필요한 모든 카운터와 상태를 관리하며 API를 노출하는 상태를 유지하는 백엔드를 Rails에서 분리하는 것이 시기를 결정해야 할 필요가 있을 것입니다.

그러나 현재 시점에서는 이와 관련된 증명-of-concept 작업과 구체적인 반복 작업들을 더 배포해야 하므로 분리된 제한 서비스를 추출할 지 여부를 결정할 수 없습니다. 우리는 이를 결정하기 위해 진화 아키텍처 관행에 의존할 것입니다.

이 설계를 발전시키면, 이 서비스가 어떻게 보여야 하는지에 대한 우리의 발견과 통찰을 이 문서의 이 섹션에 문서화할 것입니다.

GitLab 정책 서비스

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

모든 제한을 YAML로 쉽게 설명할 수 있는 것은 아닙니다. 더 복잡한 정책은 좀 더 정교한 접근 방식과 이를 강제하는 선언형 프로그래밍 언어가 필요할 수 있습니다. 이러한 언어 중 하나로 Rego 언어가 있습니다. 이는 OPA - Open Policy Agent에서 정책을 정의하는 표준 방법입니다. 우리는 이미 OPA를 일부 부서에서 사용하고 있습니다. 우리는 내부적으로 사용하는 도구를 통합할 뿐만 아니라 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 정책 서비스와 분리된 제한 서비스가 실제로 동일한 것일 수 있습니다. 그러나 이러한 서비스를 함께 Merge할 것인지에 대한 결정은 아직 예측할 수 없는 구현 세부 정보에 따라서 이루어져야 하며, 이러한 서비스들을 Merge하기로 결정하는 결정은 후속 반복의 피드백에 따라 결정되어야 할 것입니다.

계층적 제한

GitLab 애플리케이션은 사용자, 프로젝트, 그룹 및 네임스페이스를 계층적으로 모아두었습니다. 이 계층적 구조는 권한을 관리하고 작업 흐름을 최적화하며 사용자와 고객이 연관 프로젝트, 리포지터리 및 기타 아티팩트를 함께 저장할 수 있도록 설계되었습니다.

기존 권한 구조 내에서 제한이 어떻게 관리되고 적용되며 계층 구조 내에서 어떻게 재정의되는지에 대한 이해에 필요한 인지 부하를 줄이고자합니다. 주어진 요청과 주어진 액터에 적용할 제한과 임계값을 결정하기 위한 간단하고 이해하기 쉬운 공식을 만들어야 합니다.

GitLab은 모든 작업에 대한 기본 제한을 읽고 구성된 모든 재정의를 선택하며, 구성된 최우선 순위가있는 제한을 선택할 것입니다. 각 재정의에 대해 명시적으로 구성된 제한 우선 순위가 필요하며, 기본 제한의 우선 순위는 100입니다.

일반적으로 제한 관리를 단순화하는 한 가지 방법은 다음과 같습니다.

  1. 기본 제한 / 임계값을 YAML 파일에 정의하고 기본 우선 순위 100을 갖도록 함.
  2. API를 통해 재정의를 허용하고, 재정의를 데이터베이스에 저장해야 함.
  3. 모든 제한/임계값 재정의는 정수 우선 순위 값을 제공해야 함.
  4. 액터를 받아들이고 이에 적용되는 제한을 노출하는 API를 구축해야 함.
  5. 비표준 제한/재정의를 갖는 액터를 보여주는 대시보드를 구축해야 함.
  6. Kibana에서 사용되는 관측성을 표시하여 비표준 제한이 사용될 때 표시해야 함.

위의 내용은 우선 순위 점수 (또는 제한에 대한 Z-Index)를 사용하는 방법에 대한 아이디어를 나타내지만, 일반적으로 더 나은 해결책이 있을 수 있습니다. 예를 들어 낮은 제한은 계층 구조 상위에서 정의된 제한을 항상 재정의하도록 하는 것과 같은 적절한 해결책을 선택하는 것은 신중한 연구가 필요할 것입니다.

원칙

  1. 긴밀하게 결합된 방식으로 요율 제한 프레임워크를 구축하는 것을 피하려고 노력하십시오.
  2. 애플리케이션 제한 API를 별도의 서비스로 쉽게 추출할 수 있는 방식으로 구축하십시오.
  3. Rails 애플리케이션과 독립적인 방식으로 애플리케이션 제한 정의를 구축하십시오.
  4. 프로그래밍 언어 간에 일관된 동작과 결과를 생성하는 도구를 구축하십시오.
  5. 새로운 프레임워크를 구축하는 방식으로 Self-Managed형 관리자가 제한을 사용자 정의할 수 있도록 확장할 수 있도록 하십시오.
  6. SaaS 및 Self-Managed형 코드베이스 전체에서 일관된 기능과 동작을 유지하십시오.
  7. 계층 제한으로 인한 인지 부하에 주의를 기울이고, 이를 줄이도록 노력하십시오.

단계 및 반복

  1. 현재 가장 중요한 애플리케이션 제한의 예제를 컴파일하십시오 (소유 팀)
    • 소유 팀 (Stage 그룹과 협력)이 오늘날 Rails에서 가장 중요한 애플리케이션 제한의 디렉터리을 컴파일합니다.
  2. Rails에서 요율 제한 프레임워크를 구현하십시오 (소유 팀)
    • 제 1단계에서 수집한 데이터를 기반으로 요율 제한 추상화를 삼각측량합니다.
    • 제한에 대한 YAML 모델을 개발하십시오.
    • Rails SDK를 구축하십시오.
    • 새로운 요율 제한 SDK의 사용 예시를 만듭니다.
  3. Rails SDK의 팀 확산 (Stage 그룹)
    • 개별 stage 그룹이 제 2단계에서 구축된 SDK를 사용하여 새로운 제한 및 정책을 시작합니다.
    • Stage 그룹은 SDK로 구현된 기존의 임시 제한 구현을 대체하기 시작합니다.
    • (소유 팀) 대체 작업의 진행 상황을 모니터링하고 관찰할 방법을 제공합니다. 이상적으로는 feature_category 수준으로 분할하여 그룹 수준의 참여를 독려합니다.
  4. 위성 서비스가 요율 제한 프레임워크를 사용할 수 있도록 활성화하십시오 (소유 팀)
    • 제 4단계의 목표가 최상의 방법으로 달성되는지 여부를 결정합니다:
      • Rails 요율 제한 서비스를 분리된 서비스로 추출하는 것
      • 요율 제한을 위해 동일한 백엔드(예: Redis)를 사용하는 별도의 Go 라이브러리를 구현하는 것
  5. 위성 서비스용 SDK (소유 팀)
    • Go SDK 구축
    • 새로운 요율 제한 SDK의 사용 예시를 만듭니다.
  6. 위성 서비스용 팀 확산 (Stage 그룹)
    • 개별 stage 그룹은 제 5단계에서 구축된 SDK를 사용하여 새로운 제한 및 정책을 시작합니다.
    • Stage 그룹은 SDK로 구현된 기존의 임시 제한 구현을 대체하기 시작합니다.

상태

의견 요청 중입니다.

타임라인