쿠버네티스 실행기

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed

Kubernetes 클러스터를 빌드에 사용하기 위해 Kubernetes 실행기를 사용하세요. 실행기는 Kubernetes 클러스터 API를 호출하고 각 GitLab CI 작업에 대한 포드를 생성합니다.

Kubernetes 실행기는 빌드를 여러 단계로 나눕니다:

  1. 준비: Kubernetes 클러스터에 대한 포드를 생성합니다.
    이는 빌드 및 실행할 서비스에 필요한 컨테이너를 생성합니다.
  2. 사전 빌드: 이전 단계에서 캐시를 복원하고 아티팩트를 다운로드하며 클론합니다. 이 단계는 포드의 일부로서 특수 컨테이너에서 실행됩니다.
  3. 빌드: 사용자 빌드.
  4. 사후 빌드: 캐시를 생성하고 GitLab에 아티팩트를 업로드합니다. 이 단계도 포드의 일부로서 특수 컨테이너를 사용합니다.

러너가 Kubernetes 포드를 생성하는 방식

다음 다이어그램은 GitLab 인스턴스와 Kubernetes 클러스터에 호스팅된 러너 간의 상호작용을 보여줍니다. 러너는 클러스터에서 포드를 생성하기 위해 Kubernetes API를 호출합니다.

포드는 .gitlab-ci.yml 또는 config.toml 파일에 정의된 각 service에 대해 다음 컨테이너로 구성됩니다:

  • build로 정의된 빌드 컨테이너.
  • helper로 정의된 헬퍼 컨테이너.
  • svc-X로 정의된 서비스 컨테이너, 여기서 X[0-9]+입니다.

서비스와 컨테이너는 동일한 Kubernetes 포드에서 실행되며 동일한 localhost 주소를 공유합니다. 다음 제약 조건이 적용됩니다:

  • GitLab Runner 12.8 및 Kubernetes 1.7 이상에서 서비스는 DNS 이름을 통해 접근할 수 있습니다. 이전 버전을 사용하는 경우, localhost를 사용해야 합니다.
  • 동일한 포트를 사용하는 여러 서비스를 사용할 수 없습니다. 예를 들어, 동시에 두 개의 mysql 서비스를 가질 수 없습니다.
sequenceDiagram participant G as GitLab instance participant R as Runner on Kubernetes cluster participant Kube as Kubernetes API participant P as POD R->>+G: CI 작업을 가져옵니다. loop G-->R: ; end Note over R,G: POST /api/v4/jobs/request G->>+R: CI 작업 데이터입니다. R-->>-Kube: CI 작업을 실행하기 위해 포드를 만듭니다. Note over R,Kube: Kube API에 POST P->>+P: 작업을 실행합니다. Note over P: CI 빌드 작업 = 준비 + 사전 빌드 + 빌드 + 사후 빌드 P->>+G: 작업 로그

다이어그램의 상호작용은 모든 Kubernetes 클러스터에 대해 유효합니다. 예를 들어, 주요 퍼블릭 클라우드 제공업체에서 호스팅되는 턴키 솔루션 또는 자체 관리 Kubernetes 설치가 있습니다.

Kubernetes API에 연결

다음 옵션을 사용하여 Kubernetes API에 연결하세요. 제공된 사용자 계정은 지정된 네임스페이스에서 포드를 생성, 나열 및 연결할 수 있는 권한이 있어야 합니다.

옵션 설명
host 선택적 Kubernetes apiserver 호스트 URL(지정하지 않으면 자동 검색 시도).
cert_file 선택적 Kubernetes apiserver 사용자 인증서.
key_file 선택적 Kubernetes apiserver 사용자 인증 개인 키.
ca_file 선택적 Kubernetes apiserver ca 인증서.

Kubernetes 클러스터에서 GitLab Runner를 실행하는 경우, GitLab Runner가 Kubernetes API를 자동으로 검색할 수 있도록 이 모든 필드를 생략해야 합니다.

클러스터 외부에서 GitLab Runner를 실행하는 경우, 각 설정을 반드시 지정하고 GitLab Runner가 클러스터에서 Kubernetes API에 접근할 수 있도록 해야 합니다.

Kubernetes API 호출을 위한 Bearer Token 설정

API 호출을 통해 포드를 생성하기 위한 Bearer Token을 설정하려면 KUBERNETES_BEARER_TOKEN 변수를 사용하세요.

이는 프로젝트 소유자가 프로젝트 비밀 변수를 사용하여 Bearer Token을 지정할 수 있도록 합니다.

Bearer Token을 지정할 때는 Host 구성 설정을 설정해야 합니다.

variables:
  KUBERNETES_BEARER_TOKEN: thebearertokenfromanothernamespace

러너 API 권한 구성

코어 API 그룹에 대한 권한을 구성하려면 GitLab Runner Helm 차트의 values.yml 파일을 업데이트하세요.

다음 중 하나를 선택할 수 있습니다:

  • rbac.createtrue로 설정합니다.

  • 다음 권한을 가진 서비스 계정을 rbac.serviceAccountName: <service_account_name>으로 지정합니다.

    values.yml 파일에서.

자원 동사 (선택적 기능 플래그)
events list, watch (FF_PRINT_POD_EVENTS=true)
namespaces create, delete
pods attach (FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false), create, delete, exec, get, watch (FF_KUBERNETES_HONOR_ENTRYPOINT=true, FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false)
pods/log get (FF_KUBERNETES_HONOR_ENTRYPOINT=true, FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false, FF_WAIT_FOR_POD_TO_BE_REACHABLE=true), list (FF_KUBERNETES_HONOR_ENTRYPOINT=true, FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false)
secrets create, delete, get, update
serviceAccounts get
services create, get
  • serviceAccount 권한은 다음의 경우에만 필요합니다:

    • GitLab 15.0 및 15.1의 경우.

    • GitLab 15.0.1, 15.1.1 및 15.2가 resource_availability_check_max_attempts가 0보다 높은 값으로 설정된 경우.

  • GitLab Runner 15.8부터는 configmaps 권한이 더 이상 필요하지 않습니다.

  • event 권한은 다음의 경우에만 필요합니다:

    • GitLab 16.2.1 이상.
  • namespace 권한은 다음의 경우에만 필요합니다:

    • namespace_per_job을 통해 네임스페이스 격리를 활성화할 때.
  • pods/log 권한은 다음 시나리오 중 하나가 참일 때만 필요합니다:

구성 설정

Kubernetes 실행자를 구성하려면 config.toml 파일에서 다음 설정을 사용하세요.

CPU 요청 및 제한

설정 설명
cpu_limit 빌드 컨테이너에 할당된 CPU입니다.
cpu_limit_overwrite_max_allowed 빌드 컨테이너에 대한 CPU 할당을 쓸 수 있는 최대 값입니다. 비어 있을 경우, CPU 제한 재작성 기능이 비활성화됩니다.
cpu_request 빌드 컨테이너에 요청된 CPU입니다.
cpu_request_overwrite_max_allowed 빌드 컨테이너에 대한 CPU 요청을 쓸 수 있는 최대 값입니다. 비어 있을 경우, CPU 요청 재작성 기능이 비활성화됩니다.
helper_cpu_limit 빌드 도우미 컨테이너에 할당된 CPU입니다.
helper_cpu_limit_overwrite_max_allowed 도우미 컨테이너에 대한 CPU 할당을 쓸 수 있는 최대 값입니다. 비어 있을 경우, CPU 제한 재작성 기능이 비활성화됩니다.
helper_cpu_request 빌드 도우미 컨테이너에 요청된 CPU입니다.
helper_cpu_request_overwrite_max_allowed 도우미 컨테이너에 대한 CPU 요청을 쓸 수 있는 최대 값입니다. 비어 있을 경우, CPU 요청 재작성 기능이 비활성화됩니다.
service_cpu_limit 빌드 서비스 컨테이너에 할당된 CPU입니다.
service_cpu_limit_overwrite_max_allowed 서비스 컨테이너에 대한 CPU 할당을 쓸 수 있는 최대 값입니다. 비어 있을 경우, CPU 제한 재작성 기능이 비활성화됩니다.
service_cpu_request 빌드 서비스 컨테이너에 요청된 CPU입니다.
service_cpu_request_overwrite_max_allowed 서비스 컨테이너에 대한 CPU 요청을 쓸 수 있는 최대 값입니다. 비어 있을 경우, CPU 요청 재작성 기능이 비활성화됩니다.

메모리 요청 및 제한

설정 설명
memory_limit 빌드 컨테이너에 할당된 메모리 양입니다.
memory_limit_overwrite_max_allowed 빌드 컨테이너에 대해 메모리 할당이 기록될 수 있는 최대 양입니다. 비어 있으면 메모리 제한 재작성 기능이 비활성화됩니다.
memory_request 빌드 컨테이너에서 요청된 메모리 양입니다.
memory_request_overwrite_max_allowed 빌드 컨테이너에 대해 메모리 할당 요청이 기록될 수 있는 최대 양입니다. 비어 있으면 메모리 요청 재작성 기능이 비활성화됩니다.
helper_memory_limit 빌드 헬퍼 컨테이너에 할당된 메모리 양입니다.
helper_memory_limit_overwrite_max_allowed 헬퍼 컨테이너에 대해 메모리 할당이 기록될 수 있는 최대 양입니다. 비어 있으면 메모리 제한 재작성 기능이 비활성화됩니다.
helper_memory_request 빌드 헬퍼 컨테이너에 요청된 메모리 양입니다.
helper_memory_request_overwrite_max_allowed 헬퍼 컨테이너에 대해 메모리 할당 요청이 기록될 수 있는 최대 양입니다. 비어 있으면 메모리 요청 재작성 기능이 비활성화됩니다.
service_memory_limit 빌드 서비스 컨테이너에 할당된 메모리 양입니다.
service_memory_limit_overwrite_max_allowed 서비스 컨테이너에 대해 메모리 할당이 기록될 수 있는 최대 양입니다. 비어 있으면 메모리 제한 재작성 기능이 비활성화됩니다.
service_memory_request 빌드 서비스 컨테이너에 요청된 메모리 양입니다.
service_memory_request_overwrite_max_allowed 서비스 컨테이너에 대해 메모리 할당 요청이 기록될 수 있는 최대 양입니다. 비어 있으면 메모리 요청 재작성 기능이 비활성화됩니다.

저장소 요청 및 제한

설정 설명
ephemeral_storage_limit 빌드 컨테이너에 대한 임시 저장소 제한입니다.
ephemeral_storage_limit_overwrite_max_allowed 빌드 컨테이너에 대한 임시 저장소 제한이 재작성될 수 있는 최대 양입니다. 비어 있으면 임시 저장소 제한 재작성 기능이 비활성화됩니다.
ephemeral_storage_request 빌드 컨테이너에 제공된 임시 저장소 요청입니다.
ephemeral_storage_request_overwrite_max_allowed 빌드 컨테이너에 대해 임시 저장소 요청이 재작성될 수 있는 최대 양입니다. 비어 있으면 임시 저장소 요청 재작성 기능이 비활성화됩니다.
helper_ephemeral_storage_limit 헬퍼 컨테이너에 주어진 임시 저장소 제한입니다.
helper_ephemeral_storage_limit_overwrite_max_allowed 헬퍼 컨테이너에 대해 임시 저장소 제한이 재작성될 수 있는 최대 양입니다. 비어 있으면 임시 저장소 요청 재작성 기능이 비활성화됩니다.
helper_ephemeral_storage_request 헬퍼 컨테이너에 주어진 임시 저장소 요청입니다.
helper_ephemeral_storage_request_overwrite_max_allowed 헬퍼 컨테이너에 대해 임시 저장소 요청이 재작성될 수 있는 최대 양입니다. 비어 있으면 임시 저장소 요청 재작성 기능이 비활성화됩니다.
service_ephemeral_storage_limit 서비스 컨테이너에 주어진 임시 저장소 제한입니다.
service_ephemeral_storage_limit_overwrite_max_allowed 서비스 컨테이너에 대해 임시 저장소 제한이 재작성될 수 있는 최대 양입니다. 비어 있으면 임시 저장소 요청 재작성 기능이 비활성화됩니다.
service_ephemeral_storage_request 서비스 컨테이너에 주어진 임시 저장소 요청입니다.
service_ephemeral_storage_request_overwrite_max_allowed 서비스 컨테이너에 대해 임시 저장소 요청이 재작성될 수 있는 최대 양입니다. 비어 있으면 임시 저장소 요청 재작성 기능이 비활성화됩니다.

기타 config.toml 설정

| 설정 | 설명 | |———|————-| | affinity | 빌드를 실행할 노드를 결정하는 affinity 규칙을 지정합니다. affinity 사용에 대해 더 알아보기를 읽어보세요. | | allow_privilege_escalation | allowPrivilegeEscalation 플래그가 활성화된 모든 컨테이너를 실행합니다. 비어 있을 경우, 컨테이너의 SecurityContext에서 allowPrivilegeEscalation 플래그를 정의하지 않으며, 기본 privilege escalation 동작을 사용하도록 Kubernetes가 허용됩니다. | | allowed_images | .gitlab-ci.yml에서 지정할 수 있는 이미지의 와일드카드 목록입니다. 없으면 모든 이미지가 허용됩니다(동일한 의미: ["*/*:*"]). 자세히 보기. | | allowed_pull_policies | .gitlab-ci.yml 파일 또는 config.toml 파일에서 지정할 수 있는 풀 정책 목록입니다. | | allowed_services | .gitlab-ci.yml에서 지정할 수 있는 서비스의 와일드카드 목록입니다. 없으면 모든 이미지가 허용됩니다(동일한 의미: ["*/*:*"]). 자세히 보기. | | automount_service_account_token | 빌드 포드에서 서비스 계정 토큰의 자동 정산을 제어하는 부울 값입니다. | | bearer_token | 빌드 포드를 시작하는 데 사용되는 기본 베어러 토큰입니다. | | bearer_token_overwrite_allowed | 프로젝트가 빌드 포드를 만들 때 사용될 베어러 토큰을 지정할 수 있도록 허용하는 부울 값입니다. | | build_container_security_context | 빌드 컨테이너에 대한 보안 컨텍스트를 설정합니다. 보안 컨텍스트에 대해 더 알아보기. | | cap_add | 작업 포드 컨테이너에 추가해야 하는 Linux 기능을 지정합니다. Kubernetes executor에서 기능 구성에 대해 더 알아보기. | | cap_drop | 작업 포드 컨테이너에서 삭제해야 하는 Linux 기능을 지정합니다. Kubernetes executor에서 기능 구성에 대해 더 알아보기. | | cleanup_grace_period_seconds | 작업이 완료되면, 포드가 정상적으로 종료하는 데 필요한 시간(초)입니다. 이 기간이 지나면 프로세스가 종료 신호로 강제로 중단됩니다. terminationGracePeriodSeconds가 지정될 경우 무시됩니다. | | dns_policy | 포드를 구성할 때 사용해야 하는 DNS 정책을 지정합니다: none, default, cluster-first, cluster-first-with-host-net. 설정하지 않으면 Kubernetes 기본값(cluster-first)이 사용됩니다. | | dns_config | 포드를 구성할 때 사용해야 하는 DNS 구성을 지정합니다. 포드의 DNS 구성 사용에 대해 더 알아보기. | | helper_container_security_context | 헬퍼 컨테이너에 대한 보안 컨텍스트를 설정합니다. 보안 컨텍스트에 대해 더 알아보기. | | helper_image | (고급) 레포를 복제하고 아티팩트를 업로드하는 데 사용되는 기본 헬퍼 이미지를 재정의합니다. | | helper_image_flavor | 헬퍼 이미지 맛을 설정합니다(alpine, alpine3.16, alpine3.17, alpine3.18, alpine3.19 또는 ubuntu). 기본값은 alpine입니다. alpine을 사용하는 것은 alpine3.18과 동일합니다. | | host_aliases | 모든 컨테이너에 추가해줄 호스트 이름 별칭 목록입니다. 추가 호스트 별칭 사용에 대해 더 알아보기. | | image_pull_secrets | 개인 레지스트리에서 Docker 이미지를 인증하기 위해 사용되는 Kubernetes docker-registry 비밀 이름의 항목 배열입니다. | | init_permissions_container_security_context | init-permissions 컨테이너에 대한 보안 컨텍스트를 설정합니다. 보안 컨텍스트에 대해 더 알아보기. | | namespace | Kubernetes Pods를 실행할 네임스페이스입니다. | | namespace_per_job | 작업을 별도의 네임스페이스로 격리합니다. 활성화되면 namespacenamespace_overwrite_allowed는 무시됩니다. | | namespace_overwrite_allowed | 네임스페이스 덮어쓰기 환경 변수의 내용 검증을 위한 정규 표현식입니다(아래 문서화됨). 비어 있으면 네임스페이스 덮어쓰기 기능이 비활성화됩니다. | | node_selector | key=value 쌍을 string=string 형식으로 나타내는 table입니다(환경 변수가 있는 경우에는 string:string). 이는 Kubernetes 노드에서 모든 key=value 쌍과 일치하는 포드 생성을 제한합니다. [노드 선택자 사용에 대해 더 알아보기](#specify-the-node-to-execute-builds). | | node_tolerations | “key=value” = “Effect” 쌍의 table입니다. 이는 string=string:string 형식으로 설정되며, 이는 포드가 모두 또는 부분적인 허용된 오염 물질이 있는 노드에서 예약될 수 있도록 허용합니다. 환경 변수 구성에서 하나의 허용만 제공될 수 있습니다. key, value, 및 effect는 Kubernetes 포드 허용 구성에서 해당 필드 이름과 일치합니다. | | pod_annotations | key=value 쌍의 table입니다. 이는 러너가 생성한 각 빌드 포드에 추가할 주석 목록입니다. 이들의 값은 변수 확장을 포함할 수 있습니다. 포드 주석은 각 빌드에서 덮어쓸 수 있습니다. | | pod_annotations_overwrite_allowed | 포드 주석 덮어쓰기 환경 변수의 내용 검증을 위한 정규 표현식입니다. 비어 있으면 포드 주석 덮어쓰기 기능이 비활성화됩니다. | | pod_labels | key=value 쌍의 table입니다. 이는 러너가 생성한 각 빌드 포드에 추가할 레이블 목록입니다. 이들의 값은 변수 확장을 포함할 수 있습니다. 포드 레이블은 pod_labels_overwrite_allowed를 사용하여 각 빌드에서 덮어쓸 수 있습니다. | | pod_labels_overwrite_allowed | 포드 레이블 덮어쓰기 환경 변수의 내용 검증을 위한 정규 표현식입니다. 비어 있으면 포드 레이블 덮어쓰기 기능이 비활성화됩니다. | | pod_security_context | 구성 파일을 통해 구성이 이루어지며, 이 설정은 빌드 포드에 대한 보안 컨텍스트를 설정합니다. [보안 컨텍스트에 대해 더 알아보기](#set-a-security-policy-for-the-pod). | | pod_termination_grace_period_seconds | 포드 수준 설정으로, 포드가 정상적으로 종료되는 데 필요한 시간(초)을 결정합니다. 그 후, 프로세스가 강제로 종료 신호로 종료됩니다. terminationGracePeriodSeconds가 지정될 경우 무시됩니다. | | poll_interval | 러너가 방금 생성한 Kubernetes 포드의 상태를 확인하기 위해 폴링하는 빈도(초)입니다(기본값 = 3). | | poll_timeout | 러너가 방금 생성한 컨테이너에 연결 시도를 시간 초과하기까지 경과해야 하는 시간(초)입니다. 클러스터가 한 번에 처리할 수 있는 빌드를 큐에 추가하는 데 유용합니다(기본값 = 180). | | cleanup_resources_timeout | 작업이 완료된 후 Kubernetes 리소스가 정리되는 데 걸리는 총 시간입니다. 지원되는 문법: 1h30m, 300s, 10m. 기본값은 5분(5m)입니다. | | priority_class_name | 포드에 설정할 우선 순위 클래스를 지정합니다. 설정하지 않으면 기본값이 사용됩니다. | | privileged | 특권 플래그가 있는 컨테이너를 실행합니다. | | pull_policy | 이미지 풀 정책을 지정합니다: never, if-not-present, always. 설정하지 않으면 클러스터의 이미지 [기본 풀 정책](https://kubernetes.io/docs/concepts/containers/images/#updating-images)이 사용됩니다. 여러 풀 정책 설정에 대한 더 많은 정보 및 지침은 [풀 정책 사용](#set-a-pull-policy)을 참조하십시오. 또한 [if-not-present, never 보안 고려사항](../../security/index.md#usage-of-private-docker-images-with-if-not-present-pull-policy)을 참조하세요. [풀 정책 제한](#restrict-docker-pull-policies)도 가능합니다. | | resource_availability_check_max_attempts | 사용할 수 있는 리소스(서비스 계정 및/또는 풀 비밀)가 있는지 확인하기 위한 최대 시도 횟수입니다. 각 시도 사이에는 5초 간격이 있습니다. [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27664) in GitLab 15.0. [준비 단계에서 리소스 확인에 대해 더 알아보기](#resources-check-during-prepare-step). | | runtime_class_name | 생성된 모든 포드에 사용할 런타임 클래스를 지정합니다. 클러스터에서 기능이 지원되지 않으면 작업이 종료되거나 실패합니다. | | service_container_security_context | 서비스 컨테이너에 대한 보안 컨텍스트를 설정합니다. [보안 컨텍스트에 대해 더 알아보기](#set-a-security-policy-for-the-pod). | | scheduler_name | 빌드 포드를 예약하는 데 사용할 스케줄러입니다. | | service_account | 기본 서비스 계정 작업/실행자가 Kubernetes API와 통신하는 데 사용됩니다. | | service_account_overwrite_allowed | 서비스 계정 덮어쓰기 환경 변수의 내용 검증을 위한 정규 표현식입니다. 비어 있으면 서비스 계정 덮어쓰기 기능이 비활성화됩니다. | | services | [sidecar 패턴](https://learn.microsoft.com/en-us/azure/architecture/patterns/sidecar)을 사용하여 빌드 컨테이너에 연결된 [서비스](https://docs.gitlab.com/ee/ci/services/) 목록입니다. [서비스 사용에 대해 더 알아보기](#define-a-list-of-services). | | use_service_account_image_pull_secrets | 활성화되면 실행자가 생성한 포드에는 imagePullSecrets가 없습니다. 이는 설정된 경우 서비스 계정의 [imagePullSecrets](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-image-pull-secret-to-service-account)를 사용하여 포드가 생성되도록 합니다. | | terminationGracePeriodSeconds | 포드 내에서 실행 중인 프로세스가 종료 신호를 받고 프로세스가 강제로 종료되는 시간입니다. [cleanup_grace_period_secondspod_termination_grace_period_seconds에 대한 deprecation](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/28165). | | volumes | 구성 파일을 통해 구성되며, 빌드 컨테이너에 마운트된 볼륨 목록입니다. [볼륨 사용에 대해 더 알아보기](#configure-volume-types). | | pod_spec | 이 설정은 실험입니다. CI 작업을 실행하는 데 사용되는 포드에 설정된 구성 목록으로 러너 관리자가 생성한 포드 사양을 재정의합니다. Kubernetes Pod Specification에 나열된 모든 속성을 설정할 수 있습니다. [생성된 포드 사양을 재정의하기](#overwrite-generated-pod-specifications) 관련 정보를 확인하세요. | | retry_limit | Kubernetes API와 통신하기 위한 최대 시도 횟수입니다. 각 시도 간의 재시도 간격은 500ms에서 시작하는 백오프 알고리즘에 따라 결정됩니다. | | retry_backoff_max | 각 시도에 대한 재시도 간격의 사용자 지정 최대 백오프 값(밀리초)입니다. 기본값은 2000ms이며, 500ms보다 낮을 수 없습니다. 각 시도에 도달하는 최대 재시도 간격의 기본값은 2초이며, retry_backoff_max로 사용자 지정할 수 있습니다. | | retry_limits | 각 요청 오류를 얼마나 많은 횟수로 재시도할 것인지입니다. | | logs_base_dir | 생성된 경로에 추가되어 빌드 로그를 저장하는 기본 디렉토리입니다. 빌드 로그 및 스크립트의 기본 디렉토리 변경에 대한 추가 정보는 [Change the base directory for build logs and scripts](#change-the-base-directory-for-build-logs-and-scripts)를 참조하세요. | | scripts_base_dir` | 생성된 경로에 추가되어 빌드 스크립트를 저장하는 기본 디렉토리입니다. 빌드 로그 및 스크립트의 기본 디렉토리 변경에 대한 추가 정보는 Change the base directory for build logs and scripts를 참조하세요. |

구성 예시

다음 샘플은 Kubernetes 실행기용 config.toml 파일의 구성 예시를 보여줍니다.

concurrent = 4

[[runners]]
  name = "myRunner"
  url = "https://gitlab.com/ci"
  token = "......"
  executor = "kubernetes"
  [runners.kubernetes]
    host = "https://45.67.34.123:4892"
    cert_file = "/etc/ssl/kubernetes/api.crt"
    key_file = "/etc/ssl/kubernetes/api.key"
    ca_file = "/etc/ssl/kubernetes/ca.crt"
    namespace = "gitlab"
    namespace_overwrite_allowed = "ci-.*"
    bearer_token_overwrite_allowed = true
    privileged = true
    cpu_limit = "1"
    memory_limit = "1Gi"
    service_cpu_limit = "1"
    service_memory_limit = "1Gi"
    helper_cpu_limit = "500m"
    helper_memory_limit = "100Mi"
    poll_interval = 5
    poll_timeout = 3600
    dns_policy = "cluster-first"
    priority_class_name = "priority-1"
    logs_base_dir = "/tmp"
    scripts_base_dir = "/tmp"
    [runners.kubernetes.node_selector]
      gitlab = "true"
    [runners.kubernetes.node_tolerations]
      "node-role.kubernetes.io/master" = "NoSchedule"
      "custom.toleration=value" = "NoSchedule"
      "empty.value=" = "PreferNoSchedule"
      "onlyKey" = ""

실행기 서비스 계정 구성

실행기 서비스 계정을 구성하려면 KUBERNETES_SERVICE_ACCOUNT 환경 변수를 설정하거나 --kubernetes-service-account 플래그를 사용할 수 있습니다.

포드 및 컨테이너

작업 실행 방식을 제어하기 위해 포드 및 컨테이너를 구성할 수 있습니다.

작업 포드에 대한 기본 주석

작업을 실행하는 포드에 대해 기본적으로 추가되는 주석은 다음과 같습니다:

설명
job.runner.gitlab.com/id GitLab 인스턴스 내의 모든 작업에서 고유한 작업 ID.
job.runner.gitlab.com/url 작업 세부정보의 URL.
job.runner.gitlab.com/sha 프로젝트가 빌드된 커밋 리비전.
job.runner.gitlab.com/before_sha 브랜치 또는 태그에 존재하는 이전 최신 커밋.
job.runner.gitlab.com/ref 프로젝트가 빌드된 브랜치 또는 태그 이름.
job.runner.gitlab.com/name 작업의 이름.
project.runner.gitlab.com/id 작업의 프로젝트 ID.

기본 주석을 덮어쓰려면 GitLab Runner 구성에서 pod_annotations를 사용하세요.

각 CI/CD 작업의 주석을 덮어쓸 수도 있습니다 .gitlab-ci.yml 파일에서.

포드 생명주기

포드의 생명주기는 다음에 영향을 받을 수 있습니다:

  • TOML 구성 파일에서 pod_termination_grace_period_seconds 속성을 설정합니다. 포드에서 실행 중인 프로세스는 TERM 신호가 전송된 후 주어진 시간 동안 실행될 수 있습니다. 이 마감 시간 이후에 포드가 성공적으로 종료되지 않으면 킬 신호가 전송됩니다.

  • FF_USE_POD_ACTIVE_DEADLINE_SECONDS 기능 플래그를 사용합니다. 사용 시 작업이 제한시간 초과되면 CI/CD 작업을 실행 중인 포드가 실패로 표시되고 모든 관련 컨테이너가 종료됩니다. GitLab에서 작업이 먼저 제한시간 초과되도록 하려면, activeDeadlineSecondsconfigured timeout + 1 second로 설정됩니다.

주의 사항: FF_USE_POD_ACTIVE_DEADLINE_SECONDS 기능 플래그가 활성화되고 pod_termination_grace_period_seconds가 0이 아닌 값으로 설정된 경우, CI 작업 포드는 작업이 제한시간 초과된 경우 즉시 종료되지 않습니다. 포드 terminationGracePeriods는 포드가 만료되었을 때만 종료됩니다.

파드 내구성 재정의

Kubernetes 파드 내구성을 재정의하려면:

  1. config.toml 또는 Helm values.yaml 파일에서 CI 작업 파드 내구성의 재정의를 활성화하려면 node_tolerations_overwrite_allowed에 대한 정규 표현식을 정의합니다.
    이 정규 표현식은 KUBERNETES_NODE_TOLERATIONS_로 시작하는 CI 변수 이름의 값을 검증합니다.

    runners:
     ...
     config: |
       [[runners]]
         [runners.kubernetes]
           node_tolerations_overwrite_allowed = ".*"
    
  2. .gitlab-ci.yml 파일에서 CI 작업 파드 내구성을 재정의하기 위해 하나 이상의 CI 변수를 정의합니다.

    variables:
      KUBERNETES_NODE_TOLERATIONS_1: 'node-role.kubernetes.io/master:NoSchedule'
      KUBERNETES_NODE_TOLERATIONS_2: 'custom.toleration=value:NoSchedule'
      KUBERNETES_NODE_TOLERATIONS_3: 'empty.value=:PreferNoSchedule'
      KUBERNETES_NODE_TOLERATIONS_4: 'onlyKey'
      KUBERNETES_NODE_TOLERATIONS_5: '' # 모든 얼룩을 허용
    

파드 레이블 재정의

각 CI/CD 작업에 대한 Kubernetes 파드 레이블을 재정의하려면:

  1. .config.yaml 파일에서 pod_labels_overwrite_allowed에 대한 정규 표현식을 정의합니다.
  2. .gitlab-ci.yml 파일에서 KUBERNETES_POD_LABELS_* 변수를 key=value 값으로 설정합니다. 파드 레이블은 key=value로 재정의됩니다. 여러 값을 적용할 수 있습니다:

     variables:
       KUBERNETES_POD_LABELS_1: "Key1=Val1"
       KUBERNETES_POD_LABELS_2: "Key2=Val2"
       KUBERNETES_POD_LABELS_3: "Key3=Val3"
    

파드 주석 재정의

각 CI/CD 작업에 대한 Kubernetes 파드 주석을 재정의하려면:

  1. .config.yaml 파일에서 pod_annotations_overwrite_allowed에 대한 정규 표현식을 정의합니다.
  2. .gitlab-ci.yml 파일에서 KUBERNETES_POD_ANNOTATIONS_* 변수를 설정하고 key=value를 값으로 사용합니다.
    파드 주석은 key=value로 재정의됩니다. 여러 주석을 지정할 수 있습니다:

    variables:
      KUBERNETES_POD_ANNOTATIONS_1: "Key1=Val1"
      KUBERNETES_POD_ANNOTATIONS_2: "Key2=Val2"
      KUBERNETES_POD_ANNOTATIONS_3: "Key3=Val3"
    

아래 예에서는 pod_annotationspod_annotations_overwrite_allowed가 설정되어 있습니다.
이 구성은 config.toml에서 구성된 모든 pod_annotations를 재정의할 수 있습니다.

[[runners]]
  # 일반 구성
  executor = "kubernetes"
  [runners.kubernetes]
    image = "alpine"
    pod_annotations_overwrite_allowed = ".*"
    [runners.kubernetes.pod_annotations]
      "Key1" = "Val1"
      "Key2" = "Val2"
      "Key3" = "Val3"
      "Key4" = "Val4"

생성된 팟 사양 덮어쓰기

상태: Beta
History

이 기능은 베타 상태입니다. 우리는 이 기능을 프로덕션 클러스터에서 사용하기 전에 테스트 Kubernetes 클러스터에서 사용하기를 강력히 권장합니다. 이 기능을 사용하려면 FF_USE_ADVANCED_POD_SPEC_CONFIGURATION 기능 플래그를 활성화해야 합니다.

일반적으로 사용 가능해지기 전에 개선사항에 대한 피드백을 추가하려면 이 문제를 사용하세요.

러너 관리자가 생성한 PodSpec를 수정하려면 config.toml 파일의 pod_spec 설정을 사용하십시오.

pod_spec 설정:

  • 생성된 팟 사양의 필드를 덮어쓰고 완성합니다.

  • [runners.kubernetes] 아래의 config.toml에서 설정될 수 있는 구성 값을 덮어씁니다.

여러 pod_spec 설정을 구성할 수 있습니다.

설정 설명
name 사용자 정의 pod_spec에 주어진 이름.
patch_path 최종 PodSpec 객체에 적용할 변경 사항을 정의하는 파일의 경로입니다. 파일은 JSON 또는 YAML 파일이어야 합니다.
patch 최종 PodSpec 객체에 적용해야 할 변경 사항을 설명하는 JSON 또는 YAML 형식의 문자열입니다.
patch_type 러너가 GitLab Runner에 의해 생성된 PodSpec 객체에 지정된 변경 사항을 적용하는 전략입니다. 허용된 값은 merge, json, 및 strategic입니다.

동일한 pod_spec 구성에 patch_pathpatch를 설정할 수 없으며, 그렇지 않으면 오류가 발생합니다.

config.toml에서 여러 pod_spec 구성의 예:

[[runners]]
  [runners.kubernetes]
    [[runners.kubernetes.pod_spec]]
      name = "hostname"
      patch = '''
        hostname: "custom-pod-hostname"
      '''
      patch_type = "merge"
    [[runners.kubernetes.pod_spec]]
      name = "subdomain"
      patch = '''
        subdomain: "subdomain"
      '''
      patch_type = "strategic"
    [[runners.kubernetes.pod_spec]]
      name = "terminationGracePeriodSeconds"
      patch = '''
        [{"op": "replace", "path": "/terminationGracePeriodSeconds", "value": 60}]
      '''
      patch_type = "json"

병합 패치 전략

merge 패치 전략은 기존의 PodSpec키-값 교체를 적용합니다.

이 전략을 사용하는 경우, config.tomlpod_spec 구성은 생성되기 전에 최종 PodSpec 객체의 값을 덮어씁니다. 값이 완전히 덮어쓰기 때문에 이 패치 전략을 사용할 때는 주의해야 합니다.

merge 패치 전략을 가진 pod_spec 구성의 예:

concurrent = 1
check_interval = 1
log_level = "debug"
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = ""
  url = "https://gitlab.example.com"
  id = 0
  token = "__REDACTED__"
  token_obtained_at = 0001-01-01T00:00:00Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "kubernetes"
  shell = "bash"
  environment = ["FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=true", "CUSTOM_VAR=value"]
  [runners.kubernetes]
    image = "alpine"
    ...
    [[runners.kubernetes.pod_spec]]
      name = "build envvars"
      patch = '''
        containers:
        - env:
          - name: env1
            value: "value1"
          - name: env2
            value: "value2"
          name: build
      '''
      patch_type = "merge"

이 구성으로 인해 최종 PodSpecbuild라는 이름의 단일 컨테이너와 두 개의 환경 변수 env1env2만을 포함하게 됩니다. 위의 예는 관련 CI 작업이 실패하게 만들 수 있습니다:

  • helper 컨테이너 사양이 제거됩니다.
  • build 컨테이너 사양이 GitLab Runner에 의해 설정된 모든 필수 구성을 잃습니다.

작업 실패를 방지하기 위해 이 예에서는 pod_spec에 GitLab Runner에 의해 생성된 보존된 속성이 포함되어야 합니다.

JSON 패치 전략

json 패치 전략은 JSON Patch 사양을 사용하여 업데이트할 PodSpec 객체와 배열에 대한 제어를 제공합니다. 이 전략은 array 속성에서는 사용할 수 없습니다.

다음은 json 패치 전략을 사용한 pod_spec 구성의 예입니다. 이 구성에서는 기존의 nodeSelector에 새로운 key: value pair가 추가됩니다. 기존 값은 덮어쓰지 않습니다.

concurrent = 1
check_interval = 1
log_level = "debug"
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = ""
  url = "https://gitlab.example.com"
  id = 0
  token = "__REDACTED__"
  token_obtained_at = 0001-01-01T00:00:00Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "kubernetes"
  shell = "bash"
  environment = ["FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=true", "CUSTOM_VAR=value"]
  [runners.kubernetes]
    image = "alpine"
    ...
    [[runners.kubernetes.pod_spec]]
      name = "val1 node"
      patch = '''
        { "op": "add", "path": "/nodeSelector", "value": { key1: "val1" } }
      '''
      patch_type = "json"

전략적 패치 전략

strategic 패치 전략은 PodSpec 객체의 각 필드에 적용된 기존 patchStrategy를 사용합니다.

다음은 strategic 패치 전략을 사용한 pod_spec 구성의 예입니다. 이 구성에서는 빌드 컨테이너에 resource request가 설정됩니다.

concurrent = 1
check_interval = 1
log_level = "debug"
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = ""
  url = "https://gitlab.example.com"
  id = 0
  token = "__REDACTED__"
  token_obtained_at = 0001-01-01T00:00:00Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "kubernetes"
  shell = "bash"
  environment = ["FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=true", "CUSTOM_VAR=value"]
  [runners.kubernetes]
    image = "alpine"
    ...
    [[runners.kubernetes.pod_spec]]
      name = "cpu request 500m"
      patch = '''
        containers:
        - name: build
          resources:
            requests:
              cpu: "500m"
      '''
      patch_type = "strategic"

이 구성에서는 빌드 컨테이너에 resource request가 설정됩니다.

모범 사례

  • 배포 전에 테스트 환경에서 추가된 pod_spec를 테스트하세요.

  • pod_spec 구성이 GitLab Runner가 생성한 사양에 부정적인 영향을 미치지 않도록 하세요.

  • 복잡한 pod 사양 업데이트에 대해 merge 패치 전략을 사용하지 마세요.

  • 가능할 경우 구성 가능할 때 config.toml을 사용하세요. 예를 들어, 다음 구성은 GitLab Runner가 설정한 첫 번째 환경 변수를 기존 목록에 추가하는 대신 사용자 정의 pod_spec에서 설정한 것으로 대체합니다.

concurrent = 1
check_interval = 1
log_level = "debug"
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = ""
  url = "https://gitlab.example.com"
  id = 0
  token = "__REDACTED__"
  token_obtained_at = 0001-01-01T00:00:00Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "kubernetes"
  shell = "bash"
  environment = ["FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=true", "CUSTOM_VAR=value"]
  [runners.kubernetes]
    image = "alpine"
    ...
    [[runners.kubernetes.pod_spec]]
      name = "build envvars"
      patch = '''
        containers:
        - env:
          - name: env1
            value: "value1"
          name: build
      '''
      patch_type = "strategic"

각 빌드 작업을 위한 PVC 생성하기: Pod Spec 수정

각 빌드 작업을 위한 PersistentVolumeClaim을 생성하려면 Pod Spec 기능을 활성화하는 방법을 확인해야 합니다.

Kubernetes는 Pod의 생명 주기에 연결된 일회용 PersistentVolumeClaim을 생성할 수 있도록 허용합니다.

이것은 동적 프로비저닝이 Kubernetes 클러스터에서 활성화되면 작동하며, 각 PVC가 새로운 Volume을 요청할 수 있게 해 주고, 이 볼륨 또한 Pod의 수명에 연결됩니다.

동적 프로비저닝이 활성화된 후, 다음과 같이 config.toml을 수정하여 일회용 PVC를 생성할 수 있습니다:

[[runners.kubernetes.pod_spec]]
  name = "ephemeral-pvc"
  patch = '''
    containers:
    - name: build
      volumeMounts:
      - name: builds
        mountPath: /builds
    - name: helper
      volumeMounts:
      - name: builds
        mountPath: /builds
    volumes:
    - name: builds
      ephemeral:
        volumeClaimTemplate:
          spec:
            storageClassName: <동적 프로비저닝으로 볼륨을 생성할 스토리지 클래스>
            accessModes: [ ReadWriteOnce ]
            resources:
              requests:
                storage: 1Gi
  '''

Pod의 보안 정책 설정하기

config.toml에서 보안 컨텍스트를 구성하여 빌드 Pod의 보안 정책을 설정합니다.

다음 옵션을 사용하세요:

옵션 유형 필수 설명
fs_group int 아니요 Pod의 모든 컨테이너에 적용되는 특수 보조 그룹입니다.
run_as_group int 아니요 컨테이너 프로세스의 진입점이 실행될 GID입니다.
run_as_non_root boolean 아니요 컨테이너가 비루트 사용자로 실행되어야 함을 나타냅니다.
run_as_user int 아니요 컨테이너 프로세스의 진입점이 실행될 UID입니다.
supplemental_groups int 목록 아니요 각 컨테이너에서 실행되는 첫 번째 프로세스에 적용되는 그룹 목록입니다. 주요 GID 외에 추가됩니다.
selinux_type string 아니요 Pod의 모든 컨테이너에 적용되는 SELinux 유형 레이블입니다.

config.toml에서의 Pod 보안 컨텍스트 예제:

concurrent = %(concurrent)s
check_interval = 30
  [[runners]]
    name = "myRunner"
    url = "gitlab.example.com"
    executor = "kubernetes"
    [runners.kubernetes]
      helper_image = "gitlab-registry.example.com/helper:latest"
      [runners.kubernetes.pod_security_context]
        run_as_non_root = true
        run_as_user = 59417
        run_as_group = 59417
        fs_group = 59417

오래된 러너 팟 제거

가끔 오래된 러너 팟이 정리되지 않을 수 있습니다. 이는 러너 관리자가 잘못 종료되었을 때 발생할 수 있습니다.

이 상황을 처리하기 위해 GitLab Runner Pod Cleanup 애플리케이션을 사용하여 오래된 팟의 정리를 예약할 수 있습니다. 더 많은 정보는 다음을 참조하세요:

  • GitLab Runner Pod Cleanup 프로젝트 README.
  • GitLab Runner Pod Cleanup 문서.

컨테이너에 대한 보안 정책 설정

config.toml 실행기에서 컨테이너 보안 컨텍스트를 구성하여 빌드, 헬퍼 또는 서비스 팟에 대한 컨테이너 보안 정책을 설정합니다.

다음 옵션을 사용하세요:

옵션 유형 필수 설명
run_as_group int 아니오 컨테이너 프로세스의 진입점을 실행할 GID입니다.
run_as_non_root boolean 아니오 컨테이너가 비루트 사용자로 실행되어야 함을 나타냅니다.
run_as_user int 아니오 컨테이너 프로세스의 진입점을 실행할 UID입니다.
capabilities.add string list 아니오 컨테이너 실행 시 추가할 기능입니다.
capabilities.drop string list 아니오 컨테이너 실행 시 삭제할 기능입니다.
selinux_type string 아니오 컨테이너 프로세스와 연결된 SELinux 유형 레이블입니다.

다음 예제는 config.toml의 보안 컨텍스트 구성입니다:

  • 팟 보안 컨텍스트를 설정합니다.
  • 빌드 및 헬퍼 컨테이너에 대한 run_as_userrun_as_group을 재정의합니다.
  • 모든 서비스 컨테이너가 팟 보안 컨텍스트에서 run_as_userrun_as_group를 상속받도록 지정합니다.
concurrent = 4
check_interval = 30
  [[runners]]
    name = "myRunner"
    url = "gitlab.example.com"
    executor = "kubernetes"
    [runners.kubernetes]
      helper_image = "gitlab-registry.example.com/helper:latest"
      [runners.kubernetes.pod_security_context]
        run_as_non_root = true
        run_as_user = 59417
        run_as_group = 59417
        fs_group = 59417
      [runners.kubernetes.init_permissions_container_security_context]
        run_as_user = 1000
        run_as_group = 1000
      [runners.kubernetes.build_container_security_context]
        run_as_user = 65534
        run_as_group = 65534
        [runners.kubernetes.build_container_security_context.capabilities]
          add = ["NET_ADMIN"]
      [runners.kubernetes.helper_container_security_context]
        run_as_user = 1000
        run_as_group = 1000
      [runners.kubernetes.service_container_security_context]
        run_as_user = 1000
        run_as_group = 1000

풀 정책 설정

config.toml 파일에서 pull_policy 매개변수를 사용하여 단일 또는 다중 풀 정책을 지정합니다.

정책은 이미지가 어떻게 가져오고 업데이트되는지를 제어하며, 빌드 이미지, 헬퍼 이미지 및 모든 서비스에 적용됩니다.

어떤 정책을 사용할지 결정하려면 풀 정책에 대한 Kubernetes 문서를 참조하세요.

단일 풀 정책의 경우:

[runners.kubernetes]
  pull_policy = "never"

다중 풀 정책의 경우:

[runners.kubernetes]
  # 다중 풀 정책 사용
  pull_policy = ["always", "if-not-present"]

여러 정책을 정의할 경우, 이미지를 성공적으로 가져올 때까지 각 정책이 시도됩니다.

예를 들어, [ always, if-not-present ]를 사용하면 if-not-present 정책은 always 정책이 임시 레지스트리 문제로 실패할 경우 사용됩니다.

실패한 풀을 재시도하려면:

[runners.kubernetes]
  pull_policy = ["always", "always"]

GitLab 명명 규칙은 Kubernetes 것과 다릅니다.

러너 풀 정책 Kubernetes 풀 정책 설명
blank blank Kubernetes에서 지정한 기본 정책을 사용합니다.
if-not-present IfNotPresent 이미 노드에 존재하지 않는 경우에만 이미지를 가져옵니다. 보안 고려 사항이 있습니다.
always Always 작업이 실행될 때마다 이미지를 가져옵니다.
never Never 이미지를 절대 가져오지 않으며, 노드에 이미 존재해야 합니다.

컨테이너 기능 지정

컨테이너에서 사용할 Kubernetes 기능을 지정할 수 있습니다.

컨테이너 기능을 지정하려면 config.toml 파일의 cap_addcap_drop 옵션을 사용하세요. 컨테이너 런타임은 Dockercontainer와 같은 기본 기능 목록을 정의할 수도 있습니다.

런너가 기본적으로 제거하는 기능의 목록이 있습니다.

cap_add 옵션에 나열한 기능은 제거 목록에서 제외됩니다.

config.toml 파일의 예시 구성:

concurrent = 1
check_interval = 30
[[runners]]
  name = "myRunner"
  url = "gitlab.example.com"
  executor = "kubernetes"
  [runners.kubernetes]
    # ...
    cap_add = ["SYS_TIME", "IPC_LOCK"]
    cap_drop = ["SYS_ADMIN"]
    # ...

기능을 지정할 때:

  • 사용자 정의 cap_drop이 사용자 정의 cap_add보다 우선합니다. 두 설정 모두에서 동일한 기능을 정의하는 경우, cap_drop에서 정의된 기능만 컨테이너에 전달됩니다.
  • 컨테이너 구성에 전달되는 기능 식별자에서 CAP_ 접두사를 제거하세요. 예를 들어, CAP_SYS_TIME 기능을 추가하거나 제거하려면, 구성 파일에 문자열 SYS_TIME을 입력합니다.
  • Kubernetes 클러스터의 소유자는 PodSecurityPolicy를 정의할 수 있습니다, 여기에서 특정 기능이 허용되거나 제한되거나 기본적으로 추가됩니다. 이러한 규칙은 사용자 정의 구성보다 우선합니다.

컨테이너 리소스 덮어쓰기

각 CI/CD 작업에 대한 Kubernetes CPU 및 메모리 할당을 덮어쓸 수 있습니다. 빌드 컨테이너, 헬퍼 컨테이너 및 서비스 컨테이너에 대한 요청과 제한에 대한 설정을 적용할 수 있습니다.

컨테이너 리소스를 덮어쓰려면 .gitlab-ci.yml 파일에서 다음 변수를 사용하세요.

변수의 값은 해당 리소스에 대한 최대 덮어쓰기 설정으로 제한됩니다. 리소스에 대한 최대 덮어쓰기가 설정되지 않은 경우, 변수는 사용되지 않습니다.

 variables:
   KUBERNETES_CPU_REQUEST: "3"
   KUBERNETES_CPU_LIMIT: "5"
   KUBERNETES_MEMORY_REQUEST: "2Gi"
   KUBERNETES_MEMORY_LIMIT: "4Gi"
   KUBERNETES_EPHEMERAL_STORAGE_REQUEST: "512Mi"
   KUBERNETES_EPHEMERAL_STORAGE_LIMIT: "1Gi"

   KUBERNETES_HELPER_CPU_REQUEST: "3"
   KUBERNETES_HELPER_CPU_LIMIT: "5"
   KUBERNETES_HELPER_MEMORY_REQUEST: "2Gi"
   KUBERNETES_HELPER_MEMORY_LIMIT: "4Gi"
   KUBERNETES_HELPER_EPHEMERAL_STORAGE_REQUEST: "512Mi"
   KUBERNETES_HELPER_EPHEMERAL_STORAGE_LIMIT: "1Gi"

   KUBERNETES_SERVICE_CPU_REQUEST: "3"
   KUBERNETES_SERVICE_CPU_LIMIT: "5"
   KUBERNETES_SERVICE_MEMORY_REQUEST: "2Gi"
   KUBERNETES_SERVICE_MEMORY_LIMIT: "4Gi"
   KUBERNETES_SERVICE_EPHEMERAL_STORAGE_REQUEST: "512Mi"
   KUBERNETES_SERVICE_EPHEMERAL_STORAGE_LIMIT: "1Gi"

서비스 목록 정의

  • GitLab Runner 16.9에서 HEALTCHECK_TCP_SERVICES에 대한 지원이 도입되었습니다. 링크

config.toml 파일에서 서비스 목록을 정의합니다.

concurrent = 1
check_interval = 30
  [[runners]]
    name = "myRunner"
    url = "gitlab.example.com"
    executor = "kubernetes"
    [runners.kubernetes]
      helper_image = "gitlab-registy.example.com/helper:latest"
      [[runners.kubernetes.services]]
        name = "postgres:12-alpine"
        alias = "db1"
      [[runners.kubernetes.services]]
        name = "registry.example.com/svc1"
        alias = "svc1"
        entrypoint = ["entrypoint.sh"]
        command = ["executable","param1","param2"]
        environment = ["ENV=value1", "ENV2=value2"]

서비스 환경에 HEALTHCHECK_TCP_PORT가 포함되어 있으면, GitLab Runner는 사용자 CI 스크립트를 시작하기 전에 해당 포트에서 서비스가 응답할 때까지 기다립니다. .gitlab-ci.ymlservices 섹션에서 HEALTHCHECK_TCP_PORT 환경 변수를 구성할 수도 있습니다.

서비스 컨테이너 리소스 덮어쓰기

작업에 여러 서비스 컨테이너가 있는 경우, 각 서비스 컨테이너에 명시적 리소스 요청 및 제한을 설정할 수 있습니다. 각 서비스에서 변수를 사용하여 .gitlab-ci.yml에 지정된 컨테이너 리소스를 덮어쓸 수 있습니다.

  services:
    - name: redis:5
      alias: redis5
      variables:
        KUBERNETES_SERVICE_CPU_REQUEST: "3"
        KUBERNETES_SERVICE_CPU_LIMIT: "6"
        KUBERNETES_SERVICE_MEMORY_REQUEST: "3Gi"
        KUBERNETES_SERVICE_MEMORY_LIMIT: "6Gi"
        KUBERNETES_EPHEMERAL_STORAGE_REQUEST: "2Gi"
        KUBERNETES_EPHEMERAL_STORAGE_LIMIT: "3Gi"
    - name: postgres:12
      alias: MY_relational-database.12
      variables:
        KUBERNETES_CPU_REQUEST: "2"
        KUBERNETES_CPU_LIMIT: "4"
        KUBERNETES_MEMORY_REQUEST: "1Gi"
        KUBERNETES_MEMORY_LIMIT: "2Gi"
        KUBERNETES_EPHEMERAL_STORAGE_REQUEST: "1Gi"
        KUBERNETES_EPHEMERAL_STORAGE_LIMIT: "2Gi"

이러한 특정 설정은 작업의 일반 설정보다 우선합니다.

값은 여전히 ​​해당 리소스에 대한 최대 덮어쓰기 설정으로 제한됩니다.

Kubernetes 기본 서비스 계정 덮어쓰기

.gitlab-ci.yml 파일에서 각 CI/CD 작업에 대한 Kubernetes 서비스 계정을 덮어쓰려면, 변수 KUBERNETES_SERVICE_ACCOUNT_OVERWRITE를 설정하세요.

이 변수를 사용하여 복잡한 RBAC 구성에 필요할 수 있는 네임스페이스에 첨부된 서비스 계정을 지정할 수 있습니다.

variables:
  KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: ci-service-account

CI 실행 중에 지정된 서비스 계정만 사용하도록 하려면, 다음 중 하나에 대한 정규 표현식을 정의하세요:

  • service_account_overwrite_allowed 설정.
  • KUBERNETES_SERVICE_ACCOUNT_OVERWRITE_ALLOWED 환경 변수.

둘 다 설정하지 않으면, 덮어쓰기가 비활성화됩니다.

RuntimeClass 설정

runtime_class_name을 사용하여 각 작업 컨테이너의 RuntimeClass를 설정하세요.

RuntimeClass 이름을 지정하고 클러스터에 구성되지 않았거나 기능이 지원되지 않으면, 실행자는 작업을 생성하지 못합니다.

concurrent = 1
check_interval = 30
  [[runners]]
    name = "myRunner"
    url = "gitlab.example.com"
    executor = "kubernetes"
    [runners.kubernetes]
      runtime_class_name = "myclass"

빌드 로그 및 스크립트를 위한 기본 디렉터리 변경

emptyDir 볼륨이 빌드 로그 및 스크립트를 위한 포드에 마운트되는 디렉토리를 변경할 수 있습니다.

디렉토리를 사용하여:

  • 수정된 이미지를 사용하여 작업 포드를 실행합니다.
  • 비특권 사용자로 실행합니다.
  • SecurityContext 설정을 사용자 지정합니다.

디렉터리를 변경하려면:

  • 빌드 로그의 경우 logs_base_dir를 설정합니다.
  • 빌드 스크립트의 경우 scripts_base_dir를 설정합니다.

기대되는 값은 슬래시가 없는 기본 디렉토리를 나타내는 문자열입니다 (예: /tmp 또는 /mydir/example). 디렉터리는 이미 존재해야 합니다.

이 값은 빌드 로그 및 스크립스를 위한 생성된 경로에 추가됩니다. 예를 들어:

  [[runners]]
    name = "myRunner"
    url = "gitlab.example.com"
    executor = "kubernetes"
    [runners.kubernetes]
      logs_base_dir = "/tmp"
      scripts_base_dir = "/tmp"

이 구성은 다음과 같은 emptyDir 볼륨을 마운트합니다:

  • /tmp/logs-${CI_PROJECT_ID}-${CI_JOB_ID} 빌드 로그용 기본값인 /logs-${CI_PROJECT_ID}-${CI_JOB_ID} 대신입니다.
  • /tmp/scripts-${CI_PROJECT_ID}-${CI_JOB_ID} 빌드 스크립트용입니다.

사용자 네임스페이스

Kubernetes 1.30 이상에서, 컨테이너에서 실행되는 사용자를 호스트의 사용자와 격리할 수 있는 사용자 네임스페이스를 사용할 수 있습니다.

컨테이너 내에서 root로 실행되는 프로세스는 호스트에서 다른 비특권 사용자로 실행될 수 있습니다.

사용자 네임스페이스를 사용하면 CI/CD 작업을 실행하는 데 사용되는 이미지에 대한 더 많은 제어를 할 수 있습니다.

추가 설정이 필요한 작업(예: root로 실행)을 수행할 수 있으며, 호스트에 대한 추가 공격 표면을 열지 않고도 작동할 수 있습니다.

이 기능을 사용하려면 클러스터가 적절하게 구성되었는지 확인하세요.

다음 예제에서는 hostUsers 키에 대한 pod_spec을 추가하고 특권 포드 및 권한 상승을 모두 비활성화합니다:

  [[runners]]
    environment = ["FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=true"]
    builds_dir = "/tmp/builds"
  [runners.kubernetes]
    logs_base_dir = "/tmp"
    scripts_base_dir = "/tmp"
    privileged = false
    allowPrivilegeEscalation = false
  [[runners.kubernetes.pod_spec]]
    name = "hostUsers"
    patch = '''
      [{"op": "add", "path": "/hostUsers", "value": false}]
    '''
    patch_type = "json"

사용자 네임스페이스를 사용할 때는 빌드 디렉토리(builds_dir), 빌드 로그(logs_base_dir), 또는 빌드 스크립트(scripts_base_dir)에 대한 기본 경로를 사용할 수 없습니다.

그렇지 않으면, 컨테이너의 root 사용자조차도 볼륨을 마운트하거나 컨테이너 파일 시스템의 루트에 디렉터리를 생성할 권한이 없습니다.

대신, 빌드 로그 및 스크립트의 기본 디렉토리를 변경할 수 있습니다. [[runners]].builds_dir를 설정하여 빌드 디렉토리를 변경할 수도 있습니다.

운영 체제, 아키텍처 및 Windows 커널 버전

Kubernetes 실행기를 사용하는 GitLab Runner는 구성된 클러스터에 해당 운영 체제를 실행하는 노드가 있는 경우 다양한 운영 체제에서 빌드를 실행할 수 있습니다.

시스템은 헬퍼 이미지의 운영 체제, 아키텍처 및 Windows 커널 버전(해당되는 경우)을 결정합니다. 그런 다음 이 매개변수를 다른 빌드 측면, 예를 들어 사용할 컨테이너나 이미지를 위해 사용합니다.

다음 다이어그램은 시스템이 이러한 세부 정보를 감지하는 방법을 설명합니다:

%%|fig-align: center flowchart TB init[<b>초기 기본값</b>:<br/>운영 체제: linux</br>아키텍처: amd64] hasAutoset{구성<br/><tt><a href="https://docs.gitlab.com/runner/configuration/advanced-configuration.html">helper_image_autoset_arch_and_os</a> == true</tt>?} setArch[<b>업데이트</b>:<br/>아키텍처: <i>러너와 동일</i>] isWin{GitLab Runner가 Windows에서 실행되나요?} setWin[<b>업데이트</b>:<br/>운영 체제: windows<br/>커널 버전: <i>러너와 동일</i>] hasNodeSel{<a href="https://docs.gitlab.com/runner/configuration/advanced-configuration.html"><tt>node_selector</tt></a>가<br/> <tt>runners.kubernetes</tt> 섹션에 구성됨?} hasNodeSelOverride{<tt>node_selector</tt>가<br/><a href="https://docs.gitlab.com/runner/executors/kubernetes/#overwrite-the-node-selector">오버라이드로</a> 구성됨?} updateNodeSel[<b><tt>node_selector</tt>에서 업데이트</b>가 설정된 경우:<br/>운영 체제: <tt>kubernetes.io/os</tt>에서<br/>아키텍처: <tt>kubernetes.io/arch</tt>에서<br/>커널 버전: <tt>node.kubernetes.io/windows-build</tt>에서] updateNodeSelOverride[<b><tt>node_selector</tt> 오버라이드를 통해 업데이트</b>가 설정된 경우:</br>운영 체제: <tt>kubernetes.io/os</tt>에서<br/>아키텍처: <tt>kubernetes.io/arch</tt>에서<br/>커널 버전: <tt>node.kubernetes.io/windows-build</tt>에서] result[최종 <b>운영 체제</b>, <b>아키텍처</b>, <b>커널 버전</b>] init --> hasAutoset hasAutoset -->|false | hasNodeSel hasAutoset -->|true | setArch setArch --> isWin isWin -->|false | hasNodeSel isWin -->|true | setWin setWin --> hasNodeSel hasNodeSel -->|false | hasNodeSelOverride hasNodeSel -->|true | updateNodeSel updateNodeSel --> hasNodeSelOverride hasNodeSelOverride -->|false | result hasNodeSelOverride -->|true | updateNodeSelOverride updateNodeSelOverride --> result

다음은 빌드의 운영 체제, 아키텍처 및 Windows 커널 버전 선택에 영향을 미치는 유일한 매개변수입니다.

  • helper_image_autoset_arch_and_os 구성
  • kubernetes.io/os, kubernetes.io/archnode.kubernetes.io/windows-build 레이블 선택기:
    • node_selector 구성
    • node_selector 오버라이드

위에 설명된 선택 프로세스에는 다른 매개변수가 영향을 미치지 않습니다. 그러나, 예를 들어 affinity 구성은 빌드가 예약될 노드를 추가로 제한하는 데 사용될 수 있습니다.

노드

빌드를 실행할 노드 지정

node_selector 옵션을 사용하여 Kubernetes 클러스터에서 빌드를 실행할 수 있는 노드를 지정합니다.

이는 string=string 형식의 key=value 쌍입니다. (환경 변수의 경우 string:string).

러너는 제공된 정보를 사용하여 빌드를 위한 운영 체제 및 아키텍처를 결정합니다. 이는 정확한 헬퍼 이미지가 사용되도록 보장합니다. 기본 운영 체제 및 아키텍처는 linux/amd64입니다.

특정 레이블을 사용하여 서로 다른 운영 체제와 아키텍처를 가진 노드를 예약할 수 있습니다.

linux/arm64 예제

  [[runners]]
    name = "myRunner"
    url = "gitlab.example.com"
    executor = "kubernetes"

    [runners.kubernetes.node_selector]
      "kubernetes.io/arch" = "arm64"
      "kubernetes.io/os" = "linux"

windows/amd64 예제

Windows용 Kubernetes에는 특정 제한 사항이 있습니다.

프로세스 격리를 사용하는 경우, node.kubernetes.io/windows-build 레이블과 함께 특정 Windows 빌드 버전을 제공해야 합니다.

  [[runners]]
    name = "myRunner"
    url = "gitlab.example.com"
    executor = "kubernetes"

    # PowerShell이 Windows 노드를 대상으로 할 때 Linux 환경에서 경로를 올바르게 해결할 수 있도록
    # FF_USE_POWERSHELL_PATH_RESOLVER 기능 플래그를 활성화해야 합니다.
    environment = ["FF_USE_POWERSHELL_PATH_RESOLVER=true"]

    [runners.kubernetes.node_selector]
      "kubernetes.io/arch" = "amd64"
      "kubernetes.io/os" = "windows"
      "node.kubernetes.io/windows-build" = "10.0.20348"

노드 선택기 덮어쓰기

노드 선택기를 덮어쓰려면:

  1. config.toml 또는 Helm values.yaml 파일에서 노드 선택기 덮어쓰기를 활성화합니다:

    runners:
     ...
     config: |
       [[runners]]
         [runners.kubernetes]
           node_selector_overwrite_allowed = ".*"
    
  2. .gitlab-ci.yml 파일에서 노드 선택기를 덮어쓰는 변수를 정의합니다:

    variables:
      KUBERNETES_NODE_SELECTOR_* = ''
    

아래 예제에서는 Kubernetes 노드 아키텍처를 덮어쓰기 위해 설정이 config.toml.gitlab-ci.yml 파일에 구성됩니다:

config.toml
concurrent = 1
check_interval = 1
log_level = "debug"
shutdown_timeout = 0

listen_address = ':9252'

[session_server]
  session_timeout = 1800

[[runners]]
  name = ""
  url = "https://gitlab.com/"
  id = 0
  token = "__REDACTED__"
  token_obtained_at = "0001-01-01T00:00:00Z"
  token_expires_at = "0001-01-01T00:00:00Z"
  executor = "kubernetes"
  shell = "bash"
  [runners.kubernetes]
    host = ""
    bearer_token_overwrite_allowed = false
    image = "alpine"
    namespace = ""
    namespace_overwrite_allowed = ""
    pod_labels_overwrite_allowed = ""
    service_account_overwrite_allowed = ""
    pod_annotations_overwrite_allowed = ""
    node_selector_overwrite_allowed = "kubernetes.io/arch=.*" # <--- 아키텍처 덮어쓰기를 허용
.gitlab-ci.yml
job:
  image: IMAGE_NAME
  variables:
    KUBERNETES_NODE_SELECTOR_ARCH: 'kubernetes.io/arch=amd64'  # <--- 아키텍처 선택

노드 선호도 목록 정의

빌드 시 포드 사양에 추가할 노드 선호도 목록을 정의합니다.

주의:

node_affinities는 빌드가 실행될 운영 체제를 결정하지 않으며, 오직 node_selectors만 결정합니다. 자세한 내용은 운영 체제, 아키텍처 및 Windows 커널 버전을 참조하세요.

config.toml에서의 예시 구성:

concurrent = 1
[[runners]]
  name = "myRunner"
  url = "gitlab.example.com"
  executor = "kubernetes"
  [runners.kubernetes]
    [runners.kubernetes.affinity]
      [runners.kubernetes.affinity.node_affinity]
        [[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution]]
          weight = 100
          [runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference]
            [[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference.match_expressions]]
              key = "cpu_speed"
              operator = "In"
              values = ["fast"]
            [[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference.match_expressions]]
              key = "mem_speed"
              operator = "In"
              values = ["fast"]
        [[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution]]
          weight = 50
          [runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference]
            [[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference.match_expressions]]
              key = "core_count"
              operator = "In"
              values = ["high", "32"]
            [[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference.match_fields]]
              key = "cpu_type"
              operator = "In"
              values = ["arm64"]
      [runners.kubernetes.affinity.node_affinity.required_during_scheduling_ignored_during_execution]
        [[runners.kubernetes.affinity.node_affinity.required_during_scheduling_ignored_during_execution.node_selector_terms]]
          [[runners.kubernetes.affinity.node_affinity.required_during_scheduling_ignored_during_execution.node_selector_terms.match_expressions]]
            key = "kubernetes.io/e2e-az-name"
            operator = "In"
            values = [
              "e2e-az1",
              "e2e-az2"
            ]

포드가 예약되는 노드 정의

포드 친화성과 비친화성을 사용하여 노드를 제한합니다.

your pod is eligible 포드가 예약될 수 있도록, 다른 포드의 레이블에 기반합니다.

config.toml에서의 예시 구성:

concurrent = 1
[[runners]]
  name = "myRunner"
  url = "gitlab.example.com"
  executor = "kubernetes"
  [runners.kubernetes]
    [runners.kubernetes.affinity]
      [runners.kubernetes.affinity.pod_affinity]
        [[runners.kubernetes.affinity.pod_affinity.required_during_scheduling_ignored_during_execution]]
          topology_key = "failure-domain.beta.kubernetes.io/zone"
          namespaces = ["namespace_1", "namespace_2"]
          [runners.kubernetes.affinity.pod_affinity.required_during_scheduling_ignored_during_execution.label_selector]
            [[runners.kubernetes.affinity.pod_affinity.required_during_scheduling_ignored_during_execution.label_selector.match_expressions]]
              key = "security"
              operator = "In"
              values = ["S1"]
        [[runners.kubernetes.affinity.pod_affinity.preferred_during_scheduling_ignored_during_execution]]
          weight = 100
          [runners.kubernetes.affinity.pod_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term]
            topology_key = "failure-domain.beta.kubernetes.io/zone"
            [runners.kubernetes.affinity.pod_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.label_selector]
              [[runners.kubernetes.affinity.pod_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.label_selector.match_expressions]]
                key = "security_2"
                operator = "In"
                values = ["S2"]
      [runners.kubernetes.affinity.pod_anti_affinity]
        [[runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution]]
          topology_key = "failure-domain.beta.kubernetes.io/zone"
          namespaces = ["namespace_1", "namespace_2"]
          [runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution.label_selector]
            [[runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution.label_selector.match_expressions]]
              key = "security"
              operator = "In"
              values = ["S1"]
          [runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution.namespace_selector]
            [[runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution.namespace_selector.match_expressions]]
              key = "security"
              operator = "In"
              values = ["S1"]
        [[runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution]]
          weight = 100
          [runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term]
            topology_key = "failure-domain.beta.kubernetes.io/zone"
            [runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.label_selector]
              [[runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.label_selector.match_expressions]]
                key = "security_2"
                operator = "In"
                values = ["S2"]
            [runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.namespace_selector]
              [[runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.namespace_selector.match_expressions]]
                key = "security_2"
                operator = "In"
                values = ["S2"]

네트워킹

컨테이너 생애 주기 후크 구성

컨테이너 생애 주기 후크를 사용하여 해당 생애 주기 후크가 실행될 때 핸들러에 대해 구성된 코드를 실행합니다.

두 가지 유형의 후크를 구성할 수 있습니다: PreStopPostStart. 각 후크는 한 가지 유형의 핸들러만 설정할 수 있습니다.

config.toml 파일의 예제 구성:

[[runners]]
  name = "kubernetes"
  url = "https://gitlab.example.com/"
  executor = "kubernetes"
  token = "yrnZW46BrtBFqM7xDzE7dddd"
  [runners.kubernetes]
    image = "alpine:3.11"
    privileged = true
    namespace = "default"
    [runners.kubernetes.container_lifecycle.post_start.exec]
      command = ["touch", "/builds/postStart.txt"]
    [runners.kubernetes.container_lifecycle.pre_stop.http_get]
      port = 8080
      host = "localhost"
      path = "/test"
      [[runners.kubernetes.container_lifecycle.pre_stop.http_get.http_headers]]
        name = "header_name_1"
        value = "header_value_1"
      [[runners.kubernetes.container_lifecycle.pre_stop.http_get.http_headers]]
        name = "header_name_2"
        value = "header_value_2"

각 생애 주기 후크를 구성하는 데 사용할 수 있는 설정은 다음과 같습니다:

옵션 유형 필수 설명
exec KubernetesLifecycleExecAction 아니요 Exec는 수행할 작업을 지정합니다.
http_get KubernetesLifecycleHTTPGet 아니요 HTTPGet은 수행할 http 요청을 지정합니다.
tcp_socket KubernetesLifecycleTcpSocket 아니요 TCPsocket은 TCP 포트와 관련된 작업을 지정합니다.

KubernetesLifecycleExecAction

옵션 유형 필수 설명
command string 목록 컨테이너 내에서 실행할 명령어입니다.

KubernetesLifecycleHTTPGet

옵션 유형 필수 설명
port int 컨테이너에서 접근할 포트 번호입니다.
host string 아니요 연결할 호스트 이름으로, 기본적으로 파드 IP로 설정됩니다(선택 사항).
path string 아니요 HTTP 서버에서 접근할 경로입니다(선택 사항).
scheme string 아니요 호스트에 연결할 때 사용하는 스킴으로, 기본적으로 HTTP입니다(선택 사항).
http_headers KubernetesLifecycleHTTPGetHeader 목록 아니요 요청에 설정할 사용자 정의 헤더입니다(선택 사항).

KubernetesLifecycleHTTPGetHeader

옵션 유형 필수 설명
name string HTTP 헤더 이름입니다.
value string HTTP 헤더 값입니다.

KubernetesLifecycleTcpSocket

옵션 유형 필수 설명
port int 컨테이너에서 접근할 포트 번호입니다.
host string 아니오 연결할 호스트 이름, 기본값은 포드 IP입니다(선택적).

포드 DNS 설정 구성

다음 옵션을 사용하여 포드의 DNS 설정을 구성합니다.

옵션 유형 필수 설명
nameservers string 리스트 아니오 포드에 대한 DNS 서버로 사용될 IP 주소의 목록입니다.
options KubernetesDNSConfigOption 아니오 각 객체가 필수 속성인 이름과 선택적 속성인 값을 가질 수 있는 객체 목록입니다.
searches string 리스트 아니오 포드에서 호스트 이름을 조회하기 위한 DNS 검색 도메인의 목록입니다.

config.toml 파일의 예제 구성:

concurrent = 1
check_interval = 30
[[runners]]
  name = "myRunner"
  url = "https://gitlab.example.com"
  token = "__REDACTED__"
  executor = "kubernetes"
  [runners.kubernetes]
    image = "alpine:latest"
    [runners.kubernetes.dns_config]
      nameservers = [
        "1.2.3.4",
      ]
      searches = [
        "ns1.svc.cluster-domain.example",
        "my.dns.search.suffix",
      ]

      [[runners.kubernetes.dns_config.options]]
        name = "ndots"
        value = "2"

      [[runners.kubernetes.dns_config.options]]
        name = "edns0"

KubernetesDNSConfigOption

옵션 유형 필수 설명
name string 구성 옵션 이름입니다.
value *string 아니오 구성 옵션 값입니다.

기본 드롭된 기능 목록

GitLab Runner는 기본적으로 다음 기능을 드롭합니다.

사용자 정의 cap_add가 기본 드롭된 기능 목록보다 우선합니다.

기본적으로 드롭된 기능을 추가하려면 cap_add에 추가하세요.

  • NET_RAW

추가 호스트 별칭 추가

이 프리미엄 기능은 Kubernetes 1.7 이상에서 사용할 수 있습니다.

Kubernetes에 컨테이너의 /etc/hosts 파일에 항목을 추가하도록 지시하기 위해 호스트 별칭을 구성합니다.

다음 옵션을 사용하세요:

옵션 유형 필수 설명
IP string 호스트를 연결하려는 IP 주소입니다.
Hostnames string 리스트 IP에 연결될 호스트 이름 별칭 목록입니다.

config.toml 파일의 예제 구성:

concurrent = 4

[[runners]]
  # 일반 구성
  executor = "kubernetes"
  [runners.kubernetes]
    [[runners.kubernetes.host_aliases]]
      ip = "127.0.0.1"
      hostnames = ["web1", "web2"]
    [[runners.kubernetes.host_aliases]]
      ip = "192.168.1.1"
      hostnames = ["web14", "web15"]

또한 JSON 입력이 포함된 명령줄 매개변수 --kubernetes-host_aliases를 사용하여 호스트 별칭을 구성할 수 있습니다. 예를 들어:

gitlab-runner register --kubernetes-host_aliases '[{"ip":"192.168.1.100","hostnames":["myservice.local"]},{"ip":"192.168.1.101","hostnames":["otherservice.local"]}]'

볼륨

Kubernetes 실행자와 함께 캐시 사용하기

Kubernetes 실행자와 함께 캐시를 사용할 때, /cache라는 볼륨이 파드에 마운트됩니다.

작업 실행 중, 캐시된 데이터가 필요할 경우, 러너는 캐시된 데이터가 사용 가능한지 확인합니다.

캐시된 데이터는 압축된 파일이 캐시 볼륨에 있을 때 사용 가능합니다.

캐시 볼륨을 설정하려면, config.toml 파일의 cache_dir 설정을 사용하세요.

  • 사용 가능한 경우, 압축된 파일이 빌드 폴더로 추출되어 작업에서 사용할 수 있습니다.

  • 사용 가능하지 않은 경우, 캐시된 데이터는 구성된 저장소에서 다운로드되어 cache dir에 압축된 파일로 저장됩니다. 그런 다음 압축된 파일이 build 폴더로 추출됩니다.

볼륨 유형 구성하기

다음 볼륨 유형을 마운트할 수 있습니다:

  • hostPath
  • persistentVolumeClaim
  • configMap
  • secret
  • emptyDir
  • csi

여러 볼륨 유형이 포함된 구성의 예:

concurrent = 4

[[runners]]
  # 일반 구성
  executor = "kubernetes"
  [runners.kubernetes]
    [[runners.kubernetes.volumes.host_path]]
      name = "hostpath-1"
      mount_path = "/path/to/mount/point"
      read_only = true
      host_path = "/path/on/host"
    [[runners.kubernetes.volumes.host_path]]
      name = "hostpath-2"
      mount_path = "/path/to/mount/point_2"
      read_only = true
    [[runners.kubernetes.volumes.pvc]]
      name = "pvc-1"
      mount_path = "/path/to/mount/point1"
    [[runners.kubernetes.volumes.config_map]]
      name = "config-map-1"
      mount_path = "/path/to/directory"
      [runners.kubernetes.volumes.config_map.items]
        "key_1" = "relative/path/to/key_1_file"
        "key_2" = "key_2"
    [[runners.kubernetes.volumes.secret]]
      name = "secrets"
      mount_path = "/path/to/directory1"
      read_only = true
      [runners.kubernetes.volumes.secret.items]
        "secret_1" = "relative/path/to/secret_1_file"
    [[runners.kubernetes.volumes.empty_dir]]
      name = "empty-dir"
      mount_path = "/path/to/empty_dir"
      medium = "Memory"
    [[runners.kubernetes.volumes.csi]]
      name = "csi-volume"
      mount_path = "/path/to/csi/volume"
      driver = "my-csi-driver"
      [runners.kubernetes.volumes.csi.volume_attributes]
        size = "2Gi"

hostPath 볼륨

지정된 호스트 경로를 컨테이너에 마운트하기 위해 hostPath 볼륨을 구성하세요.

config.toml 파일에서 다음 옵션을 사용하세요:

옵션 유형 필수 여부 설명
name string 볼륨의 이름입니다.
mount_path string 볼륨이 마운트되는 컨테이너 내 경로입니다.
sub_path string 아니오 루트 대신 볼륨 안에 서브 경로를 마운트합니다.
host_path string 아니오 볼륨으로 마운트 할 호스트 경로입니다. 지정하지 않으면 mount_path와 동일한 경로로 설정됩니다.
read_only boolean 아니오 볼륨을 읽기 전용 모드로 설정합니다(기본값은 false입니다).

persistentVolumeClaim 볼륨

persistentVolumeClaim 볼륨을 구성하여

Kubernetes에 Kubernetes 클러스터에서 정의된 persistentVolumeClaim을 사용하고 이를 컨테이너에 마운트하도록 지시합니다.

config.toml 파일에 다음 옵션을 사용하세요:

옵션 유형 필수 설명
name string 볼륨의 이름이자 사용해야 할 PersistentVolumeClaim의 이름입니다. 변수를 지원합니다. 자세한 정보는 동시 빌드 볼륨을 지속적으로 유지하기를 참조하세요.
mount_path string 볼륨이 마운트되는 컨테이너 내 경로입니다.
read_only boolean 아니오 볼륨을 읽기 전용 모드로 설정합니다(기본값은 false입니다).
sub_path string 아니오 루트 대신 볼륨 내에 서브 경로를 마운트합니다.

configMap 볼륨

configMap 볼륨을 구성하여 Kubernetes에

Kubernetes 클러스터에서 정의된 configMap을 사용하고 이를 컨테이너에 마운트하도록 지시합니다.

config.toml에 다음 옵션을 사용하세요:

옵션 유형 필수 설명
name string 볼륨의 이름이자 사용해야 할 _configMap_의 이름입니다.
mount_path string 볼륨이 마운트되는 컨테이너 내 경로입니다.
read_only boolean 아니오 볼륨을 읽기 전용 모드로 설정합니다(기본값은 false입니다).
sub_path string 아니오 루트 대신 볼륨 내에 서브 경로를 마운트합니다.
items map[string]string 아니오 사용해야 할 _configMap_의 키-경로 매핑입니다.

configMap의 각 키는 파일로 변경되어 마운트 경로에 저장됩니다. 기본적으로:

  • 모든 키가 포함됩니다.
  • configMap 키가 파일 이름으로 사용됩니다.
  • 값은 파일 내용으로 저장됩니다.

기본 키 및 값 저장 방식을 변경하려면 items 옵션을 사용하세요. items 옵션을 사용하는 경우, 지정된 키만 볼륨에 추가되고 다른 모든 키는 건너뜁니다.

참고: 존재하지 않는 키를 사용하는 경우, 작업이 포드 생성 단계에서 실패합니다.

secret 볼륨

secret 볼륨을 구성하여 Kubernetes에

Kubernetes 클러스터에서 정의된 secret을 사용하고 이를 컨테이너에 마운트하도록 지시합니다.

config.toml 파일에 다음 옵션을 사용하세요:

옵션 유형 필수 설명
name string 볼륨의 이름이자 사용해야 할 _secret_의 이름입니다.
mount_path string 볼륨이 마운트되는 컨테이너 내 경로입니다.
read_only boolean 아니오 볼륨을 읽기 전용 모드로 설정합니다(기본값은 false입니다).
sub_path string 아니오 루트 대신 볼륨 내에 서브 경로를 마운트합니다.
items map[string]string 아니오 사용해야 할 _configMap_의 키-경로 매핑입니다.

선택한 secret의 각 키는 선택한 마운트 경로에 저장된 파일로 변경됩니다. 기본적으로:

  • 모든 키가 포함됩니다.
  • configMap 키가 파일 이름으로 사용됩니다.
  • 값은 파일 내용으로 저장됩니다.

기본 키 및 값 저장 방식을 변경하려면 items 옵션을 사용하세요. items 옵션을 사용하는 경우, 지정된 키만 볼륨에 추가되고 다른 모든 키는 건너뜁니다.

참고: 존재하지 않는 키를 사용하는 경우, 작업이 포드 생성 단계에서 실패합니다.

emptyDir 볼륨

emptyDir 볼륨을 구성하여 Kubernetes에 컨테이너에 빈 디렉토리를 마운트하도록 지시합니다.

config.toml 파일에서 다음 옵션을 사용하세요:

옵션 타입 필수 설명
name 문자열 볼륨의 이름입니다.
mount_path 문자열 볼륨이 마운트되어야 하는 컨테이너 내부 경로입니다.
sub_path 문자열 아니오 루트 대신 볼륨의 서브 경로를 마운트합니다.
medium 문자열 아니오 “Memory”는 tmpfs를 제공하며, 기본적으로 노드 디스크 저장소를 사용합니다(기본값: “”).
size_limit 문자열 아니오 emptyDir 볼륨에 필요한 로컬 저장소의 총 용량입니다.

csi 볼륨

컨테이너 저장소 인터페이스(csi) 볼륨을 구성하여 Kubernetes에 사용자 지정 csi 드라이버를 사용하여 컨테이너에 임의의 저장 시스템을 마운트하도록 지시합니다.

config.toml에서 다음 옵션을 사용하세요:

옵션 타입 필수 설명
name 문자열 볼륨의 이름입니다.
mount_path 문자열 볼륨이 마운트되어야 하는 컨테이너 내부 경로입니다.
driver 문자열 사용할 볼륨 드라이버의 이름을 지정하는 문자열 값입니다.
fs_type 문자열 아니오 파일 시스템 유형의 이름을 지정하는 문자열 값입니다(예: “ext4”, “xfs”, “ntfs”).
volume_attributes map[string]string 아니오 CSI 볼륨 속성에 대한 키-값 쌍 매핑입니다.
sub_path 문자열 아니오 루트 대신 볼륨 내의 서브 경로를 마운트합니다.
read_only 불리언 아니오 볼륨을 읽기 전용 모드로 설정합니다(기본값: false).

서비스 컨테이너에 볼륨 마운트

빌드 컨테이너에 정의된 볼륨은 모든 서비스 컨테이너에 자동으로 마운트됩니다. 이 기능은 데이터베이스 저장소를 RAM에 마운트하여 테스트 속도를 높이기 위해 services_tmpfs 대신 사용할 수 있습니다(오직 Docker 실행자에서만 사용 가능).

config.toml 파일에서의 예시 구성:

[[runners]]
  # 일반 구성
  executor = "kubernetes"
  [runners.kubernetes]
    [[runners.kubernetes.volumes.empty_dir]]
      name = "mysql-tmpfs"
      mount_path = "/var/lib/mysql"
      medium = "Memory"

사용자 정의 볼륨 마운트

작업을 위한 빌드 디렉토리를 저장하려면 구성된 builds_dir(기본값: /builds)에 사용자 정의 볼륨 마운트를 정의하세요.

PVC 볼륨을 사용하는 경우, 접근 모드에 따라 한 노드에서만 작업을 실행해야 할 수도 있습니다.

config.toml 파일에서의 예시 구성:

concurrent = 4

[[runners]]
  # 일반 구성
  executor = "kubernetes"
  builds_dir = "/builds"
  [runners.kubernetes]
    [[runners.kubernetes.volumes.empty_dir]]
      name = "repo"
      mount_path = "/builds"
      medium = "Memory"

지속적인 동시 빌드 볼륨

Kubernetes CI 작업의 빌드 디렉토리는 기본적으로 일시적입니다.

작업 간에 Git 클론을 유지하려면(GIT_STRATEGY=fetch가 작동하도록 하려면),

빌드 폴더에 대한 지속적인 볼륨 클레임을 마운트해야 합니다.

여러 작업이 동시에 실행될 수 있으므로,

ReadWriteMany 볼륨을 사용하거나

같은 러너에서 잠재적인 동시 작업마다 하나의 볼륨을 가져야 합니다.

후자의 경우 더 높은 성능을 발휘할 가능성이 높습니다.

다음은 이러한 구성의 예입니다:

concurrent = 4

[[runners]]
  executor = "kubernetes"
  builds_dir = "/mnt/builds"
  [runners.kubernetes]
    [[runners.kubernetes.volumes.pvc]]
      # CI_CONCURRENT_ID는 같은 러너의 병렬 작업을 식별합니다.
      name = "build-pvc-$CI_CONCURRENT_ID"
      mount_path = "/mnt/builds"

이 예시에서는

build-pvc-0에서 build-pvc-3까지의 지속적 볼륨 클레임을

직접 생성해야 합니다.

러너의 concurrent 설정이 지시하는 만큼 생성하세요.

헬퍼 이미지 사용하기

보안 정책을 설정한 후,

헬퍼 이미지는 정책을 준수해야 합니다.

이미지는 루트 그룹의 권한을 받지 않으므로,

사용자 ID가 루트 그룹의 일부인지 확인해야 합니다.

참고: nonroot 환경만 필요하다면,

GitLab Runner UBI

GitLab Runner Helper UBI

OpenShift(OCP) 이미지를 헬퍼 이미지 대신 사용할 수 있습니다.

다음 예는 nonroot라는 사용자와 그룹을 생성하고

해당 사용자로 실행되도록 헬퍼 이미지를 설정합니다.

ARG tag
FROM registry.gitlab.com/gitlab-org/ci-cd/gitlab-runner-ubi-images/gitlab-runner-helper-ocp:${tag}
USER root
RUN groupadd -g 59417 nonroot && \
    useradd -u 59417 nonroot -g nonroot
WORKDIR /home/nonroot
USER 59417:59417

빌드에서 Docker 사용하기

빌드에서 Docker를 사용할 때,

알아야 할 몇 가지 고려사항이 있습니다.

노출된 /var/run/docker.sock

호스트의 /var/run/docker.sock을 빌드 컨테이너에 노출하기 위해

runners.kubernetes.volumes.host_path 옵션을 사용하는 경우,

특정 위험이 있습니다.

노드의 컨테이너는 빌드 컨테이너에서 접근할 수 있으며,

프로덕션 컨테이너와 동일한 클러스터에서 빌드를 실행하는 경우에는

그렇게 하는 것이 현명하지 않을 수 있습니다.

docker:dind 사용하기

docker:dind를 실행하면

docker-in-docker 이미지라고도 하며,

컨테이너는 특권 모드에서 실행해야 합니다.

이로 인해 잠재적인 위험이 있으며

추가적인 문제가 발생할 수 있습니다.

Docker 데몬은 팟에서 별도의 컨테이너로 실행되며

service로 시작되므로

일반적으로 .gitlab-ci.yml에서 실행됩니다.

팟의 컨테이너는 그들에게 할당된 볼륨과

서로 통신하는 데 사용하는 IP 주소만 공유합니다.

docker:dind 컨테이너는 /var/run/docker.sock을 공유하지 않으며

docker 바이너리는 기본적으로 이를 사용하려고 합니다.

클라이언트가 Docker 데몬에 TCP로 접속하도록 구성하려면,

다른 컨테이너에

빌드 컨테이너의 환경 변수를 포함하세요:

  • TLS 연결이 없는 경우 DOCKER_HOST=tcp://<hostname>:2375입니다.
  • TLS 연결이 있는 경우 DOCKER_HOST=tcp://<hostname>:2376입니다.

hostname의 값을 설정합니다:

  • GitLab Runner 12.7 이하, Kubernetes 1.6 이하의 경우 localhost입니다.
  • GitLab Runner 12.8 이상, Kubernetes 1.7 이상에서 docker입니다.

Docker 19.03 이상에서는

기본적으로 TLS가 활성화되어 있지만

클라이언트에 인증서를 매핑해야 합니다.

DIND에 대한 비 TLS 연결을 활성화하거나

인증서를 마운트할 수 있습니다.

자세한 내용은

Docker 실행기를 사용한 Docker In Docker 워크플로우 사용하기를 참조하세요.

호스트 커널 노출 방지

docker:dind 또는 /var/run/docker.sock을 사용하는 경우, Docker 데몬은 호스트 머신의 기본 커널에 접근할 수 있습니다. 이는 Docker 이미지를 빌드할 때 포드에 설정된 어떤 limits도 작동하지 않음을 의미합니다. Docker 데몬은 Kubernetes에서 생성된 Docker 빌드 컨테이너에 부과된 제한과 상관없이 노드의 전체 용량을 보고합니다.

빌드 컨테이너를 특권 모드로 실행하거나 /var/run/docker.sock이 노출되면, 호스트 커널이 빌드 컨테이너에 노출될 수 있습니다. 노출을 최소화하려면, node_selector 옵션에 라벨을 지정하세요. 이는 컨테이너가 노드에 배포되기 전에 노드가 라벨과 일치하는지 확인합니다. 예를 들어, role=ci 라벨을 지정하면, 빌드 컨테이너는 role=ci로 라벨링된 노드에서만 실행되며, 모든 다른 프로덕션 서비스는 다른 노드에서 실행됩니다.

빌드 컨테이너를 추가로 분리하기 위해, 노드 taints를 사용할 수 있습니다. Taints는 추가 구성 없이 빌드 포드와 동일한 노드에 다른 포드가 스케줄링되는 것을 방지합니다.

kaniko를 사용하여 Docker 이미지 빌드

Kubernetes 클러스터 내에서 Docker 이미지를 빌드하려면 kaniko를 사용할 수 있습니다.

Kaniko는 Docker 데몬 없이 작동하며, 특권 접근 권한 없이 이미지를 빌드합니다.

더 많은 정보는 kaniko 및 GitLab CI/CD로 이미지 빌드하기를 참조하세요.

kaniko를 사용하여 multi-stage Dockerfile을 빌드할 때 알려진 문제가 있습니다. 파이프라인 작업에 after_script 섹션이 포함되어 있으면, after_script 섹션이 실행될 때 다음 오류 메시지와 함께 실패합니다. 작업은 여전히 성공적으로 완료됩니다.

OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: chdir to cwd
("/workspace") set in config.json failed: no such file or directory: unknown

이 섹션은 kaniko가 multi-stage Dockerfile을 빌드할 때 컨테이너의 WORKDIR을 삭제하기 때문에 실패합니다. 이로 인해 kubectl exec (그리고 유사한 SDK API)이 컨테이너에 연결되지 못합니다.

이 문제에 대한 두 가지 우회 방법이 있습니다:

  • kaniko 실행 호출에 --ignore-path /workspace를 추가합니다.
  • kaniko 실행 호출 후에 작업의 scriptmkdir -p /workspace를 추가합니다.

더 많은 정보는 이슈 30769를 참조하세요.

Docker 이미지 및 서비스 제한

  • GitLab Runner 14.2에서 Kubernetes 실행자에 추가되었습니다.

작업을 실행하는 데 사용되는 Docker 이미지를 제한할 수 있습니다. 이를 위해 와일드카드 패턴을 지정합니다. 예를 들어, 개인 Docker 레지스트리에서 이미지만 허용하려면:

[[runners]]
  (...)
  executor = "kubernetes"
  [runners.kubernetes]
    (...)
    allowed_images = ["my.registry.tld:5000/*:*"]
    allowed_services = ["my.registry.tld:5000/*:*"]

또는 이 레지스트리에서 특정 이미지 목록으로 제한하려면:

[[runners]]
  (...)
  executor = "kubernetes"
  [runners.kubernetes]
    (...)
    allowed_images = ["my.registry.tld:5000/ruby:*", "my.registry.tld:5000/node:*"]
    allowed_services = ["postgres:9.4", "postgres:latest"]

Docker 풀 정책 제한

.gitlab-ci.yml 파일에서 풀 정책을 지정할 수 있습니다. 이 정책은 CI/CD 작업이 이미지를 가져오는 방식을 결정합니다.

.gitlab-ci.yml 파일에서 사용할 수 있는 풀 정책을 제한하려면 allowed_pull_policies를 사용합니다.

예를 들어, alwaysif-not-present 풀 정책만 허용하려면:

[[runners]]
  (...)
  executor = "kubernetes"
  [runners.kubernetes]
    (...)
    allowed_pull_policies = ["always", "if-not-present"]
  • allowed_pull_policies를 지정하지 않으면, 기본값은 pull_policy 키워드의 값입니다.
  • pull_policy를 지정하지 않으면 클러스터의 이미지 기본 풀 정책이 사용됩니다.
  • 기존의 pull_policy 키워드allowed_pull_policies에 지정되지 않은 풀 정책을 포함하면 안 됩니다. 포함된 경우 작업은 오류를 반환합니다.

작업 실행

  • 기본적으로 활성화된 기능 플래그 FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY 뒤에 있습니다.
  • GitLab Runner 14.0에서 기본적으로 attach 사용.

GitLab Runner는 기본적으로 kube attach를 사용합니다. 이는 작업이 중간에 성공으로 표시되는 문제를 방지해야 합니다. 불안정한 네트워크 환경에서 발생할 수 있습니다.

GitLab Runner 14.0으로 업데이트한 후 문제가 발생하면 기능 플래그 FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGYtrue로 전환하고 문제를 제출하세요.

레거시 실행 전략 제거에 대한 진행 상황은 문제 #27976를 참조하세요.

Kubernetes API에 대한 요청 시도 횟수 구성

기본적으로 Kubernetes 실행자는 Kubernetes API에 특정 요청을 5회 실패한 후 재시도합니다. 지연은 500밀리초 플로어와 기본값이 2초인 사용자 지정 가능한 상한을 가진 백오프 알고리즘으로 제어됩니다. 재시도 횟수와 백오프 상한을 구성하려면 config.toml 파일에서 각각 retry_limitretry_backoff_max 옵션을 사용합니다.

다음 실패는 자동으로 재시도됩니다:

각 오류에 대한 재시도 횟수를 제어하려면 retry_limits 옵션을 사용합니다.

retry_limits는 각 오류에 대한 재시도 횟수를 별도로 지정하며, 오류 메시지와 재시도 횟수의 맵입니다.

오류 메시지는 Kubernetes API에서 반환된 오류 메시지의 서브스트링일 수 있습니다.

retry_limits 옵션은 retry_limit 옵션보다 우선합니다.

예를 들어, TLS 관련 오류의 수를 제어해야 하는 경우, retry_limits 옵션을 구성하여 해당 오류를 기본 5회 대신 10회 재시도하도록 설정할 수 있습니다:

[[runners]]
  name = "myRunner"
  url = "https://gitlab.example.com/"
  executor = "kubernetes"
  [runners.kubernetes]
    retry_limit = 5

    [runners.kubernetes.retry_limits]
        "TLS handshake timeout" = 10
        "tls: internal error" = 10

exceeded quota와 같은 전혀 다른 오류를 20회 재시도하려면:

[[runners]]
  name = "myRunner"
  url = "https://gitlab.example.com/"
  executor = "kubernetes"
  [runners.kubernetes]
    retry_limit = 5

    [runners.kubernetes.retry_limits]
        "exceeded quota" = 20

컨테이너 엔트리포인트 알려진 문제

note
GitLab Runner 15.0에서는 Kubernetes 실행기와 함께 kube attach를 사용할 때 Docker 이미지에서 정의된 엔트리포인트를 사용합니다.
GitLab 15.1 이상에서는 FF_KUBERNETES_HONOR_ENTRYPOINT가 설정되어 있을 때 Docker 이미지에서 정의된 엔트리포인트가 Kubernetes 실행기와 함께 사용됩니다.

컨테이너 엔트리 포인트에는 다음과 같은 알려진 문제가 있습니다:

  • 이미지의 Dockerfile에 엔트리포인트가 정의된 경우, 유효한 셸을 열어야 합니다. 그렇지 않으면 작업이 중단됩니다.

    • 셸을 열기 위해 시스템은 명령을 args 매개변수로 빌드 컨테이너에 전달합니다.
  • 파일 유형 CI/CD 변수는 엔트리포인트가 실행될 때 디스크에 기록되지 않습니다. 파일은 오직 스크립트 실행 중에 작업에서만 접근할 수 있습니다.
  • 다음의 CI/CD 변수는 엔트리포인트에서 접근할 수 없습니다. before_script를 사용하여 스크립트 명령을 실행하기 전에 필요한 설정 변경을 수행할 수 있습니다:

GitLab Runner 17.4 이전:

  • 엔트리포인트 로그는 빌드 로그로 전달되지 않았습니다.
  • kube exec를 사용하는 Kubernetes 실행기와 함께 GitLab Runner는 엔트리포인트가 셸을 열기를 기다리지 않았습니다 (위의 open-valid-shell 참조).

GitLab Runner 17.4부터는 엔트리포인트 로그가 이제 전달됩니다. 시스템은 엔트리포인트가 실행되어 셸을 생성할 때까지 기다립니다. 이는 다음과 같은 영향을 미칩니다:

  • FF_KUBERNETES_HONOR_ENTRYPOINT가 설정되어 있고, 이미지의 엔트리포인트가 poll_timeout(기본값: 180초)보다 오래 걸릴 경우, 빌드가 실패합니다.
    엔트리포인트가 더 오래 실행될 것으로 예상되는 경우 poll_timeout 값(및 잠재적으로 poll_interval)을 조정해야 합니다.
  • FF_KUBERNETES_HONOR_ENTRYPOINT FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY가 설정되어 있을 때, 시스템은 빌드 컨테이너에
    시작 프로브를 추가하여 엔트리포인트가 셸을 생성할 때 알 수 있도록 합니다.
    사용자 정의 엔트리포인트가 제공된 args를 사용하여 예상되는 셸을 생성하는 경우, 시작 프로브가 자동으로 해결됩니다.
    그러나 컨테이너 이미지가 args를 통해 전달된 명령을 사용하지 않고 셸을 생성하는 경우, 엔트리포인트는 빌드 디렉터리의 루트에 .gitlab-startup-marker라는 파일을 생성하여 시작 프로브를 해결해야 합니다.
    시작 프로브는 .gitlab-startup-marker 파일을 위해 매 poll_interval마다 확인합니다. 파일이 poll_timeout 내에 존재하지 않으면, 파드는 비정상으로 간주되며 시스템은 빌드를 중단합니다.

작업 변수에 대한 접근 제한

Kubernetes 실행자를 사용할 때, Kubernetes 클러스터에 접근할 수 있는 사용자는 작업에 사용되는 변수를 읽을 수 있습니다. 기본적으로 작업 변수는 다음에 저장됩니다:

  • Pod의 환경 섹션

작업 변수 데이터를 보호하기 위해, GitLab 관리자가 GitLab Runner가 사용하는 네임스페이스에만 접근할 수 있도록 역할 기반 접근 제어(RBAC)를 사용해야 합니다.

다른 사용자가 GitLab Runner 네임스페이스에 접근할 수 있도록 하려면, 다음의 verbs를 설정하여 사용자가 GitLab Runner 네임스페이스에서 가지는 접근 유형을 제한하세요:

  • podsconfigmaps의 경우:
    • get
    • watch
    • list
  • pods/execpods/attach의 경우, create를 사용하세요.

인증된 사용자를 위한 예시 RBAC 정의:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitlab-runner-authorized-users
rules:
- apiGroups: [""]
  resources: ["configmaps", "pods"]
  verbs: ["get", "watch", "list"]
- apiGroups: [""]
  resources: ["pods/exec", "pods/attach"]
  verbs: ["create"]

준비 단계 동안의 리소스 확인

  • GitLab 15.0에 도입됨.
  • GitLab 15.2에서 업데이트됨.

전제 조건:

  • image_pull_secrets 또는 service_account가 설정되어 있어야 합니다.
  • resource_availability_check_max_attempts가 0보다 큰 숫자로 설정되어야 합니다.
  • getlist 권한으로 사용된 Kubernetes serviceAccount가 필요합니다.

GitLab Runner는 새로운 서비스 계정이나 비밀이 사용 가능한지 5초 간격으로 확인합니다.

  • GitLab 15.0 및 15.1에서는 이 기능을 비활성화할 수 없으며, 부정값이 설정되었을 때 기본값은 5입니다.
  • GitLab 15.0.1, 15.1.1, 15.2 및 이후 버전에서는 이 기능이 기본적으로 비활성화되어 있습니다. 이 기능을 활성화하려면 resource_availability_check_max_attempts0이 아닌 값으로 설정하세요.

설정한 값은 러너가 서비스 계정이나 비밀을 확인하는 횟수를 정의합니다.

Kubernetes 네임스페이스 재정의

전제 조건:

  • GitLab Runner Helm 차트의 values.yml 파일에서 rbac.clusterWideAccesstrue로 설정되어 있어야 합니다.
  • 러너가 권한을 core API 그룹에서 구성해야 합니다.

CI 목적으로 네임스페이스를 지정하기 위해 Kubernetes 네임스페이스를 재정의하고, 사용자 정의된 pods 세트를 배포할 수 있습니다. 러너에 의해 생성된 pods는 재정의된 네임스페이스에 있어 CI 단계 동안 컨테이너 간의 접근을 가능하게 합니다.

각 CI/CD 작업에 대한 Kubernetes 네임스페이스를 재정의하려면, .gitlab-ci.yml 파일의 KUBERNETES_NAMESPACE_OVERWRITE 변수를 설정하세요.

variables:
  KUBERNETES_NAMESPACE_OVERWRITE: ci-${CI_COMMIT_REF_SLUG}

참고: 이 변수는 클러스터에 네임스페이스를 생성하지 않습니다. 작업을 실행하기 전에 네임스페이스가 존재하는지 확인하세요.

CI 실행 중에 지정된 네임스페이스만 사용하려면, config.toml 파일에서 namespace_overwrite_allowed에 대한 정규 표현식을 정의하세요:

[runners.kubernetes]
    ...
    namespace_overwrite_allowed = "ci-.*"

Kubernetes 클러스터의 내결함성

GitLab Runner의 내결함성 기능은 러너 관리자가 재시작할 때 고아 리소스(예: Kubernetes 포드)와 실행 중 상태에 있는 작업을 방지하는 데 도움이 됩니다.

다음 단계는 일반적인 조건 하에서 작업 실행이 어떻게 작동하는지를 설명합니다.

러너 관리자는:

  1. GitLab에서 작업을 수신합니다.

  2. Kubernetes에서 작업 포드를 생성합니다.

  3. 작업 포드에서 실행될 명령을 보냅니다.

  4. 작업 로그 및 상태를 읽고, 정보를 GitLab에 다시 전송합니다.
    그러면 GitLab은 UI를 새로 고칩니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart LR accTitle: Kubernetes에서의 일반적인 작업 실행 흐름. accDescr: GitLab에서 러너 관리자, Kubernetes 작업 포드로 그리고 다시 GitLab으로의 작업 실행 흐름을 보여주는 다이어그램입니다. gitlab[(GitLab)] -.->|작업| manager((러너 관리자)) manager ===> |작업 로그/상태| gitlab manager -.->|생성| pod[[Kubernetes 작업 포드]] manager -.->|명령 전송| pod manager -.->|정리| pod pod ====>|작업 로그/상태| manager

Kubernetes에서 러너 관리자 포드를 호스팅하는 노드가 클러스터에서 CI/CD 작업을 조정할 때 제거되면, 러너 포드는 고아 상태가 됩니다.

그들은 다른 메커니즘에 의해 제거될 때까지 계속 실행됩니다.

새로운 러너 관리자는 활성 러너 포드와 관련된 CI/CD 작업에 접근할 수 없습니다.

결과적으로, 고아 러너 포드는 클러스터에서 계속 리소스를 소모합니다.

GitLab UI는 작업이 결국 구성된 타임아웃 때문에 실패할 때까지 작업 상태를 업데이트하지 않습니다.

내결함성 기능을 사용하면 GitLab Runner는 중단된 지점에서 작업을 다시 실행합니다.

GitLab Runner는 작업 및 각 작업의 실행 상태구성된 저장소에 저장합니다.

새로운 작업을 요청하기 전에, GitLab은 이미 실행 중인 작업이 있는지 저장소를 확인합니다.

내결함성 러너 관리자는:

  1. 실행자가 상태 저장 실행기인 경우, 구성된 저장소를 생성합니다.

    • 저장소가 구성되지 않았지만 실행자가 상태 저장인 경우, no-op(작업 없음) 저장소가 사용됩니다.
      no-op 저장소 덕분에 추가 논리 분기 없이 데이터 호출을 절약할 수 있습니다.

      store := NewNoopStore()
      if isStatefulExecutor := executor.(StatefulExecutor); isStatefulExecutor {
       store, _ = provider.GetStore(runnerConfig)
      }
      
  2. 작업을 평소와 같이 실행하지만, 주기적으로 또는 특정 이벤트 시 저장소에 기록합니다.

  3. 재시작 중에 저장소에서 실행 중인 작업을 확인합니다.

    작업이 최근에 업데이트되지 않았다면, 러너는:

    1. 작업을 재개합니다.

    2. 작업 실행 시작 중에 러너가 수많은 작업 로그를 생성하므로 로그 중복을 방지하기 위해 모든 추적 로그 작성을 비활성화합니다.

    3. 먼저 Kubernetes 실행기에서 상태 메타데이터를 복원합니다.

      type executorStateMetadata struct {
        // 실행자에 의해 생성된 비밀
       Credentials *api.Secret   `json:"credentials"`
       // 빌드 포드
       Pod         *api.Pod      `json:"pod"`
       // 서비스
       Services    []api.Service `json:"services"`
       // 오프셋은 빌드 포드에서 작업 로그를 읽는 오프셋입니다
       Offset      int64         `json:"offset"`
      }
      
      // 이러한 리소스의 이름과 네임스페이스만 저장소에 직렬화됩니다
      /*
      {
       credentials: { name: "", namespace: "" }
       pod: { name: "", namespace: "" }
       services: [{ name: "", namespace: "" }]
       offset: 0
      }
      */
      
    4. 작업 처리를 위해 ExecutorPrepare 메서드를 호출합니다.

    5. 추적 로그 작성을 다시 활성화하고 재개합니다.

    6. Kubernetes 클러스터에 대한 전체 API 객체를 쿼리하는 StatefulExecutor 인터페이스의 일환으로 Restore 메서드를 호출합니다.

      func (s *executor) Restore(ctx context.Context) error {
       s.state.Pod, _ = s.kubeClient.CoreV1().Pods(s.state.Pod.Namespace).Get(s.state.Pod.Name)
       s.state.Credentials, _ = s.kubeClient.CoreV1().Secrets(s.state.Credentials.Namespace).Get(s.state.Credentials.Name)
       // 서비스에 대해서도 동일하게 수행합니다
      
       return nil
      }
      
    7. 일반적인 Run 메서드 대신 StatefulExecutor 인터페이스의 Resume 메서드를 호출합니다.
      Resume 메서드는 Pod에 다시 연결하고 작업 추적 및 상태를 GitLab에 계속 전달합니다.

재시작 후, 새로운 작업 실행 메커니즘은 다음과 같이 작동합니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart LR accTitle: 재시작 후 내결함성 작업 실행 흐름. accDescr: 재시작 후 러너 관리자가 저장소에서 작업을 복원하고 Kubernetes 작업 포드에서 실행을 재개하는 방법을 보여주는 다이어그램입니다. store[(저장소)] -.->|작업 복원|manager((러너 관리자)) manager -.->|재개| pod[[Kubernetes 작업 포드]] manager ===> |작업 로그/상태| gitlab[(GitLab)] pod ====>|작업 로그/상태| manager