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
proposed @ajwalker @johnwparent @ayufan @DarrenEastman @engineering-manager devops 2023-03-07

GitLab Runner 입합 컨트롤러

GitLab admission controller(Kubernetes 입합 컨트롤러 개념에 영감을 받음)은 작업이 영속화되거나 실행을 위한 빌드 대기열에 추가되기 전에 작업을 가로채기 위한 제안된 기술적 솔루션입니다.

등록된 GitLab 인스턴스에 입합 컨트롤러를 등록할 수 있으며 작성할 작업이 포함된 payload를 받을 수 있습니다. :::

동기

책임 분리, 기관 정책 또는 보안 요구 사항을 준수하기 위해 금융 서비스, 미국 연방 정부 시장 세그먼트 또는 다른 규제가 엄격한 산업의 고객은 특정 CI 작업 환경과 관련된 러너만 사용할 수 있도록 보장해야 합니다.

현재의 GitLab CI 작업 처리 메커니즘

GitLab CI 및 GitLab 러너에서 현재 작업 처리 메커니즘을 수준 맞추는 것이 도움이 됩니다.

RUNNER가 API를 계속해서 요청하여 새로운 작업이 있는지 확인합니다. 프로젝트 저장소에 .gitlab-ci.yml 파일이 있으면 GitLab의 CI 서비스가 해당 이벤트를 캐치하고 새 CI 작업을 트리거합니다. CI 작업은 러너가 인스턴스에서 작업을 요청할 때까지 대기열에서 대기 상태가 됩니다. 러너가 작업을 요청하면 데이터베이스가 쿼리되어 작업 매개변수가 러너의 것과 일치하는지 확인됩니다. 러너가 실행할 작업이 있는 경우 지정된 기준과 일치하면 할당됩니다. 작업이 특정 러너와 일치하는 경우 GitLab은 작업을 러너에 연결하고 작업 상태를 실행으로 변경합니다. 러너는 태그 없는 작업을 실행하도록 구성할 수 있습니다. 태그는 오늘날 고객이 특정 유형의 작업을 어떤 러너에서 실행할지 제어하는 데 사용되는 주요 메커니즘입니다. 러너는 인스턴스, 그룹 또는 프로젝트에 범위가 지정되지만, 오늘날 추가 액세스 제어 메커니즘이 기존 설정을 확장하는 데 사용될 수 있는 추가적인 액세스 제어 메커니즘은 없습니다. :::

목표

기본 작업 세부 정보(사용자, 그룹 또는 프로젝트 멤버십과 같은)를 기반으로하여 특정 러너 개체에서 CI 작업 실행을 허용, 거부 또는 리디렉션하는 쉽게 구성할 수 있고 사용할 수 있는 메커니즘을 제공하는 초기 솔루션을 구현합니다.

비목표

CI 작업 대기열 매커니즘을 재설계하는 것은 이 청사진의 범위에 포함되지 않습니다.

제안

CI 작업을 가로채거나 변형하거나 유효성을 검사하도록 입합 컨트롤러 메커니즘을 구현합니다. 입합 컨트롤러는 CI 작업이 CI 작업 대기열에 삽입되기 전에 웹훅을 통해 호출되는 작업을 수정하거나 정책에 따라 작업을 거부할 수 있는 변형 웹훅입니다.

지침 원칙

  • 웹훅 페이로드 스키마는 공개 API의 일부로 유지될 것입니다.
  • 웹훅 페이로드를 확장할 때는 하위 호환성을 유지해야 합니다.
  • 컨트롤러는 멱등하게 작동해야 합니다.

입합 컨트롤러 작동 방식

시나리오 1: 특정 러너에서 액세스를 거부하려고 합니다.
  1. 입합 컨트롤러를 구성하여 특정 프로젝트에서 작업을 허용하도록 설정합니다.
  2. 작업이 생성될 때 프로젝트 정보(프로젝트 ID, 작업 ID, API 토큰)를 사용하여 GitLab에서 특정 세부 정보를 쿼리합니다.
  3. 프로젝트 정보가 허용 목록과 일치하는 경우 작업 페이로드가 수정되지 않고 해당 작업이 대상 러너에서 실행될 수 있습니다.
  4. 프로젝트 정보가 허용 목록과 일치하지 않는 경우 작업 페이로드가 수정되지 않고 해당 작업이 삭제됩니다.
  5. 작업 태그가 변경되지 않습니다.
  6. 선택적으로 입합 컨트롤러는 작업이 거부되는 이유에 대한 임의의 텍스트 설명을 되돌려보낼 수 있습니다.

시나리오 2: 공통 구성 및 태그를 사용하는 대규모 러너 플리트.

각 러너에는 zone_a, zone_b와 같은 태그가 있습니다. 특정 작업이 zone_a에 실행되어야 하는 경우 일부 사용자는 zone_a에 액세스 권한이 있어야 하고 일부 사용자는 zone_b에 액세스 권한을 가져야 합니다. 작업이 올바르게 zone_a에 태그가 지정되지 않은 경우 작업을 실패시키는 대신 작업을 리디렉션하려고 합니다.

  1. 사용자 ID에 따라 작업을 변형하는 입합 컨트롤러를 구성합니다.
  2. 작업이 생성될 때 프로젝트 정보(프로젝트 ID, 작업 ID, API 토큰)를 사용하여 GitLab에서 특정 세부 정보를 쿼리합니다.
  3. 사용자 ID가 일치하는 경우 입합 컨트롤러는 작업 태그 목록을 수정합니다. zone_a가 작업을 트리거한 사용자가 zone_a에서 작업이 실행되어야 함을 감지했기 때문에 zone_a가 태그 목록에 추가됩니다.

시나리오 3: 특정 태그 체계를 사용하는 러너 풀, 사용자는 특정 하위 집합에만 액세스 권한을 갖고 있습니다.

각 러너에는 해당 러너에 고유한 태그 식별자가 있습니다. 예: DiscoveryOne, tugNostromo, MVSeamus 등. 사용자는 이러한 러너에 임의로 액세스할 수 있지만, 액세스를 거부하려는 작업에 실패시키는 것이 아니라 해당 사용자가 액세스 권한이 없는 러너에서 작업을 실행하는 것을 방지하려고 합니다. 또한 작업이 실행될 수 있는 러너의 풀을 축소하고 싶지는 않습니다.

  1. 사용자 ID에 따라 작업을 변형하는 입합 컨트롤러를 구성합니다.
  2. 작업이 생성될 때 프로젝트 정보(프로젝트 ID, 작업 ID, API 토큰)를 사용하여 GitLab에서 특정 세부 정보를 쿼리합니다.
  3. 입합 컨트롤러는 user_id로 사용 가능한 러너를 쿼리하고 해당 사용자에게 작업을 실행할 수 없는 모든 러너를 수집합니다. 모든 러너에 실행할 수 없는 경우, 입합 컨트롤러는 작업을 거부하고 삭제합니다. 태그는 변경되지 않으며 이유를 나타내는 메시지가 포함됩니다. 사용 권한이 있는 러너가 있는 경우 입합 컨트롤러는 사용 권한이 없는 러너와 관련된 러너를 필터링합니다. :::

MVC

입학 컨트롤러

  1. 단일 입학 컨트롤러는 인스턴스 수준에서만 등록할 수 있습니다.
  2. 입학 컨트롤러는 1시간 이내에 응답해아 합니다.
  3. 입학 컨트롤러는 개별 작업을 수신합니다. 응답은 해당 작업에 대한 응답만 포함해야 합니다.
  4. 입학 컨트롤러는 변이 매개변수를 수락하는 콜백과 거부 및 수락을 위한 API 콜백을 받게 됩니다.

작업 라이프사이클

  1. preparing 작업 상태는 유효성 검사 프로세스 전제 조건을 포함하도록 확장됩니다.

    stateDiagram-v2 created --> preparing state preparing { [*] --> accept [*] --> reject } reject --> failed accept --> pending pending --> running: picked by runner running --> executed state executed { [*] --> failed [*] --> success [*] --> canceled } executed --> created: retry
  2. 상태가 preparing인 경우, 변이 웹훅 페이로드가 입학 컨트롤러로 비동기적으로 전송됩니다. 필요에 따라 여러 번 재시도됩니다.
  3. preparing 상태는 웹훅으로부터의 응답이나 타임아웃이 될 때까지 대기합니다.
  4. UI는 작업 전제 조건 및 입학의 현재 상태로 업데이트되어야 합니다.
  5. 웹훅이 타임아웃되는 작업의 경우(1시간), 그들의 상태는 입학이 거부된 것으로 설정되어야 합니다. 이는 일반적인 상황에서는 드물어야 합니다.
  6. 입학이 거부된 작업은 재시도할 수 있습니다. 재시도된 작업은 태그 변이나 러너 필터링 재설정 없이 입학 컨트롤러로 다시 전송됩니다.
  7. 허용 실패는 실패한 작업을 지원하도록 업데이트되어야 합니다. 예를 들어:

    job:
      script:
        - echo "I will fail admission"
      allow_failure:
        on_denied_admission: true
    
  8. UI는 작업 변이(제공된 경우) 또는 거부를 표시하는 데 업데이트되어야 합니다.
  9. 입학 컨트롤러에 의해 적용된 태그 수정은 시스템에 의해 관련 이유와 함께 유지되어야 합니다.

페이로드

  1. 페이로드는 개별 작업 항목으로 구성됩니다:
  2. 응답 페이로드는 개별 작업 항목으로 구성됩니다:
    • 작업 ID.
    • 입학 상태: 수락 또는 거부.
    • 변이: 추가제거. 추가는 기존 태그 집합을 보충하고, 제거는 현재 태그 목록에서 태그를 제거합니다.
    • 이유: 컨트롤러는 입학 및 변이에 대한 이유를 제공할 수 있습니다.
    • 수락된 러너: 작업 매칭을 고려해야 하는 러너로, 모든 러너와 일치하도록 비워 둘 수 있습니다.
    • 거부된 러너: 작업 매칭에 고려해서는 안 되는 러너로, 모든 러너와 일치하도록 비워 둘 수 있습니다.
요청 예
[
  {
    "id": 123,
    "variables": {
      # 사전 정의된 변수: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
      "CI_PROJECT_ID": 123,
      "CI_PROJECT_NAME": "something",
      "GITLAB_USER_ID": 98123,
      ...
    },
    "tags": [ "docker", "windows" ]
  }
]
[
  {
    "id": 245,
    "variables": {
      "CI_PROJECT_ID": 245,
      "CI_PROJECT_NAME": "foobar",
      "GITLAB_USER_ID": 98123,
      ...
    },
    "tags": [ "linux", "eu-west" ]
  }
]
[
  {
    "id": 666,
    "variables": {
      "CI_PROJECT_ID": 666,
      "CI_PROJECT_NAME": "do-bad-things",
      "GITLAB_USER_ID": 98123,
      ...
    },
    "tags": [ "secure-runner" ]
  },
]
응답 예
[
  {
    "id": 123,
    "admission": "accepted",
    "reason": "it's always-allow-day-wednesday"
  }
]
[
  {
    "id": 245,
    "admission": "accepted",
    "tags": {
      "add": [ "linux", "us-west" ],
      "remove": [...]
    },
    "runners": {
      "accepted_ids": ["822993167"],
      "rejected_ids": ["822993168"]
    },
    "reason": "user is US employee: retagged region; user only has uid on runner 822993167"
  }
]
[
  {
    "id": 666,
    "admission": "rejected",
    "reason": "you have no power here"
  }
]

MVC +

  1. 그룹 및 프로젝트 수준에서 여러 개의 입학 컨트롤러를 사용합니다.
  2. 컨트롤러 체인을 통해 작업 정의를 전달합니다(프로젝트에서 시작하여 정의된 모든 그룹 컨트롤러를 거쳐 인스턴스 컨트롤러까지).
  3. 각 수준은 이전 컨트롤러에 의해 수정된 정의를 받고 현재 상태에 따라 결정을 내립니다.
  4. 여러 컨트롤러가 보고한 경우, 수정 이유는 연결됩니다.
  5. 입학 컨트롤러의 사용은 선택 사항이므로 프로젝트+인스턴스, 프로젝트+그룹+상위 그룹+인스턴스, 프로젝트+그룹, 그룹+인스턴스 등을 포함하는 체인을 가질 수 있습니다.

실행 세부 정보

GitLab

  1. preparing 상태를 확장하여 prerequisite 인터페이스를 통해 검증 프로세스에 참여합니다.
  2. preparing 상태를 변경하여 작업 준비 상태에 대한 작업 전제 조건의 상태를 UI 및 API를 통해 사용자에게 표시해야 합니다.
    1. 각 전제 조건 리소스의 상태를 개별적으로 표시해야 합니다. (비동기적으로 처리되므로)
    2. 전체 전제 조건 상태를 나타내야 합니다.
  3. 전체 preparing 상태에 1시간 제한 시간을 도입합니다.
  4. Gitlab::Ci::Build::Prerequisite::Factory를 통해 preparing 상태 의존성에 AdmissionValidation 전제 조건을 추가합니다.
  5. 전제 조건 팩토리와 preparing 상태를 비동기적으로 동작하도록 변환합니다.
  6. PreparingBuildService를 비동기적으로 동작하도록 변환합니다.
  7. PreparingBuildService는 검증 성공에 따라 작업을 준비 중에서 실패 또는 대기 중으로 전환합니다.
  8. AdmissionValidation은 요청을 보낼 때 합리적인 수의 재시도를 수행합니다.
  9. Webhook/Admission Controller 응답 콜백을 위한 API 엔드포인트를 추가합니다.
    1. 매개변수를 수락합니다:
      • 수락/거부
      • 이유 문자열
      • 태그 변이 (수락되면 무시됨)
    2. 콜백은 일회용 인증 토큰을 인코딩합니다.
  10. 검증 거부에 대한 새로운 실패 이유를 도입합니다.
  11. 작업에 대한 Admission Controller 영향을 지속해야 합니다.
  12. 작업에 대한 Admission Controller의 응답에 따라 Runner 선택 필터링을 추가해야 합니다.

해결해야 할 기술적 문제

문제 해결 방안
큐 웹훅에 대한 규칙 정의  
입학 컨트롤러에게 보낼 데이터는 무엇인가요? 사전 정의된 변수의 하위 집합인가요, 아니면 전체인가요?  
queueing web hook은 GitLab.com 규모에서 실행할 수 있나요? GitLab.com에서는 1초에 수백만 개의 웹훅을 트리거하고, 우려 사항은 Sidekiq을 과부하로 만들거나 시스템을 남용할 수 있다는 것입니다.