Cloud Connector MVC: Self-Managed/GitLab Dedicated을 위한 코드 제안

이 문서에서는 코드 제안 AI 기능을 Self-Managed 및 GitLab Dedicated 고객에 제공하는 데 관여하는 시스템과 상호 작용을 제시합니다. 이것은 더 확장된 비전인 GitLab Cloud Connector(이전 “GitLab Plus”)에 대한 MVC 또는 초기 반복이 고려되었으며, 이를 통해 Self-Managed 고객이 우리가 운영하는 기능을 활용할 수 있게 될 것입니다.

이 문서의 맥락에서, 그리고 Cloud Connector 기능과 관련된 아키텍처에 대한 모든 토론에서 Cloud Connector는 시스템이 아니라는 것이 중요합니다. 이것은 Self-Managed 및 GitLab Dedicated 고객에게 기존 SaaS 전용 기능을 제공하는 모든 프로젝트를 위한 우산 용어입니다. 이 중 일부는 새로운 시스템을 통해 이러한 기능을 제공하므로, 솔루션을 공유할만큼 충분히 유사할 수 있지만, 이것이 Cloud Connector 우산 프로젝트에 포함된 모든 기능에 대해 확장되지는 않을 수 있습니다.

이 문서의 나머지 부분에서는 이 쓰기 시점에서 Self-Managed 및 GitLab Dedicated 사용 사례가 동일하기 때문에 구분하지 않습니다. 우리는 issue 410394에서 GitLab Dedicated를 위해 특별히 필요한 어떠한 탈도에 대해 탐구하고 있습니다.

문제 설명

Self-Managed 사용자를 위한 코드 제안은 GitLab SaaS와 거의 동일하게 작동합니다.

  1. 사용자:
    1. 자신의 IDE를 GitLab 인스턴스에 연결합니다.
    2. IDE를 통해 코드 제안을 요청합니다.
  2. GitLab 인스턴스:
    1. 사용자를 인증하고 인스턴스 내 권한 및 구성 확인을 수행합니다.
    2. JSON Web Token을 생성하여 AI 게이트웨이에서 사용합니다.
    3. AI 게이트웨이에게 이 액세스 토큰을 사용하여 요청을 전달합니다.
    4. 사용자의 IDE로 응답을 반환합니다.

Self-Managed 인스턴스의 맥락에서 우리가 해결해야 하는 고유한 도전 과제는 2b 단계입니다. GitLab SaaS의 경우 사용자가 코드 제안을 사용할 수 있는지에 대한 인스턴스 내 결정을 내릴 수 있고, 어떤 경우에든지 AI 게이트웨이에 연락할 수 있지만 Self-Managed 사용자의 경우에는 그렇지 않습니다. 왜냐하면 우리는 Self-Managed 인스턴스를 통제할 수 없기 때문에 해당 인스턴스가 이러한 토큰을 생성할 수 있는지 신뢰할 수 없기 때문입니다. Cloud Connector의 맥락에서, 이는 Self-Managed 인스턴스의 결제 이력을 고려하여 이 기능에 대한 자격이 있는지 확인하기 위해 Self-Managed 인스턴스의 결제 및 라이선스 데이터를 고려하는 권한 위임 시스템을 제공하는 것을 의미합니다.

이 솔루션의 아키텍처 및 데이터 흐름은 다음 섹션에서 기술되어 있습니다.

아키텍처

참고: 이 섹션은 Cloud Connector 맥락에서 코드 제안과 관련된 아키텍처적 세부 정보를 다룹니다. 보다 고수준의 개요는 AI 아키텍처에서 찾을 수 있습니다.

Cloud Connector를 위한 코드 제안 아키텍처는 미래에 유사한 기능을 구현하기 위한 청사진으로 기능합니다. 위에서 언급한 바와 같이 해결해야 할 주요 문제는 Self-Managed 인스턴스로부터 온 요청이 AI 게이트웨이에서 코드 제안을 받을 자격이 있는지 확인하는 것입니다. 이는 더 작은 두 가지 문제로 나뉠 수 있습니다.

  1. 인스턴스 자격. 코드 제안은 유료 기능입니다. 가입 상태의 진실의 원천지는 고객 포털(CustomersDot)입니다. 따라서 Self-Managed GitLab 인스턴스는 사용자를 대신하여 코드 제안을 요청할 자격이 있는지에 대한 결정에 CustomersDot을 포함해야 합니다.
  2. AI 게이트웨이 인증. AI 게이트웨이에는 Self-Managed 인스턴스나 사용자 ID의 개념이 없습니다. 따라서 AI 게이트웨이는 요청이 원래인 인스턴스인지를 확인해야 합니다. 이는 GitLab SaaS와 거의 동일하게 처리됩니다. 관련된 차이점은 나중에 다룹니다.

전체 흐름에는 세 가지 시스템이 개입되며, 각각 다음과 같은 책임이 있습니다.

  1. GitLab Rails 애플리케이션:
  2. CustomersDot:
    • 고객이 코드 제안을 구입할 수 있는 사용자 인터페이스 제공
    • GitLab 인스턴스가 CustomersDot과 동기화될 때, 사용 중인 코드 제안 구매 여부를 확인하고, 코드 제안 기능에 대한 범위가 있는 암호화된 서명된 JWT 액세스 토큰을 발행합니다. 이 메커니즘은 다른 Cloud Connector 기능에 대해 확장 가능합니다.
    • OIDC 공급자 역할을 수행하여 코드 제안 JWT를 유효성 검증하기 위해 필요한 공개 키를 제공하는 발견 및 구성 엔드포인트를 제공합니다. AI 게이트웨이는 이러한 엔드포인트를 호출합니다(아래 참조.)
  3. AI 게이트웨이:
    • GitLab 애플리케이션에서 온 코드 제안 요청 처리
    • CustomersDot OIDC 엔드포인트와 동기화하여 토큰 유효성 검증 키를 얻습니다.
    • GitLab 인스턴스와 AI 게이트웨이 간에 필요한 신뢰 관계를 확립하는 JWT 액세스 토큰을 이러한 키를 사용하여 유효성을 검사합니다. 이 게이트웨이는 우리가 호스팅하는 것입니다.

AI 게이트웨이의 관점에서 모든 요청은 동등합니다. 액세스 토큰이 인증될 수 있다면, 요청은 성공할 것입니다. 이것은 GitLab SaaS나 Self-Managed 사용자가 하든간에 동일합니다.

다음 다이어그램은 이러한 시스템이 고수준에서 상호 작용하는 방식을 보여줍니다:

코드 제안 아키텍처 및 컴포넌트

구현 세부 사항과 데이터 흐름

이 섹션에서는 코드 제안을 Self-Managed 인스턴스에 제공하기 위해 사용되는 세 가지 주요 메커니즘을 세분화합니다.

  1. GitLab/CustomersDot 토큰 동기화.
  2. AI 게이트웨이 요청 프록시.
  3. AI 게이트웨이 액세스 토큰 유효성 검사.

아래 순서도는 일반적인 흐름이 어떻게 보일 수 있는지 보여줍니다.

sequenceDiagram autonumber participant U as 사용자 participant VS as IDE participant SM as GitLab participant CD as CustomersDot participant AI as AI 게이트웨이<br/>(모델 게이트웨이) Note over SM,CD: AI 게이트웨이 토큰 동기화 loop Sidekiq cron 작업 SM->>CD: 구독 좌석 데이터 동기화 CD->>CD: 자격 확인 Note over CD,SM: 토큰 유효성은 구독에 묶임 CD-->>SM: 좌석 데이터 + AI 게이트웨이 액세스 토큰 (JWT) SM->>SM: 좌석 데이터 + JWT 저장 end Note over U,AI: Developer Persona U->>SM: PAT 생성 SM-->>U: PAT U->>VS: PAT로 구성 loop 코드 제안 사용 Note over VS,AI: 모든 요청은 AI 추상화 계층을 통해 처리됨 VS->>SM: PAT로 코드 제안 가져오기 SM->>SM: PAT로 사용자 인증 SM->>AI: JWT로 코드 제안 가져오기 alt 유효성 키 부재 AI->>CD: JWKS 가져오기 AI->>AI: Redis에 키 세트 캐시 else AI->>AI: 키 세트 로드 end AI->>AI: 캐시된 JWKS 키로 JWT 유효성 검사 AI-->>SM: 코드 제안 SM-->>VS: 코드 제안 end

GitLab/CustomersDot 토큰 동기화

우리가 처음으로 해결해야 했던 문제는 특정 자체 관리형 GitLab이 코드 제안을 사용할 수 있는지 여부를 결정하는 것이었습니다. 아래에 설명된 메커니즘은 코드 제안을 위해 만들어졌지만 클라우드 라이선스 구독에 연결된 다른 클라우드 커넥터 기능을 수행할 수도 있습니다.

GitLab Rails 애플리케이션의 관점에서 이러한 진실의 근원지는 CustomersDot으로, CustomersDot은 주어진 고객에 대해 활성 상태인 구독 또는 애드온을 결정하기 위해 Zuora(제3자 구독 서비스)와 대화합니다.

GitLab SaaS와는 다르게, CustomersDot은 구독 또는 애드온을 구매할 때 자체 관리형 GitLab 인스턴스로 다시 호출하지 않습니다. 대신, 매일 Sidekiq에서 스케줄된 동기화 작업이 CustomersDot의 /api/v1/seat_links REST 엔드포인트를 사용하여 구매 내용을 실제 좌석 사용량과 비교합니다. 인스턴스는 요청의 일부로 라이선스 키를 게시함으로써 자신을 인증하며, CustomersDot은 이 라이선스 키를 사용하여 이 라이선스와 관련된 구독 데이터를 조회하므로 라이선스 키를 인증 토큰의 하나로 사용합니다.

CustomersDot이 인스턴스를 적격하다고 여기면 응답 페이로드에 코드 제안 토큰을 포함합니다:

"service_tokens": {
  "code_suggestions": {
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0M2FlOWI4...qmvMVhRS01YRc6a5LaBbhU_m5tw",
    "expires_at": 1695121894
  }
}
  • token은 RSA256으로 서명된 인코딩된 JSON Web Token입니다. 이는 다른 서비스가 해당 공개 키를 보유하고 이 토큰의 진정성을 검증할 수 있게 합니다. 토큰은 수신자가 확인할 수 있는 claims를 가지고 있으며, 가장 중요한 것은 aud(청중) 클레임입니다. 우리는 청중 클레임을 사용하여 코드 제안과 같은 특정 기능에 액세스의 범위를 지정합니다. 각 유료 기능은 해당 클레임을 가진 별도의 토큰이 발급되어야 합니다.
  • expires_at: 토큰의 만료 시간을 의미하는 UNIX 에포크 타임스탬프입니다. 현재 토큰은 3일의 유효 기간을 가지고 있습니다. 이 TTL은 액세스 토큰을 주기적으로 재발급하고 토큰 동기화가 실패할 경우를 대비하여 적당한 균형을 잡기 위해 선택되었습니다.

참고: 토큰에 서명하기 위해 CustomersDot은 개인 키를 유지합니다. 보안상의 이유로 이 키를 정기적으로 로테이션합니다. 자세한 내용은 CustomersDot의 키 로테이션 프로세스를 참조하십시오.

응답을 받은 후 GitLab Rails는 이 토큰을 Postgres에 저장하고 이전에 저장했던 다른 토큰을 제거합니다. 사용자가 코드 제안을 요청하면 GitLab은 이토큰을 로드하여 AI 게이트웨이 요청에 첨부합니다. 그리고 다음에 설명하는 것입니다.

AI 게이트웨이 요청 프록시

위에서 설명한 JWT 액세스 토큰을 받은 GitLab 인스턴스는 사용자에게 코드 제안 요청을 제공할 수 있습니다. /api/v4/code_suggestions/completions로 들어오는 요청을 받으면 GitLab은 다음과 같은 작업을 수행합니다:

  1. 이 요청을 사용자의 개인 액세스 토큰(PAT)으로 인증합니다. 이는 다른 REST API 호출과 마찬가지로 사용자가 IDE 설정에서 구성합니다.
  2. 관리자가 코드 제안 기능을 활성화하고 인스턴스 라이선스 티어가 이 기능을 포함하는지 확인합니다.
  3. 데이터베이스에서 JWT 액세스 토큰을 로드합니다.
  4. 해당 토큰을 첨부하여 요청을 AI 게이트웨이로 전달합니다.

GitLab SaaS 요청과 마찬가지로 하향식 호출은 Workhorse의 senddata 기능을 사용합니다. 이 메커니즘은 send-url 헤더 필드로 응답함으로써 Workhorse에 제어를 양도합니다. 그럼 Workhorse는 이 응답을 가로채고 send-url을 통해 제공된 요청 URL, 헤더 및 페이로드를 사용하여 AI 게이트웨이로 호출합니다. 이를 통해 Puma 프로세스가 하향식 I/O에서 지체되는 것을 제거하여 확장성 병목 현상을 해소합니다.

이 프로세스는 대부분 GitLab SaaS와 동일합니다. 가장 큰 차이점은 GitLab Rails가 사용자 권한을 해결하고 액세스 토큰을 로드하는 방식입니다. GitLab SaaS는 고객Dot의 처리에 의해 코드 제안 토큰을 스스로 발급할 수 있지만, 자체 빌링을 처리하지 않기 때문입니다.

AI 게이트웨이 액세스 토큰 유효성 검사

다음으로 해결해야 했던 문제는 사용자를 대신하여 자체 관리형 GitLab이 AI 게이트웨이에 보내는 코드 제안 요청의 인증하는 것이었습니다. AI 게이트웨이는 고객 인스턴스에 대한 어떠한 정보도 알지 않아야 하며 알지 말아야 합니다. 대신 게이트웨이는 원본 토큰 발급자인 CustomersDot에서 가져온 공개 키를 사용하여 요청의 진정성을 확인합니다.

AI 게이트웨이는 먼저 CustomersDot에서 JSON Web Key 세트를 요청합니다. JWKS 엔드포인트에서 얻은 키 세트는 24시간 동안 캐시되어 코드 제안 요청에 첨부된 JWT를 디코딩하는 데 사용됩니다. 토큰 만료는 암묵적으로 강제되며 만료된 토큰은 디코드에 실패하므로 AI 게이트웨이가 이 요청을 거절합니다.

JWKS를 얻고 토큰을 검증하는 단계에 대한 세부 정보는 CustomersDot을 위한 AI 서비스 확인 시퀀스 다이어그램에 상세히 나와 있습니다.

이 프로세스는 대부분 GitLab SaaS와 동일합니다. 유일한 차이점은 AI 게이트웨이가 GitLab SaaS 대신 CustomersDot에서 유효성 키를 가져온다는 것입니다.

빈약한 부분과 전망

코드 제안은 우리가 살펴본 첫 번째 클라우드 커넥터 기능이었지만 더 많은 기능이 설계되고 구축될 것으로 예상되며, 여기에는 여기에 문서화된 기술 접근 방법과 다른 기술 접근 방법이 필요한 기능도 포함될 수 있습니다.

현재 명확하게 정의되지 않거나 이해되지 않는 몇 가지 영역은 다음과 같습니다:

  • GitLab 전용 및 지역 배포 지원. 현재 이슈 410394에서 조사 중입니다.
  • 지리적으로 US 동부의 GitLab 서비스에 연결할 때 높은 지연 오버헤드가 있는 지리적 지역에 GitLab 인스턴스가 배포될 때 최종 사용자 경험에 미치는 영향.
  • 매일 Sidekiq 작업에만 액세스 토큰을 가져오도록 의존하면 알려진 사용성 문제가 있습니다. 이 에픽에서 개선 방법을 탐구하고 있습니다.
  • MVC로는 GitLab 인스턴스 수준에서 요청 속도 제한이 불합리합니다. 이 이슈에서 이 아이디어를 탐구하고 있습니다.