OpenShift에서 GitLab 러너 구성하기

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

이 문서에서는 OpenShift에서 GitLab 러너를 구성하는 방법에 대해 설명합니다.

GitLab 러너 오퍼레이터에 속성 전달

Runner를 생성할 때, 해당 spec에 속성을 설정하여 구성할 수 있습니다. 예를 들어, 등록될 GitLab URL을 지정하거나, 등록 토큰이 포함된 시크릿의 이름을 지정할 수 있습니다.

apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
  name: dev
spec:
  gitlabUrl: https://gitlab.example.com
  token: gitlab-runner-secret # Runner 토큰이 포함된 시크릿의 이름

오퍼레이터 속성에서 모든 사용 가능한 속성에 대해 자세히 알아보세요.

오퍼레이터 속성

오퍼레이터에 전달할 수 있는 지원되는 속성 목록입니다.

일부 속성은 더 최근 버전의 오퍼레이터에서만 사용할 수 있습니다.

설정 오퍼레이터 설명
gitlabUrl all GitLab 인스턴스의 완전히 정규화된 도메인 이름입니다. 예: https://gitlab.example.com.
token all 등록된 러너를 등록하는 데 사용되는 runner-registration-token 키가 포함된 Secret의 이름입니다.
tags all 러너에 적용할 쉼표로 구분된 태그 목록입니다.
concurrent all 동시에 실행될 수 있는 작업 수를 제한합니다. 최대 수는 정의된 러너입니다. 0은 무제한을 의미하지 않습니다. 기본값은 10입니다.
interval all 새로운 작업을 확인하는 간격(초)을 정의합니다. 기본값은 30입니다.
locked 1.8 러너가 프로젝트에 잠길지 여부를 정의합니다. 기본값은 false입니다.
runUntagged 1.8 태그가 지정되지 않은 작업을 실행해야 하는지를 정의합니다. 태그가 지정되지 않았다면 기본값은 true입니다. 그렇지 않으면 false입니다.
protected 1.8 러너가 보호된 브랜치에서만 작업을 실행해야 하는지를 정의합니다. 기본값은 false입니다.
cloneURL all GitLab 인스턴스의 URL을 덮어씁니다. 러너가 GitLab URL에 연결할 수 없는 경우에만 사용됩니다.
env all 러너 파드에 주입될 환경 변수로 구성된 ConfigMap의 이름입니다.
runnerImage 1.7 기본 GitLab 러너 이미지를 덮어씁니다. 기본값은 오퍼레이터와 번들링된 러너 이미지입니다.
helperImage all 기본 GitLab 러너 보조 이미지를 덮어씁니다.
buildImage all 지정된 경우 빌드에 사용할 기본 Docker 이미지입니다.
cacheType all 러너 아티팩트에 사용되는 캐시 유형입니다. gcs, s3, azure 중 하나입니다.
cachePath all 파일 시스템의 캐시 경로를 정의합니다.
cacheShared all 러너 간 캐시 공유를 가능하게 합니다.
s3 all S3 캐시를 설정하는 데 사용되는 옵션입니다. 캐시 속성을 참조하세요.
gcs all GCS 캐시를 설정하는 데 사용되는 옵션입니다. 캐시 속성을 참조하세요.
azure all Azure 캐시를 설정하는 데 사용되는 옵션입니다. 캐시 속성을 참조하세요.
ca all 사용자 정의 CA(인증 기관) 인증서를 포함하는 TLS 시크릿의 이름입니다.
serviceaccount all 러너 파드 실행에 사용되는 서비스 계정을 덮어씁니다.
config all 구성 템플릿과 함께 사용할 사용자 정의 구성 맵의 이름입니다.

캐시 속성

S3 캐시

설정 오퍼레이터 설명
server all S3 서버 주소입니다.
credentials all 객체 저장소에 액세스하는 데 사용되는 accesskeysecretkey 속성이 포함된 Secret의 이름입니다.
bucket all 캐시가 저장되는 버킷의 이름입니다.
location all 캐시가 저장되는 S3 지역의 이름입니다.
insecure all 보안하지 않은 연결 또는 HTTP를 사용합니다.

GCS 캐시

설정 오퍼레이터 설명
credentials all 객체 저장소에 액세스하는 데 사용되는 access-idprivate-key 속성이 포함된 Secret의 이름입니다.
bucket all 캐시가 저장되는 버킷의 이름입니다.
credentialsFile all GCS 자격 증명 파일, keys.json을 사용합니다.

Azure 캐시

설정 Operator 설명
credentials all accountNameprivateKey 속성을 포함하는 Secret의 이름으로 객체 저장소에 액세스하는 데 사용됩니다.
container all 캐시가 저장될 Azure 컨테이너의 이름입니다.
storageDomain all Azure 블롭 저장소의 도메인 이름입니다.

프록시 환경 구성

프록시 환경을 생성하려면 다음을 수행하세요:

  1. custom-env.yaml 파일을 편집합니다. 예:

    apiVersion: v1
    data:
      HTTP_PROXY: example.com
    kind: ConfigMap
    metadata:
      name: custom-env
    
  2. 변경 사항을 적용하도록 OpenShift를 업데이트합니다.

    oc apply -f custom-env.yaml
    
  3. gitlab-runner.yml 파일을 업데이트합니다.

    apiVersion: apps.gitlab.com/v1beta2
    kind: Runner
    metadata:
      name: dev
    spec:
      gitlabUrl: https://gitlab.example.com
      token: gitlab-runner-secret # Runner 토큰을 포함하는 Secret의 이름
      env: custom-env
    

프록시가 Kubernetes API에 연결할 수 없는 경우 CI/CD 작업에서 오류가 발생할 수 있습니다:

ERROR: Job failed (system failure): prepare environment: setting up credentials: Post https://172.21.0.1:443/api/v1/namespaces/<KUBERNETES_NAMESPACE>/secrets: net/http: TLS handshake timeout. 자세한 내용은 https://docs.gitlab.com/runner/shells/index.html#shell-profile-loading을 확인하세요.

이 오류를 해결하려면 custom-env.yaml 파일의 NO_PROXY 구성에 Kubernetes API의 IP 주소를 추가합니다:

   apiVersion: v1
   data:
     NO_PROXY: 172.21.0.1
     HTTP_PROXY: example.com
   kind: ConfigMap
   metadata:
     name: custom-env

Kubernetes API의 IP 주소를 확인하려면 다음을 실행하여 확인할 수 있습니다:

oc get services --namespace default --field-selector='metadata.name=kubernetes' | grep -v NAME | awk '{print $3}'

구성 템플릿을 사용하여 config.toml을 사용자 지정합니다.

참고: config.toml을 사용자 지정하기 위한 구성 템플릿 사용은 현재 [runners.kubernetes.volumes] 설정을 지정하는 데로 제한되어 있습니다. 이를 다른 설정으로 확장하는 지원은 issue 49에 제안되었습니다.

구성 템플릿을 사용하여 runner의 config.toml 파일을 사용자 지정할 수 있습니다(configuration template을 사용).

  1. 사용자 정의 구성 템플릿 파일을 생성합니다. 예를 들어, runner에 EmptyDir 볼륨을 마운트하도록 지시하는 custom-config.toml 파일을 생성합니다:

    [[runners]]
      [runners.kubernetes]
        [runners.kubernetes.volumes]
          [[runners.kubernetes.volumes.empty_dir]]
            name = "empty-dir"
            mount_path = "/path/to/empty_dir"
            medium = "Memory"
    
  2. custom-config.toml 파일에서 ConfigMapcustom-config-toml을 생성합니다:

     oc create configmap custom-config-toml --from-file config.toml=custom-config.toml
    
  3. Runnerconfig 속성을 설정합니다:

     apiVersion: apps.gitlab.com/v1beta2
     kind: Runner
     metadata:
       name: dev
     spec:
       gitlabUrl: https://gitlab.example.com
       token: gitlab-runner-secret
       config: custom-config-toml
    

사용자 정의 TLS 인증서 구성

  1. 사용자 정의 TLS 인증서를 설정하려면 tls.crt 키로 시크릿을 생성합니다. 이 예제에서 파일 이름은 custom-tls-ca-secret.yaml입니다:

     apiVersion: v1
     kind: Secret
     metadata:
         name: custom-tls-ca
     type: Opaque
     stringData:
         tls.crt: |
             -----BEGIN CERTIFICATE-----
             MIIEczCCA1ugAwIBAgIBADANBgkqhkiG9w0BAQQFAD..AkGA1UEBhMCR0Ix
             .....
             7vQMfXdGsRrXNGRGnX+vWDZ3/zWI0joDtCkNnqEpVn..HoX
             -----END CERTIFICATE-----
    
  2. 시크릿을 생성합니다:

    oc apply -f custom-tls-ca-secret.yaml
    
  3. runner.yamlca 키를 시크릿의 이름과 동일하게 설정합니다:

     apiVersion: apps.gitlab.com/v1beta2
     kind: Runner
     metadata:
       name: dev
     spec:
       gitlabUrl: https://gitlab.example.com
       token: gitlab-runner-secret
       ca: custom-tls-ca
    

실행자 파드의 CPU 및 메모리 크기 구성

사용자 지정 config.toml 파일에서 CPU 한도메모리 한도를 설정하려면 이 항목의 지침에 따르세요.

클러스터 리소스에 기반한 실행자당 작업 병렬성 구성

Runner 리소스의 concurrent 속성을 설정하세요:

   apiVersion: apps.gitlab.com/v1beta2
   kind: Runner
   metadata:
     name: dev
   spec:
     gitlabUrl: https://gitlab.example.com
     token: gitlab-runner-secret
     concurrent: 2

작업 병렬성은 프로젝트의 요구 사항에 따릅니다.

  1. 우선 CI 작업을 실행하는 데 필요한 컴퓨팅 및 메모리 리소스를 결정하려고 시도하세요.
  2. 클러스터의 리소스를 고려해 해당 작업이 몇 번 실행될 수 있는지 계산하세요.

병렬성 값을 지나치게 크게 설정하면 쿠버네티스 실행자는 가능한 한 빨리 작업을 처리합니다. 그러나 쿠버네티스 클러스터의 스케줄러 용량이 작업을 스케줄링하는 시점을 결정합니다.

문제 해결

Root vs 비-Root

GitLab Runner Operator 및 GitLab Runner 파드는 비-루트 사용자로 실행됩니다. 따라서 작업에서 사용되는 빌드 이미지는 성공적으로 완료하려면 비-루트 사용자로 실행되어야 합니다. 이는 최소한의 권한으로 작업을 성공적으로 실행할 수 있도록 하는 것입니다. 그러나 이를 위해 CI 작업에 사용되는 빌드 이미지도 비-루트로 실행되도록 구축되어야 하며 제한된 파일 시스템에 쓰지 않아야 합니다. OpenShift 클러스터의 대부분의 컨테이너 파일 시스템은 읽기 전용일 수 있지만, 마운트된 볼륨, /var/tmp, /tmptmpfs로 마운트된 기타 볼륨을 제외하고 읽기 전용일 수 있습니다.

HOME 환경 변수 재정의

사용자 정의 빌드 이미지를 생성하거나 환경 변수를 재정의할 경우, HOME 환경 변수가 읽기 전용인 /로 설정되지 않도록 확인하세요. 특히 작업에서 홈 디렉토리에 파일을 쓰어야 하는 경우입니다. 예를 들어 /home 아래의 디렉토리(예: /home/ci)를 생성하고 Dockerfile에서 ENV HOME=/home/ci를 설정할 수 있습니다.

최종 사용자 파드에서는 HOME/home/gitlab-runner로 설정되어 있어야 합니다. 이 변수가 변경된 경우, 새로운 위치에는 적절한 권한이 있어야 합니다. 이러한 지침은 또한 Red Hat Container Platform Docs > 이미지 생성 > 임의의 사용자 ID 지원에서 문서화되어 있습니다.

SCC 주의사항

새로운 OpenShift 프로젝트에 설치될 때 기본적으로 GitLab Runner Operator는 비-루트로 실행됩니다. 그러나 default 프로젝트와 같이 프로젝트의 모든 서비스 계정이 anyuid 액세스를 허용받는 경우와 같은 예외가 있습니다. 이 경우 이미지 사용자는 root가 됩니다. 이는 간단히 컨테이너 셸(예: 작업)에서 whoami를 실행하여 확인할 수 있습니다. Red Hat Container Platform Docs > 보안 컨텍스트 제약 조건 관리에서 SCC에 대해 더 읽어볼 수 있습니다.

anyuid SCC로 실행

쌓이지는 않지만, CI 작업이 루트 사용자로 실행되거나 루트 파일 시스템에 쓰는 것이 절대적으로 필요한 경우, GitLab Runner 컨테이너에서 사용되는 gitlab-runner-sa 서비스 계정에 anyuid SCC를 설정해야 합니다.

OpenShift 4.3.8 및 이전:

oc adm policy add-scc-to-user anyuid -z gitlab-runner-sa -n <runner_namespace>

# anyuid SCC가 설정되었는지 확인하세요:
oc get scc anyuid -o yaml

OpenShift 4.3.8 및 이후:

oc create -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: scc-anyuid
  namespace: <runner_namespace>
rules:
- apiGroups:
  - security.openshift.io
  resourceNames:
  - anyuid
  resources:
  - securitycontextconstraints
  verbs:
  - use
EOF

oc create -f - <<EOF
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: sa-to-scc-anyuid
  namespace: <runner_namespace>
subjects:
  - kind: ServiceAccount
    name: gitlab-runner-sa
roleRef:
  kind: Role
  name: scc-anyuid
  apiGroup: rbac.authorization.k8s.io
EOF

SETFCAP 구성

Red Hat OpenShift Container Platform (RHOCP) 4.11 이상을 사용하는 경우, 다음 오류 메시지를 받을 수 있습니다.

error reading allowed ID mappings:error reading subuid mappings for user

일부 작업(buildah 등)은 올바르게 실행되기 위해 SETFCAP 기능이 필요합니다. 이 문제를 해결하려면 다음을 수행하세요:

  1. GitLab Runner가 사용하는 SCC에 SETFCAP 기능을 추가합니다 (gitlab-scc를 GitLab Runner pod에 할당된 SCC로 교체):

     oc patch scc gitlab-scc --type merge -p '{"allowedCapabilities":["SETFCAP"]}'
    
  2. config.toml을 업데이트하고 kubernetes 섹션에 SETFCAP 기능을 추가합니다:

     [[runners]]
       [runners.kubernetes]
       [runners.kubernetes.pod_security_context]
         [runners.kubernetes.build_container_security_context]
         [runners.kubernetes.build_container_security_context.capabilities]
           add = ["SETFCAP"]
    
  3. GitLab Runner가 배포된 네임스페이스에 이 config.toml을 사용하여 configmap을 생성합니다:

     oc create configmap custom-config-toml --from-file config.toml=config.toml
    
  4. 수정하려는 runner에 새로 생성된 configmap을 가리키는 config: 매개변수를 추가합니다 (올바른 runner pod 이름으로 my-runner를 교체):

     oc patch runner my-runner --type merge -p '{"spec": {"config": "custom-config-toml"}}'
    

더 많은 정보는 Red Hat documentation를 참조하세요.

FIPS 호환 GitLab Runner 사용

참고: 현재 Operator의 경우 도우미 이미지만 변경할 수 있습니다. 이슈로 GitLab Runner 이미지도 변경하도록 변경할 수 있습니다.

FIPS 호환 GitLab Runner 도우미를 사용하려면 도우미 이미지를 다음과 같이 변경하세요:

apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
 name: dev
spec:
 gitlabUrl: https://gitlab.example.com
 token: gitlab-runner-secret
 helperImage: gitlab/gitlab-runner-helper:ubi-fips
 concurrent: 2

자체 서명된 인증서를 사용하여 GitLab Runner 등록

GitLab 자체 관리 설치에서 자체 서명된 인증서를 사용하는 경우, 개인 인증서를 서명하는 데 사용된 CA 인증서를 포함하는 시크릿을 생성해야 합니다.

이후 해당 시크릿 이름을 Runner 사양 섹션에서 CA로 제공합니다:

KIND:     Runner
VERSION:  apps.gitlab.com/v1beta2

FIELD:    ca <string>

DESCRIPTION:
     사용자 지정 인증 기관(CA) 인증서를 포함하는 tls 시크릿의 이름

다음 명령을 사용하여 이 시크릿을 생성할 수 있습니다:

oc create secret generic mySecret --from-file=tls.crt=myCert.pem -o yaml

IP 주소를 가리키는 외부 URL을 사용하여 GitLab Runner 등록

Runner가 호스트 이름과 자체 서명된 인증서를 매칭할 수 없는 경우 오류 메시지를 받을 수 있습니다. 이는 GitLab 자체 관리 인스턴스가 호스트 이름이 아닌 IP 주소로부터 액세스되도록 구성된 경우 발생할 수 있습니다 (###.##.##.##는 GitLab 서버 IP입니다):

[31;1mERROR: Registering runner... failed               [0;m  [31;1mrunner[0;m=A5abcdEF [31;1mstatus[0;m=couldn't execute POST against https://###.##.##.##/api/v4/runners:
Post https://###.##.##.##/api/v4/runners: x509: cannot validate certificate for ###.##.##.## because it doesn't contain any IP SANs
[31;1mPANIC: Failed to register the runner. You may be having network problems.[0;m

이 문제를 해결하려면 다음을 수행하세요:

  1. GitLab 자체 관리 서버에서 openssl을 수정하여 IP 주소를 subjectAltName 매개변수에 추가합니다:

    # vim /etc/pki/tls/openssl.cnf
    
    [ v3_ca ]
    subjectAltName=IP:169.57.64.36 <---- 해당 줄을 추가합니다. 169.57.64.36은 GitLab 서버 IP입니다.
    
  2. 그런 다음 아래 명령으로 새로운 CA를 다시 생성합니다:

    # cd /etc/gitlab/ssl
    # openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -keyout /etc/gitlab/ssl/169.57.64.36.key -out /etc/gitlab/ssl/169.57.64.36.crt
    # openssl dhparam -out /etc/gitlab/ssl/dhparam.pem 4096
    # gitlab-ctl restart
    
  3. 이 새로운 인증서를 사용하여 새로운 시크릿을 생성합니다.