깃랩 러너(GitLab Runner) 구축: 내 파이프라인에 생명을 불어넣자

“지시서는 올렸는데, 왜 반응이 없지?”

지난 시간, 나는 야심 차게 .gitlab-ci.yml 파일을 작성해서 push 했다. “이제 배포가 자동으로 되겠지?”라며 기대에 차서 GitLab의 ‘CI/CD > Pipelines’ 메뉴를 클릭했다.

하지만 화면에 뜬 것은 초록색 성공 표시가 아니라, 하염없이 돌아가는 로딩 바와 ‘Pending (보류 중)’이라는 상태 메시지뿐이었다. 메시지를 클릭해 보니 이런 경고가 떠 있었다.

This job is stuck because the project doesn't have any runners online assigned to it.

해석하자면 “일감이 들어왔는데, 이걸 처리할 작업자(Runner)가 출근을 안 했습니다”라는 뜻이다. 아차, 나는 공장장(GitLab Server)에게 작업 지시서만 던져주고, 정작 공장에서 일할 직원(Runner)을 채용하지 않았던 것이다.

설계도가 아무리 완벽해도, 그걸 조립할 ‘일꾼’이 없으면 공장은 돌아가지 않는다.

깃랩 러너(GitLab Runner): 파이프라인의 손과 발

GitLab은 크게 두 가지 요소로 나뉜다.

  1. GitLab Server (본사/공장장): 코드를 저장하고, 파이프라인 상태를 관리하고, 지시를 내린다.
  2. GitLab Runner (지사/현장직): 실제 서버에 설치되어, 본사의 지시를 받아 코드를 가져오고, 빌드하고, 배포 명령을 수행한다.

“그냥 GitLab이 알아서 내 서버에 접속해서 배포해주면 안 되나요?” 생각해 보면 위험천만한 일이다. 만약 인터넷에 있는 웹사이트(GitLab)가 버튼 하나 눌렀다고 해서 내 방에 있는 컴퓨터(서버)에 들어와 맘대로 명령어를 실행할 수 있다면? 그건 ‘해킹’이나 다름없다. 누군가 내 GitLab 계정을 털면 내 서버를 비트코인 채굴기로 만들어버릴 수도 있다.

그래서 GitLab은 직접 내 서버에 접속하지 않는다. 대신 내 서버 안에서만 동작하는 ‘신원 확실한 대리인(Runner)’을 심어두고, 그 대리인을 통해서만 일을 시킨다. 우리가 지금부터 할 복잡한 설치와 등록 과정은 바로 이 대리인을 인증하는 ‘보안 절차’다.

1단계: 채용 공고 확인하기 (토큰 발급)

러너를 설치하기 전에, 먼저 본사(GitLab)에서 “우리 프로젝트에 일꾼이 필요합니다”라는 ‘채용 공고’를 내고 ‘등록증(Token)’을 받아야 한다.

최신 GitLab 버전에서는 보안 강화를 위해 토큰 확인 방법이 조금 숨겨져 있다.

  1. GitLab 프로젝트 접속
  2. 왼쪽 메뉴: Settings > CI/CD
  3. Runners 섹션의 Expand 클릭
  4. Project runners 섹션 우측 상단에 있는 점 3개 버튼(⋮) 클릭

이 버튼을 누르면 팝업 메뉴가 뜨는데, 여기에 우리가 찾는 정보가 있다. URLRegistration token을 확인하고 복사해두자.

(참고: ‘Support for registration tokens is deprecated’라는 무시무시한 경고가 뜰 수 있다. 곧 사라질 방식이라는 뜻이지만, 아직은 호환성을 위해 지원하니 당황하지 말고 토큰을 복사하면 된다.)

[Tip] 프로젝트가 여러 개라면? (Group Runner) 만약 나처럼 프론트엔드, 백엔드 등 여러 프로젝트를 하나의 그룹으로 묶어 관리하고 있다면, 프로젝트마다 일일이 러너를 등록하는 건 비효율적이다. 이때는 프로젝트 설정이 아니라 그룹 설정(Group Settings) > CI/CD 메뉴에서 러너를 등록하면 된다. 이렇게 만든 ‘Group Runner’는 해당 그룹에 속한 모든 프로젝트의 일감을 혼자서 다 처리할 수 있다. (나는 프로젝트가 많아서 이 방식을 택했다.)

숨겨진 메뉴(⋮)를 열어야 토큰을 볼 수 있다. 이 토큰은 러너와 서버를 연결하는 ‘비밀 열쇠’이니 절대 유출하면 안 된다.

2단계: 일꾼 채용하기 (Runner 설치)

이제 리눅스 서버(혹은 내 PC)에 러너를 실제로 설치해 보자. 가장 깔끔한 방법은 역시 우리가 사랑하는 ‘도커(Docker)’를 이용하는 것이다.

# 1. 깃랩 러너 컨테이너 실행
docker run -d --name gitlab-runner --restart always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v gitlab-runner-config:/etc/gitlab-runner \
  gitlab/gitlab-runner:latest

  • -v /var/run/docker.sock:/var/run/docker.sock: 이게 중요하다. 러너가 또 다른 도커 컨테이너(빌드용)를 띄워야 하기 때문에, 호스트의 도커 소켓을 공유해 주는 것이다. (Docker in Docker 방식)

3단계: 근로 계약서 작성 (Runner 등록)

러너를 설치했다고 끝이 아니다. 이 러너가 “나는 A 프로젝트의 일꾼입니다”라고 GitLab 서버에 등록(Register)하는 절차가 필요하다.

방금 띄운 러너 컨테이너 안으로 들어가서 등록 명령어를 실행하자.

# 러너 컨테이너 내부에서 등록 명령어 실행
docker exec -it gitlab-runner gitlab-runner register

이제 터미널에서 스무고개 같은 질문이 시작된다. 아까 1단계에서 본 정보를 입력하면 된다.

  1. Enter the GitLab instance URL:
    • https://gitlab.com/ (또는 사설 깃랩 주소)
  2. Enter the registration token:
    • (아까 복사한 토큰 붙여넣기)
  3. Enter a description for the runner:
    • my-runner-01 (아무거나, 알아보기 쉬운 이름)
  4. Enter tags for the runner:
    • (엔터 쳐서 생략 가능. 특정 태그가 달린 작업만 시킬 때 쓴다.)
  5. Enter an executor:
    • docker (우리는 도커 위에서 빌드할 거니까 docker라고 입력한다.)
  6. Enter the default Docker image:
    • docker:latest (기본으로 사용할 이미지)

“Runner registered successfully.” 이 메시지가 뜨면 채용 완료다! 이제 GitLab 화면을 새로고침 해보면, 초록색 불이 들어온 러너가 “준비됐습니다(Online)”라고 외치고 있을 것이다.

연동이 성공하면 GitLab 화면의 러너 상태등이 초록색으로 바뀐다.

4단계: 파이프라인 가동!

러너가 등록되는 순간, 멈춰있던(Pending) 파이프라인이 자동으로 움직이기 시작한다. Running… 그리고 잠시 후 Passed!

내가 아무것도 안 했는데, 기계가 알아서 테스트를 돌리고, 빌드를 하고, 이미지를 만들어서 저장소에 올렸다. 터미널을 열어 로그를 확인해 보니, 내가 수동으로 칠 때보다 훨씬 빠르고 정확하게 모든 과정이 끝나 있었다.

“와… 진짜 되네?”

10분 걸리던 수동 배포가, 이제는 git push 한 번에 끝난다. 나는 이제 배포를 걸어놓고 커피를 마시러 갈 수 있게 되었다.

실무 조언: 도커 권한 문제 (Permission Denied)

처음 러너를 세팅할 때 99% 확률로 마주치는 에러가 있다. dial unix /var/run/docker.sock: connect: permission denied

러너가 도커 명령어를 쓰려고 하는데 권한이 없어서 생기는 문제다. 이럴 땐 gitlab-runner 설정 파일(config.toml)을 열어서 privileged = true 옵션을 켜줘야 한다.

# /etc/gitlab-runner/config.toml (러너 설정 파일)
[[runners]]
  name = "my-runner-01"
  executor = "docker"

[runners.docker]

privileged = true # 이 부분을 true로 바꿔줘야 Docker-in-Docker가 잘 된다. # …

마치며: 이제 퇴근할 수 있다

드디어 나만의 ‘배포 로봇’이 생겼다. 이제 나는 코드를 짜는 데만 집중하면 된다. 지루하고 반복적인 검증과 배포 작업은 나의 충실한 로봇(Runner)이 대신해 줄 테니까.

하지만 아직 2% 부족하다. 지금은 파이프라인이 master 브랜치에 푸시될 때마다 무조건 실행된다. “개발용 서버(dev)에는 자동으로 배포하고 싶지만, 운영 서버(prod)는 내가 ‘승인 버튼’을 눌렀을 때만 배포하고 싶다면?”

다음 시간에는 파이프라인을 더 똑똑하게 제어하는 ‘브랜치별 배포 전략’과 ‘수동 승인(Manual) 절차’에 대해 알아보자.

댓글 남기기