InfoGrab DocsInfoGrab Docs

OpenShift에서 GitLab Runner 구성

요약

| --- | --- | | gitlabUrl | all | GitLab 인스턴스의 완전한 도메인 이름. 프록시 환경을 생성하려면 다음 단계를 따르세요: custom-env.yaml 파일을 편집합니다. 변경 사항을 적용하기 위해 OpenShift를 업데이트합니다.

| --- | --- | | gitlabUrl | all | GitLab 인스턴스의 완전한 도메인 이름. 예: https://gitlab.example.com | | token | all | 러너 등록에 사용하는 runner-registration-token 키가 담긴 Secret의 이름. | | tags | all | 러너에 적용할 쉼표로 구분된 태그 목록. | | concurrent | all | 동시에 실행할 수 있는 job의 최대 수. 최대값은 정의된 모든 러너 수입니다. 0은 무제한을 의미하지 않습니다. 기본값은 10입니다. | | interval | all | 새 job 확인 간격(초). 기본값은 30입니다. | | locked | 1.8 | 러너를 특정 프로젝트에 잠글지 여부. 기본값은 false입니다. | | runUntagged | 1.8 | 태그가 없는 job을 실행할지 여부. 태그가 지정되지 않은 경우 기본값은 true이고, 그렇지 않으면 false입니다. | | protected | 1.8 | 러너가 보호된 브랜치에서만 job을 실행할지 여부. 기본값은 false입니다. | | cloneURL | all | GitLab 인스턴스 URL을 덮어씁니다. 러너가 GitLab URL에 접속할 수 없을 때만 사용합니다. | | env | all | Runner Pod에 환경 변수로 주입할 키-값 쌍이 담긴 ConfigMap의 이름. | | runnerImage | 1.7 | 기본 GitLab Runner 이미지를 덮어씁니다. 기본값은 Operator에 번들된 Runner 이미지입니다. | | helperImage | all | 기본 GitLab Runner 헬퍼 이미지를 덮어씁니다. | | buildImage | all | 빌드 시 이미지가 지정되지 않을 경우 사용할 기본 Docker 이미지. | | cacheType | all | Runner 아티팩트에 사용할 캐시 유형. gcs, s3, azure 중 하나. | | cachePath | all | 파일 시스템에서 캐시 경로를 정의합니다. | | cacheShared | all | 러너 간 캐시 공유를 활성화합니다. | | s3 | all | S3 캐시 설정 옵션. Cache 속성을 참조하세요. | | gcs | all | gcs 캐시 설정 옵션. Cache 속성을 참조하세요. | | azure | all | Azure 캐시 설정 옵션. Cache 속성을 참조하세요. | | ca | all | 사용자 정의 인증 기관(CA) 인증서가 담긴 TLS Secret의 이름. | | serviceaccount | all | Runner Pod 실행에 사용하는 서비스 어카운트를 재정의합니다. | | config | all | 구성 템플릿이 포함된 사용자 정의 ConfigMap을 제공할 때 사용합니다. | | shutdownTimeout | 1.34 | 강제 종료 작업이 타임아웃되어 프로세스를 종료하기까지의 시간(초). 기본값은 30입니다. 0 이하로 설정하면 기본값이 사용됩니다. | | logLevel | 1.34 | 로그 레벨을 정의합니다. debug, info, warn, error, fatal, panic 중 하나를 선택합니다. | | logFormat | 1.34 | 로그 형식을 지정합니다. runner, text, json 중 하나를 선택합니다. 기본값은 runner이며, 색상 표현을 위한 ANSI 이스케이프 코드가 포함됩니다. | | listenAddr | 1.34 | Prometheus 메트릭 HTTP 서버가 수신 대기할 주소(:)를 정의합니다. 구성에 대한 자세한 내용은 GitLab Runner Operator 모니터링을 참조하세요. | | sentryDsn | 1.34 | 모든 시스템 레벨 오류를 Sentry로 추적하도록 활성화합니다. | | connectionMaxAge | 1.34 | GitLab 서버와의 TLS 킵얼라이브 연결을 재연결하기 전까지 유지할 최대 시간. 기본값은 15분을 의미하는 15m입니다. 0 이하로 설정하면 연결이 가능한 한 오래 유지됩니다. | | podSpec | 1.23 | GitLab Runner Pod(템플릿)에 적용할 패치 목록. 자세한 내용은 러너 Pod 템플릿 패치 적용을 참조하세요. | | deploymentSpec | 1.40 | GitLab Runner 디플로이먼트에 적용할 패치 목록. 자세한 내용은 러너 디플로이먼트 템플릿 패치 적용을 참조하세요. |

Cache 속성#

S3 캐시#

설정 Operator 설명
server all S3 서버 주소.
credentials all 오브젝트 스토리지 접근에 사용하는 accesskey 및 secretkey 속성이 담긴 Secret의 이름.
bucket all 캐시가 저장되는 버킷의 이름.
location all 캐시가 저장되는 S3 리전의 이름.
insecure all 비보안 연결 또는 HTTP를 사용합니다.

gcs 캐시#

설정 Operator 설명
credentials all 오브젝트 스토리지 접근에 사용하는 access-id 및 private-key 속성이 담긴 Secret의 이름.
bucket all 캐시가 저장되는 버킷의 이름.
credentialsFile all gcs 자격 증명 파일인 keys.json을 사용합니다.

Azure 캐시#

설정 Operator 설명
credentials all 오브젝트 스토리지 접근에 사용하는 accountName 및 privateKey 속성이 담긴 Secret의 이름.
container all 캐시가 저장되는 Azure 컨테이너의 이름.
storageDomain all Azure Blob 스토리지의 도메인 이름.

프록시 환경 구성#

프록시 환경을 생성하려면 다음 단계를 따르세요:

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

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

변경 사항을 적용하기 위해 OpenShift를 업데이트합니다.

oc apply -f custom-env.yaml

gitlab-runner.yml 파일을 업데이트합니다.

apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
  name: dev
spec:
  gitlabUrl: https://gitlab.example.com
  token: gitlab-runner-secret # Name of the secret containing the Runner token
  env: custom-env

프록시가 쿠버네티스 API에 접근하지 못하는 경우, CI/CD job에서 다음과 같은 오류가 발생할 수 있습니다:

ERROR: Job failed (system failure): prepare environment: setting up credentials: Post https://172.21.0.1:443/api/v1/namespaces//secrets: net/http: TLS handshake timeout. Check https://docs.gitlab.com/runner/shells/#shell-profile-loading for more information

이 오류를 해결하려면 custom-env.yaml 파일의 NO_PROXY 구성에 쿠버네티스 API의 IP 주소를 추가하세요:

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

다음 명령을 실행하여 쿠버네티스 API의 IP 주소를 확인할 수 있습니다:

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

구성 템플릿으로 config.toml 사용자 정의#

구성 템플릿을 사용하여 러너의 config.toml 파일을 사용자 정의할 수 있습니다.

사용자 정의 구성 템플릿 파일을 생성합니다. 예를 들어, 러너가 EmptyDir 볼륨을 마운트하고 cpu_limit을 설정하도록 지시하겠습니다. custom-config.toml 파일을 생성합니다:

[[runners]]
  [runners.kubernetes]
    cpu_limit = "500m"
    [runners.kubernetes.volumes]
      [[runners.kubernetes.volumes.empty_dir]]
        name = "empty-dir"
        mount_path = "/path/to/empty_dir"
        medium = "Memory"

custom-config.toml 파일에서 custom-config-toml이라는 이름의 ConfigMap을 생성합니다:

 oc create configmap custom-config-toml --from-file config.toml=custom-config.toml

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

알려진 이슈로 인해, 다음 설정을 수정할 때는 구성 템플릿 대신 환경 변수를 사용해야 합니다:

설정 환경 변수 기본값
runners.request_concurrency RUNNER_REQUEST_CONCURRENCY 1
runners.output_limit RUNNER_OUTPUT_LIMIT 4096
kubernetes.runner.poll_timeout KUBERNETES_POLL_TIMEOUT 180

사용자 정의 TLS 인증서 구성#

사용자 정의 TLS 인증서를 설정하려면 tls.crt 키로 Secret을 생성합니다. 이 예에서 파일 이름은 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-----

Secret을 생성합니다:

oc apply -f custom-tls-ca-secret.yaml

runner.yamlca 키를 Secret 이름과 동일하게 설정합니다:

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

러너 Pod의 CPU 및 메모리 크기 구성#

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

클러스터 리소스 기반 러너별 job 동시성 구성#

Runner 리소스의 concurrent 속성을 설정합니다:

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

job 동시성은 프로젝트의 요구 사항에 따라 결정됩니다.

  • 먼저 CI job 실행에 필요한 컴퓨팅 및 메모리 리소스를 파악하세요.

  • 클러스터의 리소스를 기준으로 해당 job이 몇 번이나 실행될 수 있는지 계산하세요.

높은 동시성 값을 설정하면 쿠버네티스 executor는 가능한 한 빨리 job을 처리합니다. 하지만 job 실제 스케줄링 시점은 쿠버네티스 클러스터의 스케줄러 용량에 따라 결정됩니다.

GitLab Runner 매니저의 서비스 어카운트#

신규 설치 시, 다음 RBAC 역할 바인딩 리소스가 존재하지 않으면 GitLab Runner는 러너 매니저 Pod를 위해 gitlab-runner-app-sa라는 쿠버네티스 ServiceAccount를 생성합니다:

  • gitlab-runner-app-rolebinding

  • gitlab-runner-rolebinding

역할 바인딩 중 하나가 존재하는 경우, GitLab은 해당 역할 바인딩의 subjectsroleRef에 정의된 역할과 서비스 어카운트를 확인합니다.

두 역할 바인딩이 모두 존재하는 경우, gitlab-runner-app-rolebindinggitlab-runner-rolebinding보다 우선합니다.

FIPS 준수 GitLab Runner 사용#

Operator의 경우 헬퍼 이미지만 변경할 수 있습니다. 아직 GitLab Runner 이미지는 변경할 수 없습니다.

이슈 28814에서 이 기능을 추적하고 있습니다.

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

문제 해결#

Root vs non-root#

GitLab Runner Operator와 GitLab Runner Pod는 non-root 사용자로 실행됩니다. 따라서 기본적으로 job에서 사용하는 빌드 이미지는 성공적으로 완료하려면 non-root 사용자로 실행되어야 합니다. 이를 통해 job이 최소한의 권한으로 성공적으로 실행될 수 있습니다.

이를 위해 CI/CD job에 사용하는 빌드 이미지가 다음 조건을 만족하는지 확인하세요:

  • non-root로 실행될 것

  • 제한된 파일 시스템에 쓰지 않을 것

OpenShift 클러스터의 대부분의 컨테이너 파일 시스템은 읽기 전용입니다. 예외는 다음과 같습니다:

  • 마운트된 볼륨

  • /var/tmp

  • /tmp

  • root 파일 시스템에 tmpfs로 마운트된 기타 볼륨

HOME 환경 변수 재정의#

사용자 정의 빌드 이미지를 생성하거나 환경 변수를 재정의할 때, HOME 환경 변수가 읽기 전용인 /로 설정되지 않도록 주의하세요. 특히 job이 홈 디렉터리에 파일을 써야 하는 경우에 중요합니다. 예를 들어 /home 아래에 /home/ci와 같은 디렉터리를 생성하고 DockerfileENV HOME=/home/ci를 설정하면 됩니다.

러너 Pod의 경우 HOME/home/gitlab-runner로 설정되어야 합니다. 이 변수를 변경하는 경우 새 위치에 적절한 권한이 부여되어야 합니다. 이러한 지침은 Red Hat Container Platform 문서에도 안내되어 있습니다.

잠긴 변수 재정의#

러너 토큰을 등록할 때 locked 변수를 true로 설정하면 다음 오류가 표시됩니다: Runner configuration other than name, description, and exector is reserved and cannot be specified

  locked: true # REQUIRED
  tags: ""
  runUntagged: false
  protected: false
  maximumTimeout: 0

자세한 내용은 이슈 472를 참조하세요.

보안 컨텍스트 제약 주의사항#

기본적으로 새 OpenShift 프로젝트에 설치 시 GitLab Runner Operator는 non-root로 실행됩니다. default 프로젝트와 같이 모든 서비스 어카운트가 anyuid 접근 권한을 갖는 일부 프로젝트는 예외입니다. 이 경우 이미지의 사용자는 root입니다. job 등 임의의 컨테이너 셸에서 whoami를 실행하여 확인할 수 있습니다. 보안 컨텍스트 제약에 대한 자세한 내용은 Red Hat Container Platform 문서를 참조하세요.

anyuid 보안 컨텍스트 제약으로 실행#

root 사용자로 job을 실행하거나 root 파일 시스템에 쓰는 것은 보안 위험을 초래할 수 있습니다.

CI/CD job을 root 사용자로 실행하거나 root 파일 시스템에 쓰려면, gitlab-runner-app-sa 서비스 어카운트에 anyuid 보안 컨텍스트 제약을 설정하세요. GitLab Runner 컨테이너는 이 서비스 어카운트를 사용합니다.

OpenShift 4.3.8 이전:

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

# Check that the anyiud SCC is set:
oc get scc anyuid -o yaml

OpenShift 4.3.8 이후:

oc create -f - <
rules:
- apiGroups:
  - security.openshift.io
  resourceNames:
  - anyuid
  resources:
  - securitycontextconstraints
  verbs:
  - use
EOF

oc create -f - <
subjects:
  - kind: ServiceAccount
    name: gitlab-runner-app-sa
roleRef:
  kind: Role
  name: scc-anyuid
  apiGroup: rbac.authorization.k8s.io
EOF

헬퍼 컨테이너와 빌드 컨테이너의 사용자 ID 및 그룹 ID 불일치#

GitLab Runner Operator 디플로이먼트는 기본 헬퍼 이미지로 registry.gitlab.com/gitlab-org/ci-cd/gitlab-runner-ubi-images/gitlab-runner-helper-ocp를 사용합니다. 이 이미지는 보안 컨텍스트로 명시적으로 수정하지 않는 한 사용자 ID 및 그룹 ID 1001:1001로 실행됩니다.

빌드 컨테이너의 사용자 ID가 헬퍼 이미지의 사용자 ID와 다를 경우, 헬퍼 컨테이너가 생성한 파일 (클론된 리포지터리와 복원된 캐시)의 소유자가 1001:1001이므로 빌드 중 권한 관련 오류가 발생할 수 있습니다. 이 불일치는 다음 두 가지 일반적인 문제를 일으킵니다:

헬퍼 컨테이너와 빌드 컨테이너의 사용자 ID 일치시키기#

두 문제 모두에 대한 해결 방법은 빌드 컨테이너의 보안 컨텍스트를 헬퍼 컨테이너의 사용자 ID 및 그룹 ID에 맞게 구성하는 것입니다:

[runners.kubernetes.build_container_security_context]
run_as_user = 1001
run_as_group = 1001

추가 참고 사항:

  • 이 설정은 리포지터리를 클론하는 컨테이너와 빌드하는 컨테이너 간에 일관된 파일 소유권을 보장합니다.

  • 헬퍼 이미지를 다른 사용자 ID 또는 그룹 ID로 사용자 정의한 경우 이 값을 그에 맞게 조정하세요.

  • OpenShift 디플로이먼트의 경우, 이러한 보안 컨텍스트 설정이 클러스터의 보안 컨텍스트 제약(SCC)을 준수하는지 확인하세요.

빌드 컨테이너의 사용자 ID를 변경할 수 없는 경우(예: 사용자 ID가 고정된 서드파티 이미지를 사용하거나, build_container_security_context를 수정할 수 없는 공유 러너를 사용하는 경우)에는 각 문제에 대해 설명된 우회 방법을 대신 사용하세요.

Git dubious ownership 오류#

빌드 컨테이너가 헬퍼 컨테이너가 클론한 리포지터리에 접근하면 Git은 다음과 같이 보고합니다:

fatal: detected dubious ownership in repository at '/builds/gitlab-org/gitlab-runner'

이 오류는 리포지터리가 사용자 ID 1001(헬퍼 컨테이너)에 의해 클론되었지만, 빌드 컨테이너의 다른 사용자 ID가 이에 접근하려 한다는 것을 나타냅니다.

이 오류를 해결하려면 다음 중 하나를 수행하세요:

헬퍼 컨테이너와 빌드 컨테이너의 사용자 ID를 일치시킵니다.

Git의 safe.directory 설정을 사용하여 소유권 불일치에도 불구하고 Git이 해당 리포지터리 디렉터리를 신뢰하도록 구성합니다. HOME 환경 변수는 쓰기 가능한 디렉터리를 가리켜야 하므로, before_script에서 설정할 수 있습니다:

my_job:
  before_script:
    - git config --global --add safe.directory $CI_PROJECT_DIR

safe.directory 설정은 dubious ownership 오류만 해결합니다. 리포지터리 파일의 소유자는 여전히 헬퍼 컨테이너의 사용자 ID이므로, 리포지터리 디렉터리에 쓰기를 수행하는 job은 여전히 권한 오류를 만날 수 있습니다.

캐시 권한 오류#

사용자 ID 불일치는 CI/CD 캐시에도 영향을 줍니다. 이 문제는 사용자 ID가 헬퍼 이미지의 사용자 ID와 일치하지 않는 non-root 빌드 컨테이너에 영향을 줍니다. root로 실행되는 빌드 컨테이너는 영향을 받지 않습니다.

OCP 헬퍼 이미지는 캐시 파일을 사용자 ID 1001로 아카이브하고 추출합니다. 빌드 컨테이너가 다른 사용자 ID로 실행되면, 파일의 소유자가 1001:1001이므로 복원된 캐시 디렉터리에 쓸 수 없습니다.

증상은 다음과 같습니다:

  • 캐시는 성공적으로 복원되지만, 애플리케이션이 새 캐시 항목을 쓸 수 없습니다.

  • 캐시 디렉터리에 쓸 때 Permission denied 오류가 발생합니다.

  • 빌드 컨테이너가 파일을 소유하고 있지 않으므로 before_scriptchown이 실패합니다.

이러한 오류를 해결하려면 다음 중 하나를 수행하세요:

헬퍼 컨테이너와 빌드 컨테이너의 사용자 ID를 일치시킵니다.

헬퍼가 캐시를 아카이브하기 전에 after_script에서 캐시 파일을 모든 사용자가 쓸 수 있도록 만듭니다. 이후 복원 시 777 권한이 tar 아카이브에 보존되므로, 어떤 사용자 ID든 읽고 쓸 수 있습니다:

my_job:
  after_script:
    - chmod -R 777 my-cache-dir/ 2>/dev/null || true
  cache:
    key: my-cache-key
    paths:
      - my-cache-dir/

이 우회 방법을 추가한 후에는 기존 캐시를 지우세요. 그래야 첫 실행에서 777 권한의 새 파일이 생성되어 이후의 아카이브 및 복원 주기에서도 유지됩니다.

SETFCAP 구성#

Red Hat OpenShift Container Platform(RHOCP) 4.11 이상을 사용하는 경우 다음 오류 메시지가 표시될 수 있습니다:

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

일부 job(예: buildah)은 올바르게 실행하기 위해 SETFCAP 기능이 부여되어야 합니다. 이 문제를 해결하려면:

GitLab Runner가 사용하는 보안 컨텍스트 제약에 SETFCAP 기능을 추가합니다(gitlab-scc를 GitLab Runner Pod에 할당된 보안 컨텍스트 제약으로 교체하세요):

oc patch scc gitlab-scc --type merge -p '{"allowedCapabilities":["SETFCAP"]}'

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"]

GitLab Runner가 배포된 네임스페이스에서 이 config.toml을 사용하여 ConfigMap을 생성합니다:

oc create configmap custom-config-toml --from-file config.toml=config.toml

수정할 러너에서 최근 생성한 ConfigMap을 가리키는 config: 파라미터를 추가합니다(my-runner를 올바른 러너 Pod 이름으로 교체하세요).

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

자세한 내용은 Red Hat 문서를 참조하세요.

자체 서명 인증서를 사용한 GitLab Runner 등록#

GitLab Self-Managed에서 자체 서명 인증서를 사용하려면, 개인 인증서 서명에 사용한 CA 인증서가 포함된 Secret을 생성하세요.

그런 다음 Runner spec 섹션에서 해당 Secret 이름을 CA로 제공합니다:

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

FIELD:    ca <string>

DESCRIPTION:
     Name of tls secret containing the custom certificate authority (CA)
     certificates

다음 명령을 사용하여 Secret을 생성할 수 있습니다:

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

IP 주소를 가리키는 외부 URL로 GitLab Runner 등록#

러너가 자체 서명 인증서와 호스트 이름을 일치시키지 못하면 오류 메시지가 표시될 수 있습니다. 이 문제는 GitLab Self-Managed를 호스트 이름 대신 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

이 문제를 해결하려면:

GitLab Self-Managed 서버에서 openssl을 수정하여 subjectAltName 파라미터에 IP 주소를 추가합니다:

# vim /etc/pki/tls/openssl.cnf

[ v3_ca ]
subjectAltName=IP:169.57.64.36 <---- Add this line. 169.57.64.36 is your GitLab server IP.

아래 명령으로 자체 서명 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

이 새 인증서를 사용하여 새 Secret을 생성합니다.

패칭#

podSpecdeploymentSpec Operator 속성을 통해 설정하는 스펙 패치를 사용하여 Operator가 생성하는 쿠버네티스 리소스를 사용자 정의할 수 있습니다.

패치 구조#

각 스펙 패치는 다음 속성으로 구성됩니다:

설정 설명
name 사용자 정의 스펙 패치의 이름.
patchFile 생성 전 최종 스펙에 적용할 변경 사항을 정의하는 파일 경로. 파일은 JSON 또는 YAML 형식이어야 합니다.
patch 생성 전 최종 스펙에 적용할 변경 사항을 기술하는 JSON 또는 YAML 형식 문자열.
patchType 스펙에 지정된 변경 사항을 적용하는 전략. 허용 값은 merge, json, strategic(기본값)입니다.

동일한 스펙 구성에서 patchFilepatch를 함께 설정할 수 없습니다.

러너 Pod 템플릿 패치 적용#

Pod 스펙 패치 적용을 통해 Operator가 생성한 쿠버네티스 디플로이먼트에 패치를 적용하여 GitLab Runner 배포 방식을 사용자 정의할 수 있습니다. 패치는 Pod 템플릿의 스펙(deployment.spec.template.spec)에 적용됩니다.

다음과 같은 Pod 레벨 설정을 제어할 수 있습니다:

  • 리소스 요청 및 제한

  • 보안 컨텍스트

  • 볼륨 마운트 및 볼륨

  • 환경 변수

  • 노드 셀렉터 및 어피니티 규칙

  • Toleration

  • 호스트 이름 및 DNS 구성

러너 디플로이먼트 템플릿 패치 적용#

디플로이먼트 스펙 패치 적용을 통해 Operator가 생성한 쿠버네티스 디플로이먼트에 패치를 적용하여 GitLab Runner 배포 방식을 사용자 정의할 수 있습니다. 패치는 디플로이먼트 스펙(deployment.spec)에 적용됩니다.

다음과 같은 디플로이먼트 레벨 설정을 제어할 수 있습니다:

  • 레플리카 수

  • 디플로이먼트 전략(RollingUpdate, Recreate)

  • 리비전 히스토리 제한

  • 진행 데드라인(초)

  • 라벨 및 어노테이션

패치 순서#

디플로이먼트 스펙 패치가 Pod 스펙 패치보다 먼저 적용됩니다. 따라서 디플로이먼트 스펙과 Pod 스펙이 동일한 필드를 수정하는 경우 Pod 스펙이 우선합니다.

예시#

Pod 스펙 패치 적용 예시#

apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
  name: dev
spec:
  gitlabUrl: https://gitlab.example.com
  token: gitlab-runner-secret
  podSpec:
    - name: "set-hostname"
      patch: |
        hostname: "custom-hostname"
      patchType: "merge"
    - name: "add-resource-requests"
      patch: |
        containers:
        - name: build
          resources:
            requests:
              cpu: "500m"
              memory: "256Mi"
      patchType: "strategic"

디플로이먼트 스펙 패치 적용 예시#

apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
  name: dev
spec:
  gitlabUrl: https://gitlab.example.com
  token: gitlab-runner-secret
  deploymentSpec:
    - name: "set-replicas"
      patch: |
        replicas: 3
      patchType: "strategic"
    - name: "configure-strategy"
      patch: |
        strategy:
          type: RollingUpdate
          rollingUpdate:
            maxUnavailable: 25%
            maxSurge: 50%
      patchType: "strategic"
    - name: "set-revision-history"
      patch: |
        [{"op": "add", "path": "/revisionHistoryLimit", "value": 10}]
      patchType: "json"

모범 사례#

  • 프로덕션 디플로이먼트에 적용하기 전에 비프로덕션 환경에서 패치를 테스트하세요.

  • 개별 Pod 설정이 아닌 디플로이먼트 동작에 영향을 미치는 설정에는 디플로이먼트 레벨 패치를 사용하세요.

  • 충돌하는 필드의 경우 Pod 스펙 패치가 디플로이먼트 스펙 패치를 재정의한다는 점을 기억하세요.

OpenShift에서 GitLab Runner 구성

GitLab v19.3
원문 보기

요약

| --- | --- | | gitlabUrl | all | GitLab 인스턴스의 완전한 도메인 이름. 프록시 환경을 생성하려면 다음 단계를 따르세요: custom-env.yaml 파일을 편집합니다. 변경 사항을 적용하기 위해 OpenShift를 업데이트합니다.

| --- | --- | | gitlabUrl | all | GitLab 인스턴스의 완전한 도메인 이름. 예: https://gitlab.example.com | | token | all | 러너 등록에 사용하는 runner-registration-token 키가 담긴 Secret의 이름. | | tags | all | 러너에 적용할 쉼표로 구분된 태그 목록. | | concurrent | all | 동시에 실행할 수 있는 job의 최대 수. 최대값은 정의된 모든 러너 수입니다. 0은 무제한을 의미하지 않습니다. 기본값은 10입니다. | | interval | all | 새 job 확인 간격(초). 기본값은 30입니다. | | locked | 1.8 | 러너를 특정 프로젝트에 잠글지 여부. 기본값은 false입니다. | | runUntagged | 1.8 | 태그가 없는 job을 실행할지 여부. 태그가 지정되지 않은 경우 기본값은 true이고, 그렇지 않으면 false입니다. | | protected | 1.8 | 러너가 보호된 브랜치에서만 job을 실행할지 여부. 기본값은 false입니다. | | cloneURL | all | GitLab 인스턴스 URL을 덮어씁니다. 러너가 GitLab URL에 접속할 수 없을 때만 사용합니다. | | env | all | Runner Pod에 환경 변수로 주입할 키-값 쌍이 담긴 ConfigMap의 이름. | | runnerImage | 1.7 | 기본 GitLab Runner 이미지를 덮어씁니다. 기본값은 Operator에 번들된 Runner 이미지입니다. | | helperImage | all | 기본 GitLab Runner 헬퍼 이미지를 덮어씁니다. | | buildImage | all | 빌드 시 이미지가 지정되지 않을 경우 사용할 기본 Docker 이미지. | | cacheType | all | Runner 아티팩트에 사용할 캐시 유형. gcs, s3, azure 중 하나. | | cachePath | all | 파일 시스템에서 캐시 경로를 정의합니다. | | cacheShared | all | 러너 간 캐시 공유를 활성화합니다. | | s3 | all | S3 캐시 설정 옵션. Cache 속성을 참조하세요. | | gcs | all | gcs 캐시 설정 옵션. Cache 속성을 참조하세요. | | azure | all | Azure 캐시 설정 옵션. Cache 속성을 참조하세요. | | ca | all | 사용자 정의 인증 기관(CA) 인증서가 담긴 TLS Secret의 이름. | | serviceaccount | all | Runner Pod 실행에 사용하는 서비스 어카운트를 재정의합니다. | | config | all | 구성 템플릿이 포함된 사용자 정의 ConfigMap을 제공할 때 사용합니다. | | shutdownTimeout | 1.34 | 강제 종료 작업이 타임아웃되어 프로세스를 종료하기까지의 시간(초). 기본값은 30입니다. 0 이하로 설정하면 기본값이 사용됩니다. | | logLevel | 1.34 | 로그 레벨을 정의합니다. debug, info, warn, error, fatal, panic 중 하나를 선택합니다. | | logFormat | 1.34 | 로그 형식을 지정합니다. runner, text, json 중 하나를 선택합니다. 기본값은 runner이며, 색상 표현을 위한 ANSI 이스케이프 코드가 포함됩니다. | | listenAddr | 1.34 | Prometheus 메트릭 HTTP 서버가 수신 대기할 주소(:)를 정의합니다. 구성에 대한 자세한 내용은 GitLab Runner Operator 모니터링을 참조하세요. | | sentryDsn | 1.34 | 모든 시스템 레벨 오류를 Sentry로 추적하도록 활성화합니다. | | connectionMaxAge | 1.34 | GitLab 서버와의 TLS 킵얼라이브 연결을 재연결하기 전까지 유지할 최대 시간. 기본값은 15분을 의미하는 15m입니다. 0 이하로 설정하면 연결이 가능한 한 오래 유지됩니다. | | podSpec | 1.23 | GitLab Runner Pod(템플릿)에 적용할 패치 목록. 자세한 내용은 러너 Pod 템플릿 패치 적용을 참조하세요. | | deploymentSpec | 1.40 | GitLab Runner 디플로이먼트에 적용할 패치 목록. 자세한 내용은 러너 디플로이먼트 템플릿 패치 적용을 참조하세요. |

Cache 속성#

S3 캐시#

설정 Operator 설명
server all S3 서버 주소.
credentials all 오브젝트 스토리지 접근에 사용하는 accesskey 및 secretkey 속성이 담긴 Secret의 이름.
bucket all 캐시가 저장되는 버킷의 이름.
location all 캐시가 저장되는 S3 리전의 이름.
insecure all 비보안 연결 또는 HTTP를 사용합니다.

gcs 캐시#

설정 Operator 설명
credentials all 오브젝트 스토리지 접근에 사용하는 access-id 및 private-key 속성이 담긴 Secret의 이름.
bucket all 캐시가 저장되는 버킷의 이름.
credentialsFile all gcs 자격 증명 파일인 keys.json을 사용합니다.

Azure 캐시#

설정 Operator 설명
credentials all 오브젝트 스토리지 접근에 사용하는 accountName 및 privateKey 속성이 담긴 Secret의 이름.
container all 캐시가 저장되는 Azure 컨테이너의 이름.
storageDomain all Azure Blob 스토리지의 도메인 이름.

프록시 환경 구성#

프록시 환경을 생성하려면 다음 단계를 따르세요:

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

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

변경 사항을 적용하기 위해 OpenShift를 업데이트합니다.

oc apply -f custom-env.yaml

gitlab-runner.yml 파일을 업데이트합니다.

apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
  name: dev
spec:
  gitlabUrl: https://gitlab.example.com
  token: gitlab-runner-secret # Name of the secret containing the Runner token
  env: custom-env

프록시가 쿠버네티스 API에 접근하지 못하는 경우, CI/CD job에서 다음과 같은 오류가 발생할 수 있습니다:

ERROR: Job failed (system failure): prepare environment: setting up credentials: Post https://172.21.0.1:443/api/v1/namespaces//secrets: net/http: TLS handshake timeout. Check https://docs.gitlab.com/runner/shells/#shell-profile-loading for more information

이 오류를 해결하려면 custom-env.yaml 파일의 NO_PROXY 구성에 쿠버네티스 API의 IP 주소를 추가하세요:

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

다음 명령을 실행하여 쿠버네티스 API의 IP 주소를 확인할 수 있습니다:

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

구성 템플릿으로 config.toml 사용자 정의#

구성 템플릿을 사용하여 러너의 config.toml 파일을 사용자 정의할 수 있습니다.

사용자 정의 구성 템플릿 파일을 생성합니다. 예를 들어, 러너가 EmptyDir 볼륨을 마운트하고 cpu_limit을 설정하도록 지시하겠습니다. custom-config.toml 파일을 생성합니다:

[[runners]]
  [runners.kubernetes]
    cpu_limit = "500m"
    [runners.kubernetes.volumes]
      [[runners.kubernetes.volumes.empty_dir]]
        name = "empty-dir"
        mount_path = "/path/to/empty_dir"
        medium = "Memory"

custom-config.toml 파일에서 custom-config-toml이라는 이름의 ConfigMap을 생성합니다:

 oc create configmap custom-config-toml --from-file config.toml=custom-config.toml

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

알려진 이슈로 인해, 다음 설정을 수정할 때는 구성 템플릿 대신 환경 변수를 사용해야 합니다:

설정 환경 변수 기본값
runners.request_concurrency RUNNER_REQUEST_CONCURRENCY 1
runners.output_limit RUNNER_OUTPUT_LIMIT 4096
kubernetes.runner.poll_timeout KUBERNETES_POLL_TIMEOUT 180

사용자 정의 TLS 인증서 구성#

사용자 정의 TLS 인증서를 설정하려면 tls.crt 키로 Secret을 생성합니다. 이 예에서 파일 이름은 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-----

Secret을 생성합니다:

oc apply -f custom-tls-ca-secret.yaml

runner.yamlca 키를 Secret 이름과 동일하게 설정합니다:

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

러너 Pod의 CPU 및 메모리 크기 구성#

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

클러스터 리소스 기반 러너별 job 동시성 구성#

Runner 리소스의 concurrent 속성을 설정합니다:

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

job 동시성은 프로젝트의 요구 사항에 따라 결정됩니다.

  • 먼저 CI job 실행에 필요한 컴퓨팅 및 메모리 리소스를 파악하세요.

  • 클러스터의 리소스를 기준으로 해당 job이 몇 번이나 실행될 수 있는지 계산하세요.

높은 동시성 값을 설정하면 쿠버네티스 executor는 가능한 한 빨리 job을 처리합니다. 하지만 job 실제 스케줄링 시점은 쿠버네티스 클러스터의 스케줄러 용량에 따라 결정됩니다.

GitLab Runner 매니저의 서비스 어카운트#

신규 설치 시, 다음 RBAC 역할 바인딩 리소스가 존재하지 않으면 GitLab Runner는 러너 매니저 Pod를 위해 gitlab-runner-app-sa라는 쿠버네티스 ServiceAccount를 생성합니다:

  • gitlab-runner-app-rolebinding

  • gitlab-runner-rolebinding

역할 바인딩 중 하나가 존재하는 경우, GitLab은 해당 역할 바인딩의 subjectsroleRef에 정의된 역할과 서비스 어카운트를 확인합니다.

두 역할 바인딩이 모두 존재하는 경우, gitlab-runner-app-rolebindinggitlab-runner-rolebinding보다 우선합니다.

FIPS 준수 GitLab Runner 사용#

Operator의 경우 헬퍼 이미지만 변경할 수 있습니다. 아직 GitLab Runner 이미지는 변경할 수 없습니다.

이슈 28814에서 이 기능을 추적하고 있습니다.

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

문제 해결#

Root vs non-root#

GitLab Runner Operator와 GitLab Runner Pod는 non-root 사용자로 실행됩니다. 따라서 기본적으로 job에서 사용하는 빌드 이미지는 성공적으로 완료하려면 non-root 사용자로 실행되어야 합니다. 이를 통해 job이 최소한의 권한으로 성공적으로 실행될 수 있습니다.

이를 위해 CI/CD job에 사용하는 빌드 이미지가 다음 조건을 만족하는지 확인하세요:

  • non-root로 실행될 것

  • 제한된 파일 시스템에 쓰지 않을 것

OpenShift 클러스터의 대부분의 컨테이너 파일 시스템은 읽기 전용입니다. 예외는 다음과 같습니다:

  • 마운트된 볼륨

  • /var/tmp

  • /tmp

  • root 파일 시스템에 tmpfs로 마운트된 기타 볼륨

HOME 환경 변수 재정의#

사용자 정의 빌드 이미지를 생성하거나 환경 변수를 재정의할 때, HOME 환경 변수가 읽기 전용인 /로 설정되지 않도록 주의하세요. 특히 job이 홈 디렉터리에 파일을 써야 하는 경우에 중요합니다. 예를 들어 /home 아래에 /home/ci와 같은 디렉터리를 생성하고 DockerfileENV HOME=/home/ci를 설정하면 됩니다.

러너 Pod의 경우 HOME/home/gitlab-runner로 설정되어야 합니다. 이 변수를 변경하는 경우 새 위치에 적절한 권한이 부여되어야 합니다. 이러한 지침은 Red Hat Container Platform 문서에도 안내되어 있습니다.

잠긴 변수 재정의#

러너 토큰을 등록할 때 locked 변수를 true로 설정하면 다음 오류가 표시됩니다: Runner configuration other than name, description, and exector is reserved and cannot be specified

  locked: true # REQUIRED
  tags: ""
  runUntagged: false
  protected: false
  maximumTimeout: 0

자세한 내용은 이슈 472를 참조하세요.

보안 컨텍스트 제약 주의사항#

기본적으로 새 OpenShift 프로젝트에 설치 시 GitLab Runner Operator는 non-root로 실행됩니다. default 프로젝트와 같이 모든 서비스 어카운트가 anyuid 접근 권한을 갖는 일부 프로젝트는 예외입니다. 이 경우 이미지의 사용자는 root입니다. job 등 임의의 컨테이너 셸에서 whoami를 실행하여 확인할 수 있습니다. 보안 컨텍스트 제약에 대한 자세한 내용은 Red Hat Container Platform 문서를 참조하세요.

anyuid 보안 컨텍스트 제약으로 실행#

root 사용자로 job을 실행하거나 root 파일 시스템에 쓰는 것은 보안 위험을 초래할 수 있습니다.

CI/CD job을 root 사용자로 실행하거나 root 파일 시스템에 쓰려면, gitlab-runner-app-sa 서비스 어카운트에 anyuid 보안 컨텍스트 제약을 설정하세요. GitLab Runner 컨테이너는 이 서비스 어카운트를 사용합니다.

OpenShift 4.3.8 이전:

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

# Check that the anyiud SCC is set:
oc get scc anyuid -o yaml

OpenShift 4.3.8 이후:

oc create -f - <
rules:
- apiGroups:
  - security.openshift.io
  resourceNames:
  - anyuid
  resources:
  - securitycontextconstraints
  verbs:
  - use
EOF

oc create -f - <
subjects:
  - kind: ServiceAccount
    name: gitlab-runner-app-sa
roleRef:
  kind: Role
  name: scc-anyuid
  apiGroup: rbac.authorization.k8s.io
EOF

헬퍼 컨테이너와 빌드 컨테이너의 사용자 ID 및 그룹 ID 불일치#

GitLab Runner Operator 디플로이먼트는 기본 헬퍼 이미지로 registry.gitlab.com/gitlab-org/ci-cd/gitlab-runner-ubi-images/gitlab-runner-helper-ocp를 사용합니다. 이 이미지는 보안 컨텍스트로 명시적으로 수정하지 않는 한 사용자 ID 및 그룹 ID 1001:1001로 실행됩니다.

빌드 컨테이너의 사용자 ID가 헬퍼 이미지의 사용자 ID와 다를 경우, 헬퍼 컨테이너가 생성한 파일 (클론된 리포지터리와 복원된 캐시)의 소유자가 1001:1001이므로 빌드 중 권한 관련 오류가 발생할 수 있습니다. 이 불일치는 다음 두 가지 일반적인 문제를 일으킵니다:

헬퍼 컨테이너와 빌드 컨테이너의 사용자 ID 일치시키기#

두 문제 모두에 대한 해결 방법은 빌드 컨테이너의 보안 컨텍스트를 헬퍼 컨테이너의 사용자 ID 및 그룹 ID에 맞게 구성하는 것입니다:

[runners.kubernetes.build_container_security_context]
run_as_user = 1001
run_as_group = 1001

추가 참고 사항:

  • 이 설정은 리포지터리를 클론하는 컨테이너와 빌드하는 컨테이너 간에 일관된 파일 소유권을 보장합니다.

  • 헬퍼 이미지를 다른 사용자 ID 또는 그룹 ID로 사용자 정의한 경우 이 값을 그에 맞게 조정하세요.

  • OpenShift 디플로이먼트의 경우, 이러한 보안 컨텍스트 설정이 클러스터의 보안 컨텍스트 제약(SCC)을 준수하는지 확인하세요.

빌드 컨테이너의 사용자 ID를 변경할 수 없는 경우(예: 사용자 ID가 고정된 서드파티 이미지를 사용하거나, build_container_security_context를 수정할 수 없는 공유 러너를 사용하는 경우)에는 각 문제에 대해 설명된 우회 방법을 대신 사용하세요.

Git dubious ownership 오류#

빌드 컨테이너가 헬퍼 컨테이너가 클론한 리포지터리에 접근하면 Git은 다음과 같이 보고합니다:

fatal: detected dubious ownership in repository at '/builds/gitlab-org/gitlab-runner'

이 오류는 리포지터리가 사용자 ID 1001(헬퍼 컨테이너)에 의해 클론되었지만, 빌드 컨테이너의 다른 사용자 ID가 이에 접근하려 한다는 것을 나타냅니다.

이 오류를 해결하려면 다음 중 하나를 수행하세요:

헬퍼 컨테이너와 빌드 컨테이너의 사용자 ID를 일치시킵니다.

Git의 safe.directory 설정을 사용하여 소유권 불일치에도 불구하고 Git이 해당 리포지터리 디렉터리를 신뢰하도록 구성합니다. HOME 환경 변수는 쓰기 가능한 디렉터리를 가리켜야 하므로, before_script에서 설정할 수 있습니다:

my_job:
  before_script:
    - git config --global --add safe.directory $CI_PROJECT_DIR

safe.directory 설정은 dubious ownership 오류만 해결합니다. 리포지터리 파일의 소유자는 여전히 헬퍼 컨테이너의 사용자 ID이므로, 리포지터리 디렉터리에 쓰기를 수행하는 job은 여전히 권한 오류를 만날 수 있습니다.

캐시 권한 오류#

사용자 ID 불일치는 CI/CD 캐시에도 영향을 줍니다. 이 문제는 사용자 ID가 헬퍼 이미지의 사용자 ID와 일치하지 않는 non-root 빌드 컨테이너에 영향을 줍니다. root로 실행되는 빌드 컨테이너는 영향을 받지 않습니다.

OCP 헬퍼 이미지는 캐시 파일을 사용자 ID 1001로 아카이브하고 추출합니다. 빌드 컨테이너가 다른 사용자 ID로 실행되면, 파일의 소유자가 1001:1001이므로 복원된 캐시 디렉터리에 쓸 수 없습니다.

증상은 다음과 같습니다:

  • 캐시는 성공적으로 복원되지만, 애플리케이션이 새 캐시 항목을 쓸 수 없습니다.

  • 캐시 디렉터리에 쓸 때 Permission denied 오류가 발생합니다.

  • 빌드 컨테이너가 파일을 소유하고 있지 않으므로 before_scriptchown이 실패합니다.

이러한 오류를 해결하려면 다음 중 하나를 수행하세요:

헬퍼 컨테이너와 빌드 컨테이너의 사용자 ID를 일치시킵니다.

헬퍼가 캐시를 아카이브하기 전에 after_script에서 캐시 파일을 모든 사용자가 쓸 수 있도록 만듭니다. 이후 복원 시 777 권한이 tar 아카이브에 보존되므로, 어떤 사용자 ID든 읽고 쓸 수 있습니다:

my_job:
  after_script:
    - chmod -R 777 my-cache-dir/ 2>/dev/null || true
  cache:
    key: my-cache-key
    paths:
      - my-cache-dir/

이 우회 방법을 추가한 후에는 기존 캐시를 지우세요. 그래야 첫 실행에서 777 권한의 새 파일이 생성되어 이후의 아카이브 및 복원 주기에서도 유지됩니다.

SETFCAP 구성#

Red Hat OpenShift Container Platform(RHOCP) 4.11 이상을 사용하는 경우 다음 오류 메시지가 표시될 수 있습니다:

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

일부 job(예: buildah)은 올바르게 실행하기 위해 SETFCAP 기능이 부여되어야 합니다. 이 문제를 해결하려면:

GitLab Runner가 사용하는 보안 컨텍스트 제약에 SETFCAP 기능을 추가합니다(gitlab-scc를 GitLab Runner Pod에 할당된 보안 컨텍스트 제약으로 교체하세요):

oc patch scc gitlab-scc --type merge -p '{"allowedCapabilities":["SETFCAP"]}'

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"]

GitLab Runner가 배포된 네임스페이스에서 이 config.toml을 사용하여 ConfigMap을 생성합니다:

oc create configmap custom-config-toml --from-file config.toml=config.toml

수정할 러너에서 최근 생성한 ConfigMap을 가리키는 config: 파라미터를 추가합니다(my-runner를 올바른 러너 Pod 이름으로 교체하세요).

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

자세한 내용은 Red Hat 문서를 참조하세요.

자체 서명 인증서를 사용한 GitLab Runner 등록#

GitLab Self-Managed에서 자체 서명 인증서를 사용하려면, 개인 인증서 서명에 사용한 CA 인증서가 포함된 Secret을 생성하세요.

그런 다음 Runner spec 섹션에서 해당 Secret 이름을 CA로 제공합니다:

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

FIELD:    ca <string>

DESCRIPTION:
     Name of tls secret containing the custom certificate authority (CA)
     certificates

다음 명령을 사용하여 Secret을 생성할 수 있습니다:

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

IP 주소를 가리키는 외부 URL로 GitLab Runner 등록#

러너가 자체 서명 인증서와 호스트 이름을 일치시키지 못하면 오류 메시지가 표시될 수 있습니다. 이 문제는 GitLab Self-Managed를 호스트 이름 대신 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

이 문제를 해결하려면:

GitLab Self-Managed 서버에서 openssl을 수정하여 subjectAltName 파라미터에 IP 주소를 추가합니다:

# vim /etc/pki/tls/openssl.cnf

[ v3_ca ]
subjectAltName=IP:169.57.64.36 <---- Add this line. 169.57.64.36 is your GitLab server IP.

아래 명령으로 자체 서명 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

이 새 인증서를 사용하여 새 Secret을 생성합니다.

패칭#

podSpecdeploymentSpec Operator 속성을 통해 설정하는 스펙 패치를 사용하여 Operator가 생성하는 쿠버네티스 리소스를 사용자 정의할 수 있습니다.

패치 구조#

각 스펙 패치는 다음 속성으로 구성됩니다:

설정 설명
name 사용자 정의 스펙 패치의 이름.
patchFile 생성 전 최종 스펙에 적용할 변경 사항을 정의하는 파일 경로. 파일은 JSON 또는 YAML 형식이어야 합니다.
patch 생성 전 최종 스펙에 적용할 변경 사항을 기술하는 JSON 또는 YAML 형식 문자열.
patchType 스펙에 지정된 변경 사항을 적용하는 전략. 허용 값은 merge, json, strategic(기본값)입니다.

동일한 스펙 구성에서 patchFilepatch를 함께 설정할 수 없습니다.

러너 Pod 템플릿 패치 적용#

Pod 스펙 패치 적용을 통해 Operator가 생성한 쿠버네티스 디플로이먼트에 패치를 적용하여 GitLab Runner 배포 방식을 사용자 정의할 수 있습니다. 패치는 Pod 템플릿의 스펙(deployment.spec.template.spec)에 적용됩니다.

다음과 같은 Pod 레벨 설정을 제어할 수 있습니다:

  • 리소스 요청 및 제한

  • 보안 컨텍스트

  • 볼륨 마운트 및 볼륨

  • 환경 변수

  • 노드 셀렉터 및 어피니티 규칙

  • Toleration

  • 호스트 이름 및 DNS 구성

러너 디플로이먼트 템플릿 패치 적용#

디플로이먼트 스펙 패치 적용을 통해 Operator가 생성한 쿠버네티스 디플로이먼트에 패치를 적용하여 GitLab Runner 배포 방식을 사용자 정의할 수 있습니다. 패치는 디플로이먼트 스펙(deployment.spec)에 적용됩니다.

다음과 같은 디플로이먼트 레벨 설정을 제어할 수 있습니다:

  • 레플리카 수

  • 디플로이먼트 전략(RollingUpdate, Recreate)

  • 리비전 히스토리 제한

  • 진행 데드라인(초)

  • 라벨 및 어노테이션

패치 순서#

디플로이먼트 스펙 패치가 Pod 스펙 패치보다 먼저 적용됩니다. 따라서 디플로이먼트 스펙과 Pod 스펙이 동일한 필드를 수정하는 경우 Pod 스펙이 우선합니다.

예시#

Pod 스펙 패치 적용 예시#

apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
  name: dev
spec:
  gitlabUrl: https://gitlab.example.com
  token: gitlab-runner-secret
  podSpec:
    - name: "set-hostname"
      patch: |
        hostname: "custom-hostname"
      patchType: "merge"
    - name: "add-resource-requests"
      patch: |
        containers:
        - name: build
          resources:
            requests:
              cpu: "500m"
              memory: "256Mi"
      patchType: "strategic"

디플로이먼트 스펙 패치 적용 예시#

apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
  name: dev
spec:
  gitlabUrl: https://gitlab.example.com
  token: gitlab-runner-secret
  deploymentSpec:
    - name: "set-replicas"
      patch: |
        replicas: 3
      patchType: "strategic"
    - name: "configure-strategy"
      patch: |
        strategy:
          type: RollingUpdate
          rollingUpdate:
            maxUnavailable: 25%
            maxSurge: 50%
      patchType: "strategic"
    - name: "set-revision-history"
      patch: |
        [{"op": "add", "path": "/revisionHistoryLimit", "value": 10}]
      patchType: "json"

모범 사례#

  • 프로덕션 디플로이먼트에 적용하기 전에 비프로덕션 환경에서 패치를 테스트하세요.

  • 개별 Pod 설정이 아닌 디플로이먼트 동작에 영향을 미치는 설정에는 디플로이먼트 레벨 패치를 사용하세요.

  • 충돌하는 필드의 경우 Pod 스펙 패치가 디플로이먼트 스펙 패치를 재정의한다는 점을 기억하세요.