OpenShift에서 GitLab Runner 구성
GitLab v19.2| --- | --- | | 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 서버가 수신 대기할 주소(
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
Runner의 config 속성을 설정합니다:
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.yaml의 ca 키를 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은 해당 역할 바인딩의 subjects 및 roleRef에 정의된 역할과 서비스 어카운트를 확인합니다.
두 역할 바인딩이 모두 존재하는 경우, gitlab-runner-app-rolebinding이 gitlab-runner-rolebinding보다 우선합니다.
문제 해결#
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와 같은 디렉터리를 생성하고 Dockerfile에 ENV 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와 다를 경우, 빌드 중 권한 관련 오류가 발생할 수 있습니다. 다음은 일반적인 오류 메시지입니다:
fatal: detected dubious ownership in repository at '/builds/gitlab-org/gitlab-runner'
이 오류는 리포지터리가 사용자 ID 1001(헬퍼 컨테이너)에 의해 클론되었지만, 빌드 컨테이너의 다른 사용자 ID가 이에 접근하려 한다는 것을 나타냅니다.
해결 방법: 빌드 컨테이너의 보안 컨텍스트를 헬퍼 컨테이너의 사용자 ID 및 그룹 ID에 맞게 구성합니다:
[runners.kubernetes.build_container_security_context]
run_as_user = 1001
run_as_group = 1001
추가 참고 사항:
-
이 설정은 리포지터리를 클론하는 컨테이너와 빌드하는 컨테이너 간에 일관된 파일 소유권을 보장합니다.
-
헬퍼 이미지를 다른 사용자 ID 또는 그룹 ID로 사용자 정의한 경우 이 값을 그에 맞게 조정하세요.
-
OpenShift 디플로이먼트의 경우, 이러한 보안 컨텍스트 설정이 클러스터의 보안 컨텍스트 제약(SCC)을 준수하는지 확인하세요.
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 문서를 참조하세요.
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
자체 서명 인증서를 사용한 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을 생성합니다.
패치 구조#
각 스펙 패치는 다음 속성으로 구성됩니다:
| 설정 | 설명 |
|---|---|
| name | 사용자 정의 스펙 패치의 이름. |
| patchFile | 생성 전 최종 스펙에 적용할 변경 사항을 정의하는 파일 경로. 파일은 JSON 또는 YAML 형식이어야 합니다. |
| patch | 생성 전 최종 스펙에 적용할 변경 사항을 기술하는 JSON 또는 YAML 형식 문자열. |
| patchType | 스펙에 지정된 변경 사항을 적용하는 전략. 허용 값은 merge, json, strategic(기본값)입니다. |
동일한 스펙 구성에서 patchFile과 patch를 함께 설정할 수 없습니다.
러너 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 스펙 패치가 디플로이먼트 스펙 패치를 재정의한다는 점을 기억하세요.