본문 바로가기
기술 공부/DevOps

GitLab Runner 설치 및 Terraform 파이프라인 구성

by soy-ul 2026. 1. 31.
반응형

시리즈 : GitLab + Terraform + Ansible 으로 VM 프로비저닝 자동화하기 

1. [Rocky Linux 기반 GitLab Docker 설치하기] 
2. [Terraform 기초 - Docker Provider로 배우기] 
3.GitLab Runner 설치 및 Terraform 파이프라인 구성
4. GitLab CI/CD로 VM 자동 생성 실전 (예정)
5. [Terraform 디스크 문제와 xe 명령어 전환] (예정)
6. [GitHub vs GitLab CI/CD 실전 비교] (예정)

 

🔹 들어가며

이전 글에서 GitLab을 Docker로 구축하고, Terraform 기초를 Docker Provider로 학습했습니다. 이번에는 본격적으로 GitLab Runner를 설치하고 CI/CD 파이프라인을 구성해보았는데요.

Runner 설치부터 .gitlab-ci.yml 파이프라인 작성까지 다루고, 다음 편에서 실제로 VM을 생성하는 과정을 다루겠습니다.

이번 편에서 다룰 내용

  • Terraform XO Provider 네트워크 설정 문제 해결 - NIC명 인식실패 이슈 트러블슈팅
  • GitLab Runner 설치 및 등록
  • GitLab 프로젝트 생성
  • Terraform 코드 CI/CD용으로 수정
  • 3단계 파이프라인 구성 (validate → plan → apply)

 

🔹 아키텍처

┌─────────────────────────────────────────────────────────────────────────┐
│                           작업 흐름                                      │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   [개발자]                                                               │
│      │                                                                  │
│      │ 1. git push (Terraform 코드)                                     │
│      ▼                                                                  │
│   [GitLab]                                                              │
│      │ http://gitlab.company.local                                     │
│      │                                                                  │
│      │ 2. Pipeline 트리거                                               │
│      ▼                                                                  │
│   [GitLab Runner]                                                       │
│      │ shell executor                                                  │
│      │                                                                  │
│      │ 3. terraform init/validate/plan/apply                           │
│      ▼                                                                  │
│   [Xen Orchestra API]                                                   │
│      │ wss://[XO_SERVER_IP]                                            │
│      │                                                                  │
│      │ 4. VM 생성 요청                                                  │
│      ▼                                                                  │
│   [XCP-NG]                                                              │
│      │                                                                  │
│      ▼                                                                  │
│   [VM 생성 완료] ← 다음 편에서 다룰 예정                                  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

 


🔹 준비 환경

이미 구축된 구성 요소

Docker 29.1.5 실행 중 -
GitLab CE latest 실행 중 (Docker) #19
Terraform 1.14.3 설치됨 #20
XO Provider 0.26.1 설치됨 -

작업 서버

  • GitLab/Runner 서버: Rocky Linux 9.7
  • XCP-NG 호스트: 가상화 서버(LNX)
  • XO 서버: Xen Orchestra 관리 서버

🔹 Step 1: Terraform XO Provider 네트워크 트러블슈팅

이슈 상황

Terraform 코드를 작성하고 terraform plan을 실행했는데 NIC 관련 에러가 발생했습니다.

$ terraform plan

Error: Invalid data resource name

  on main.tf line 12, in data "xenorchestra_network" "Pool-wide network associated with eth0":
  12: data "xenorchestra_network" "Pool-wide network associated with eth0" {

A name must start with a letter or underscore and may contain only letters,
digits, underscores, and dashes.

 

 

# ❌ 잘못된 코드 - 리소스 이름에 공백과 특수문자 사용
data "xenorchestra_network" "Pool-wide network associated with eth0" {
  name_label = "eth0"  # 잘못된 name_label
}

처음에는 XO의 네트워크 이름을 그대로 리소스 이름으로 사용하였는데, 이것이 Terraform의 네이밍 규칙에 맞지 않아 에러가 발생한 것이었습니다. 

 

분석

Terraform 리소스 이름XO 네트워크 name_label의 역할을 혼동했습니다.

구분 위치 용도 규칙
리소스 이름 두 번째 따옴표 "net" Terraform 코드 내부에서 참조할 때 사용 영문, 숫자, _, - 만 허용
name_label 속성 값 XO API에서 실제 검색할 네트워크 이름 제한 없음 (공백, 특수문자 가능)

 

해결 방법

XO 웹 UI에서 실제 네트워크 이름을 확인했습니다.

XO에서 네트워크 이름 확인하는 방법:

  1. XO 웹 UI 접속
  2. Home → Pools → 해당 Pool 선택
  3. Network 탭 확인
  4. 네트워크 이름: Pool-wide network associated with eth0

수정된 코드:

  • "MY_NETWORK_ID" = Terraform 코드에서 이 네트워크를 참조할 때 사용하는 변수명 (마음대로 정할 수 있음)
  • "실제 XO에 있는 네트워크 이름" = XO에 실제로 존재하는 네트워크의 정확한 이름 (반드시 일치해야 함)
# ✅ 올바른 코드
data "xenorchestra_network" "net" {
  name_label = "Pool-wide network associated with eth0"
}

정리:

  • "net" = Terraform 내부 참조명 
  • "Pool-wide network associated with eth0" = XO의 실제 네트워크 이름

수정 후 테스트

$ terraform plan

data.xenorchestra_network.net: Reading...
data.xenorchestra_pool.pool: Reading...
data.xenorchestra_template.rocky_template: Reading...
data.xenorchestra_network.net: Read complete after 0s [id=fd11b7be-e45e-1169-08c3-8eca6fbacfd9]
data.xenorchestra_pool.pool: Read complete after 0s [id=a4a6e4f7-f1d7-b679-1a84-6976f4408910]
data.xenorchestra_template.rocky_template: Read complete after 0s [id=161d9507-c826-fa65-bf9a-0a6fa755a4a3]

Terraform will perform the following actions:

  # xenorchestra_vm.new_rocky_vm will be created
  + resource "xenorchestra_vm" "new_rocky_vm" {
      + cpus       = 2
      + memory_max = 4294967296
      + name_label = "VM-Provisioned-by-Terraform"
      ...
    }

Plan: 1 to add, 0 to change, 0 to destroy.
 

성공! 👍

 


🔹 Step 2: GitLab Runner 설치

GitLab Runner란?

GitLab CI/CD 파이프라인을 실행하는 에이전트

역할:

  • GitLab에서 파이프라인이 트리거되면 Runner가 작업을 수행
  • 테스트, 빌드, 배포 등 자동화 작업 실행
  • 여러 Executor 타입 지원 (ex. shell, docker, kubernetes 등)

우리가 사용할 구성:

  • Executor: shell (호스트에 설치된 Terraform 직접 사용)
  • 장점: 간단하고 빠름

 

GitLab Runner 저장소 추가

$ curl -L 'https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh' | sudo bash

Detected operating system as rocky/9.
Checking for curl...
Detected curl...
Downloading repository file: https://packages.gitlab.com/install/repositories/runner/gitlab-runner/config_file.repo?os=rocky&dist=9&source=script
done.
Installing yum-utils...
Generating yum cache for runner_gitlab-runner...
Generating yum cache for runner_gitlab-runner-source...

The repository is setup! You can now install packages.
 

GitLab Runner 설치 패키지 및 버전 조회

설치 중:
 gitlab-runner                 x86_64   18.8.0-1   runner_gitlab-runner    26 M
 gitlab-runner-helper-images   noarch   18.8.0-1   runner_gitlab-runner   520 M

트랜잭션 요약
================================================================================
설치  2 패키지

다운로드 크기: 546 M
설치 크기: 2.0 G
완료되었습니다!
$ gitlab-runner --version
Version:      18.8.0
Git revision: 9ffb4aa0
Git branch:   18-8-stable
GO version:   go1.25.3
Built:        2026-01-15T15:55:25Z
OS/Arch:      linux/amd64
 

GitLab에서 Runner 토큰 발급

GitLab Runner를 GitLab 인스턴스에 등록하기 위해 토큰을 발급해야 했습니다. 

참고로, GitHub Runner 설치 후 러너 접근을 위해 토큰을 발급하는 것과 동일한 과정입니다. 

생성한 Runner의 설정정보 및 작업이력 조회화면

 

 

발급 절차:

  1. GitLab 웹 UI 접속
  2. Admin Area (렌치 아이콘) 클릭
  3. CI/CDRunners 메뉴
  4. New instance runner 클릭
  5. 설정:
    • Platform: Linux
    • Tags: lnx_test_gitlab_runner (파이프라인에서 이 Runner 지정 시 사용)
    • Run untagged jobs: 체크박스 체크 완료
  6. Create runner 클릭
  7. 화면에 표시된 토큰 복사 (glrt-... 형식)

Tags 설정의 의미:

  • .gitlab-ci.yml에서 tags: [lnx_test_gitlab_runner]로 이 Runner를 지정 가능
  • 여러 Runner가 있을 때 특정 Runner로 작업을 라우팅할 수 있음

 

Runner 등록

$ sudo gitlab-runner register \
  --non-interactive \
  --url http://[GITLAB_IP] \
  --token [토큰 값] \
  --executor shell \
  --description 'terraform-runner'

파라미터 설명:

  • --non-interactive: 대화형 입력 없이 자동 등록
  • --url: GitLab 인스턴스 URL
  • --token: 발급받은 Runner 토큰
  • --executor shell: Shell Executor 사용
  • --description: Runner 설명 (GitLab UI에서 표시됨)

결과:

Runtime platform                                    arch=amd64 os=linux pid=123456 revision=9ffb4aa0 version=18.8.0
Running in system-mode.

Verifying runner... is valid                        runner=YuV3aAd_o
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"

 

Runner 상태 확인

$ sudo gitlab-runner status
gitlab-runner: Service is running
$ sudo gitlab-runner list
Runtime platform                                    arch=amd64 os=linux
Listing configured runners                          ConfigFile=/etc/gitlab-runner/config.toml
terraform-runner                                    Executor=shell Token=glrt-YuV3aAd_o... URL=http://[GITLAB_IP]
 
 

설정 파일 위치:

  • /etc/gitlab-runner/config.toml - Runner 설정 저장

주요 설정 확인:

concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "terraform-runner"
  url = "http://[GITLAB_IP]"
  id = 1
  token = "[토큰 값]"
  token_obtained_at = 2026-01-27T06:00:00Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "shell"
  [runners.cache]
    MaxUploadedArchiveSize = 0

 

주요 설정 항목:

  • concurrent = 1: 동시에 실행할 수 있는 Job 수
  • executor = "shell": Shell Executor 사용

🔹 Step 3: GitLab 프로젝트 생성

GitLab 웹 UI에서 프로젝트 생성

  1. GitLab 접속 (root 계정 로그인)
  2. New project 버튼 클릭
  3. Create blank project 선택
  4. 프로젝트 설정:
    • Project name: terraform_integration_test
    • Project URL: http://[GITLAB_IP]/root/terraform_integration_test
    • Visibility Level: Private (비공개)
    • Initialize repository with a README: ❌ 체크 해제
  5. Create project 클릭

프로젝트가 생성 완료!


🔹 Step 4: Terraform 코드 CI/CD용으로 수정

비밀번호 하드코딩 문제

기존 Terraform 코드에서는 XO 비밀번호를 직접 코드에 작성했습니다.

# ❌ 나쁜 예 - 비밀번호 하드코딩
provider "xenorchestra" {
  url      = "wss://[XO_SERVER_IP]"
  username = "root"
  password = "[실제 패스워드 값]"  # 패스워드 값 그대로 저장, 보안상 위험
  insecure = true
}

 

문제점:

  • Git 저장소에 비밀번호가 노출됨
  • 팀원들이 모두 비밀번호를 볼 수 있음
  • 비밀번호 변경 시 코드 수정 필요

해결 방법: GitLab CI/CD Variables 활용

비밀번호를 코드에서 분리하고 GitLab CI/CD Variables로 관리할 수 있습니다. 

디렉토리 구조 정리

# Terraform 작업 디렉토리 생성
$ mkdir -p /home/terraform
$ cd /home/terraform

provider.tf 작성

terraform {
  required_providers {
    xenorchestra = {
      source = "terra-farm/xenorchestra"
    }
  }
}

# ===== 변수 정의 =====
variable "xo_url" {
  description = "XO WebSocket URL"
  default     = "wss://[XO_SERVER_IP]"
}

variable "xo_username" {
  description = "XO username"
  default     = "admin"
}

variable "xo_password" {
  description = "XO password"   # TF_VAR_xo_password 와 매핑
  sensitive   = true
  # default 값 없음 - GitLab CI/CD Variables에서 주입됨
}

# ===== Provider 설정 =====
provider "xenorchestra" {
  url      = var.xo_url
  username = var.xo_username
  password = var.xo_password  # 변수 참조
  insecure = true
}

 

핵심 포인트:

  • variable "xo_password"에 default 값을 지정하지 않음
  • sensitive = true로 로그에 노출 방지
  • GitLab CI/CD에서 TF_VAR_xo_password 환경변수로 자동 주입됨

 

Terraform 환경변수 규칙:

  • TF_VAR_ 접두사가 붙은 환경변수는 Terraform이 자동으로 인식
  • TF_VAR_xo_password → var.xo_password로 자동 매핑

 

main.tf 작성

# ===== 1. 템플릿 조회 =====
data "xenorchestra_template" "rocky_template" {
  name_label = "Rocky_9_template"
}

# ===== 2. Pool 정보 조회 =====
data "xenorchestra_pool" "pool" {
  name_label = "xcp-ng-pool"
}

# ===== 3. 네트워크 정보 조회 =====
data "xenorchestra_network" "net" {
  name_label = "Pool-wide network associated with eth0"
}

# ===== 4. VM 생성 =====
resource "xenorchestra_vm" "new_rocky_vm" {
  name_label       = "VM-Provisioned-by-Terraform"
  name_description = "Terraform을 통해 Rocky_9_template에서 복제됨"
  template         = data.xenorchestra_template.rocky_template.id
  
  cpus       = 2
  memory_max = 4294967296  # 4GB
  
  network {
    network_id = data.xenorchestra_network.net.id
  }
  
  disk {
    name_label = "VM-Provisioned-by-Terraform-Disk"
    sr_id      = "[STORAGE_REPOSITORY_ID]"  # 실제 SR ID로 변경 필요
    size       = 21474836480  # 20GB
  }
  
  high_availability = "best-effort"
}

 

SR ID 확인 방법:

# XO CLI로 확인
$ xe sr-list

# 또는 XO 웹 UI에서 확인
# Home → Storage → 해당 Storage 클릭 → UUID 복사

 

 

.gitignore 생성

민감정보가 저장된 파일(개인정보 보관이나 인증서(*.cer, *.pem 등)은 Git에 커밋하지 않도록 설정해야 합니다. 

$ cat > .gitignore << 'EOF'
# Terraform
.terraform/
*.tfstate
*.tfstate.backup
*.tfvars
.terraform.lock.hcl

# Backup
backup_*/

# Secrets
*.pem
*.key
EOF

 

제외할 파일들:

  • .terraform/: Provider 플러그인 (용량 큼, 재생성 가능)
  • *.tfstate: 현재 인프라 상태 (민감 정보 포함 가능)
  • *.tfvars: 변수 파일 (비밀번호 포함 가능)
  • .terraform.lock.hcl: Provider 버전 잠금 파일

 

🔹 Step 5: CI/CD 파이프라인 구성

.gitlab-ci.yml 작성

GitLab CI/CD 파이프라인을 validate → plan → apply 3단계로 구성하였습니다. 

stages:
  - validate
  - plan
  - apply

variables:
  TF_ROOT: ${CI_PROJECT_DIR}

default:
  tags:
    - lnx_test_gitlab_runner  # Runner 태그 지정

before_script:
  - cd ${TF_ROOT}
  - terraform version

# ===== 1단계: 검증 =====
validate:
  stage: validate
  script:
    - terraform init
    - terraform validate
  only:
    - merge_requests
    - main

# ===== 2단계: 실행 계획 =====
plan:
  stage: plan
  script:
    - terraform init
    - terraform plan -out=tfplan
  artifacts:
    paths:
      - tfplan
    expire_in: 1 hour
  only:
    - merge_requests
    - main

# ===== 3단계: 배포 (수동 승인) =====
apply:
  stage: apply
  script:
    - terraform init
    - terraform apply -auto-approve tfplan
  dependencies:
    - plan
  when: manual  # 수동 승인 필요
  only:
    - main

 

파이프라인 흐름 설명

git push
    │
    ▼
┌─────────────┐
│  validate   │ ← 자동 실행
│  - init     │    Terraform 문법 검증
│  - validate │
└──────┬──────┘
       │ ✅ 성공 시
       ▼
┌─────────────┐
│    plan     │ ← 자동 실행
│  - init     │    변경사항 미리보기
│  - plan     │    tfplan 파일 생성
│  (artifact) │
└──────┬──────┘
       │ ✅ 성공 시
       ▼
┌─────────────┐
│   apply     │ ← 수동 승인 필요 (▶️ 버튼 클릭)
│  - init     │    실제 VM 생성
│  - apply    │
└─────────────┘

 

 

파이프라인 변수 설명

variables:
  TF_ROOT: ${CI_PROJECT_DIR}
  • CI_PROJECT_DIR: GitLab이 자동으로 제공하는 변수 (프로젝트 루트 경로)
  • TF_ROOT: Terraform 작업 디렉토리 (여기서는 프로젝트 루트와 동일)

 

before_script 설명

before_script:
  - cd ${TF_ROOT}
  - terraform version
  • 모든 Job이 실행되기 전에 자동 실행
  • Terraform 작업 디렉토리로 이동
  • Terraform 버전 확인 (로그에 기록)

🔹 최종 디렉토리 구조

/home/terraform/
├── .gitignore              # Git 제외 파일 목록
├── .gitlab-ci.yml          # CI/CD 파이프라인 정의
├── main.tf                 # VM 리소스 정의
└── provider.tf             # Provider 및 변수 설정

 

🔹 마치며

 

이번 글에서는 GitLab Runner를 설치하고 CI/CD 파이프라인을 구성해보았습니다. 

 

완료한 작업:

  • ✅ Terraform XO Provider 네트워크 설정 문제 해결
  • ✅ GitLab Runner 설치 및 등록 (Shell Executor)
  • ✅ GitLab 프로젝트 생성
  • ✅ Terraform 코드 CI/CD용으로 수정 (비밀번호 분리)
  • ✅ 3단계 파이프라인 구성 (validate → plan → apply)

 

핵심 개념:

  • Terraform 리소스 이름 vs XO name_label 구분
  • CI/CD Variables를 통한 민감정보 관리
  • when: manual로 안전한 배포 프로세스(리소스 배포 승인 로직) 구현

 

다음 편에서는 이렇게 구성한 파이프라인을 실제로 GitLab에 push하고, VM을 자동으로 생성하는 과정을 다뤄보겠습니다!

 

이전 글 : [Terraform 기초 다시 시작하기 - Docker Provider 컨테이너 자동화

다음글 : GitLab CI/CD로 VM 자동 생성 실전 (작성 예정)

 

반응형