GitLab Runner
GitLab Runner란?
GitLab CI/CD 파이프라인의 잡(Job)을 실제로 실행하는 에이전트다.
.gitlab-ci.yml에 파이프라인을 정의해두면, GitLab 서버는 잡을 큐에 올리고, Runner가 그 잡을 받아서 실행한다. GitLab 서버와 Runner는 별개로 동작한다.
GitLab 서버 (잡 스케줄링)
↓ 잡 할당
GitLab Runner (잡 실행)
↓
결과 리포트
Runner 종류 (범위)
| 종류 | 설명 |
|---|---|
| Shared Runner | GitLab 인스턴스 전체에서 사용. GitLab.com이 제공하는 공용 Runner |
| Group Runner | 특정 그룹과 그 하위 프로젝트에서만 사용 |
| Project Runner | 특정 프로젝트에서만 사용 |
자체 서버나 EKS 클러스터에 Runner를 직접 설치하면 Group/Project Runner로 등록해서 쓴다.
Executor
Runner가 잡을 어떤 방식으로 실행할지 결정하는 설정이다.
| Executor | 설명 | 특징 |
|---|---|---|
shell | Runner가 설치된 호스트에서 직접 실행 | 가장 단순, 환경 격리 없음 |
docker | 각 잡을 Docker 컨테이너에서 실행 | 잡마다 격리된 환경 |
kubernetes | 쿠버네티스 파드로 잡 실행 | EKS 등 K8s 클러스터에서 주로 사용 |
docker+machine | Auto-scaling 지원 Docker | GitLab.com 공용 Runner에서 사용 |
실무에서 EKS 환경이라면 kubernetes executor를 가장 많이 쓴다.
Kubernetes Executor 동작 방식
Runner 자체는 클러스터 안에 항상 떠 있는 파드다. 잡이 들어오면 해당 잡을 실행할 **임시 파드(helper pod)**를 동적으로 생성하고, 잡이 끝나면 삭제한다.
GitLab Runner Pod (상시 실행)
↓ 잡 수신
임시 Job Pod 생성 (잡 실행용)
↓ 잡 완료
임시 Job Pod 삭제
임시 파드는 보통 세 개의 컨테이너로 구성된다:
build: 실제 잡 스크립트 실행helper: 아티팩트 업로드/다운로드, git clone 등 보조 작업service:.gitlab-ci.yml의services에 정의한 사이드카 (DB 등)
등록 방법
Runner를 GitLab에 연결하려면 등록 토큰이 필요하다.
# Runner 등록 (interactive)
gitlab-runner register
# 또는 non-interactive
gitlab-runner register \
--url "https://gitlab.com/" \
--registration-token "TOKEN" \
--executor "kubernetes" \
--description "my-runner"등록하면 config.toml에 설정이 저장된다.
config.toml 주요 설정
Runner의 동작은 config.toml으로 제어한다. Kubernetes executor 기준:
[[runners]]
name = "my-runner"
url = "https://gitlab.com/"
token = "xxxx"
executor = "kubernetes"
[runners.kubernetes]
namespace = "gitlab-runner"
image = "alpine"
cpu_request = "100m"
memory_request = "128Mi"
cpu_limit = "1"
memory_limit = "1Gi"
[runners.kubernetes.volumes]
[[runners.kubernetes.volumes.pvc]]
name = "runner-cache"
mount_path = "/cache".gitlab-ci.yml과의 관계
Runner는 .gitlab-ci.yml에서 tags로 특정 Runner를 선택할 수 있다.
build:
tags:
- my-runner # 이 태그를 가진 Runner에서만 실행
script:
- ./gradlew buildRunner 등록 시 태그를 지정해두면, 잡의 태그와 매칭되는 Runner가 해당 잡을 가져간다.
캐시 (Cache)
잡 간에 파일을 재사용해서 빌드를 빠르게 한다. 의존성 파일(.gradle, node_modules 등)을 캐시해두면 매번 다운로드하지 않아도 된다.
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- .gradle/
- build/Kubernetes executor에서는 캐시를 PVC나 S3에 저장한다.
아티팩트 (Artifacts)
잡이 생성한 파일을 다음 잡이나 GitLab UI에서 다운로드할 수 있게 보존한다.
build:
script:
- ./gradlew :prism:install
artifacts:
paths:
- prism/build/install/
expire_in: 1 week # 보존 기간캐시와 아티팩트의 차이:
- 캐시: 빌드 속도 향상용, 잡 간 공유, 보장되지 않음 (없어도 잡은 실행됨)
- 아티팩트: 잡 결과물 전달용, 파이프라인 내 다음 스테이지에 전달, 보장됨
트러블슈팅
파드가 Pending 상태에서 타임아웃
ERROR: Job failed (system failure): prepare environment:
waiting for pod running: timed out waiting for pod to start.
임시 잡 파드가 스케줄링되지 못한 경우. 원인:
- 리소스(CPU/메모리) 부족 → 노드 스케일링 확인
- PVC의 node affinity 불일치 → PVC 재생성 필요
- 노드 taint와 파드 toleration 불일치 → Runner config의 toleration 설정 확인
# 임시 잡 파드 상태 확인
kubectl get pods -n gitlab-runner
# 스케줄링 실패 이유 확인
kubectl describe pod <job-pod-name> -n gitlab-runnerRunner가 잡을 가져가지 않음
- Runner가 등록된 태그와 잡의 태그가 불일치하는지 확인
- Runner가
paused상태인지 확인 (GitLab UI → Settings → CI/CD → Runners) config.toml의concurrent값이 낮아서 잡 처리 한도를 초과했는지 확인
concurrent = 10 # 동시에 처리할 수 있는 최대 잡 수Docker-in-Docker (DinD) 권한 오류
잡 안에서 Docker 명령을 실행해야 할 때 (이미지 빌드 등) privileged 모드가 필요하다.
[runners.kubernetes]
privileged = true보안상 민감하므로 꼭 필요한 Runner에만 설정한다.
댓글 (0)