1. 폐쇄망에서 GitLab 및 Jenkins 설치 및 연동
-
가이드 환경
- OS: Rocky Linux 9.6
- K8s Version: 1.30.14
- Container Runtime: containerd (
ctr)
-
전제 조건
- Kubernetes 클러스터가 정상 동작 중이어야 합니다 (
kubectl get nodes-> Ready). - Harbor가 설치되어 있어야 합니다.
- 스토리지 클래스(
local-path)가 구성되어 있어야 합니다. - 이 가이드는 마스터 노드의
~/gitlab,~/jenkins경로에 준비되어 있다고 가정하고 시작합니다. - 설치 파일 위치
- Kubernetes 클러스터가 정상 동작 중이어야 합니다 (
🚀 Phase 1: 이미지 로드 (전체 노드)
Harbor에 이미지를 업로드합니다.
[실행 위치: Master 1]
먼저 upload_images_to_harbor_v2.sh 설정 부분을 현재 환경에 맞게 변경합니다.
HARBOR_REGISTRY: Harbor domainHARBOR_PROJECT: Harbor ProjectHARBOR_USER: IDHARBOR_PASSWORD: PasswordUSE_PLAIN_HTTP: HTTP 접속 여부
cd ~/gitlab-18.7/images
sudo bash upload_images_to_harbor_v2.sh
cd ~/jenkins-2.528.3/images
sudo bash upload_images_to_harbor_v2.sh
🚀 Phase 2: 데이터 영속성 구성 (PV 설정)
local-path 스토리지 클래스를 사용하더라도, 프로덕션 데이터를 안전하게 보관하기 위해 호스트 경로를 고정(HostPath)하여
PV를 생성하는 것을 권장합니다.
[실행 위치: Master 1]
1. 호스트 디렉토리 생성 (모든 워커 노드)
데이터가 저장될 실제 폴더를 모든 워커 노드에 생성합니다.
환경에 맞춰 경로를 수정해도 됩니다.
# (각 워커 노드에서 실행하거나, Ansible 등으로 일괄 실행)
sudo mkdir -p /data/jenkins_home
sudo mkdir -p /data/gitlab_data
sudo mkdir -p /data/gitlab_pg
sudo mkdir -p /data/gitlab_redis
sudo chmod -R 777 /data
sudo mkdir -p /data/gitlab_data/minio
sudo chmod -R 777 /data/gitlab_data/minio
2. PV 생성 (Master 노드)
위에서 경로를 수정했다면, pv-volume.yaml 파일에서도 동일한 경로로 sepc.hostPath.path 값을 수정해야 합니다.
🚀 Phase 3: Jenkins 설치 (Master-1)
우리가 빌드한 Custom Image (플러그인 포함)를 사용하여 설치합니다.
[실행 위치: K8s-Master-Node]
1. 네임스페이스 생성
2. Jenkins Helm 배포
deploy-jenkins.sh 파일 위에 있는 REGISTRY_URL 등의 변수를 환경에 맞춰 수정 후 실행합니다.
3. Jenkins 접속 정보 확인
# 1. Pod 상태 확인 (Running이 될 때까지 대기)
watch kubectl get pods -n jenkins
# 2. 초기 관리자 계정 확인
# 초기 ID는 admin
# PW 확인
kubectl get secret -n jenkins jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode
echo ""
🚀 Phase 4: GitLab 설치 (Master-1)
GitLab은 리소스를 많이 사용하므로, 불필요한 기능(NGINX, Prometheus 등)을 끄고 핵심 기능만 설치합니다. 특히 Envoy Gateway 전환을 고려하여 Ingress 설정만 남깁니다.
[실행 위치: K8s-Master-Node]
1. 설정 파일 확인 (install-gitlab-values.yaml)
사용하는 환경에 맞춰 domain , image , ingress , nginx-ingress 부분을 수정해야 합니다.
global:
edition: ce
hosts:
domain: devops.internal # 내부 도메인에 맞게 변경
https: false
image:
registry: 1.1.1.213:30002 # Harbor domain 맞춰 변경
repository: library # Harbor Project 맞춰서 변경
pullPolicy: IfNotPresent
# [핵심] Ingress 설정
# 1. Gateway API를 사용할 때
ingress:
enabled: false
configureCertmanager: false
tls:
enabled: false # TLS 비활성화 (HTTP 접속)
# 2. 이미 설치된 ingress nginx를 사용할 때
# ingress:
# enabled: true # Ingress 객체(라우팅 규칙) 생성: YES
# configureCertmanager: false
# class: "none" # NGINX가 채가면 안되므로 none 설정 (나중에 Envoy가 처리)
# tls:
# enabled: false # TLS 비활성화 (HTTP 접속)
# 3. gitlab의 ingress nginx를 사용할 떄
# ingress:
# enabled: true # Ingress 활성화
# configureCertmanager: false # 인증서 관리자 끔 (HTTP 사용)
# class: gitlab-nginx # 내장 NGINX 사용
# tls:
# enabled: false # TLS 비활성화 (HTTP 접속)
# [핵심] NGINX 컨트롤러 비활성화 (이미지는 받았지만 설치는 안 함)
# 1,2. Gateway API를 사용할 때 혹은 이미 설치된 ingress nginx를 사용할 때
nginx-ingress:
enabled: false
# 3. gitlab의 ingress nginx를 사용할 때
# nginx-ingress:
# enabled: true
# controller:
# ingressClassResource:
# # [핵심] IngressClass 이름 변경 (충돌 방지)
# name: gitlab-nginx
# # 컨트롤러 값도 유니크하게 변경
# controllerValue: "k8s.io/gitlab-nginx"
# image:
# registry: 1.1.1.213:30002 # Harbor domain
# repository: library/ingress-nginx-controller # Harbor에 올라간 이미지
# tag: "v1.11.8"
# digest: ""
# service:
# type: NodePort
# nodePorts:
# http: 30080
# https: 30443
# ssh: 30022
...
2. GitLab Helm 배포
install-gitlab.sh 파일 위에 있는 설정 변수를 환경에 맞게 정의한 후 실행합니다.
오류로 인한 재배포 시
오류로 인한 재배포가 필요하다면 먼저 아래 명령어로 비밀번호를 확보합니다.
혹여나 이미 비밀번호를 날렸다면, 볼륨으로 사용한 물리적 위치(가이드에선 지정한 워커 노드의 /data/gitlab_pg 폴더)에서
삭제 후 재생성 해야 합니다.
# 비밀번호 추출 (복사해두세요!)
kubectl get secret -n gitlab gitlab-postgresql-password -o jsonpath="{.data.postgresql-password}" | base64 -d
재생성 시, DB의 Password가 다시 무작위로 구성됩니다.
이때 PV에 있는 비밀번호와 맞지 새로 생성된 비밀번호가 달라 migration job 이 정상 동작하지 못할 때가 있습니다.
이때 아래 방법으로 비밀번호를 강제 동기화 시켜주세요.
# 1. DB 파드 이름 확인
kubectl get po -n gitlab -l app=postgresql
# 2. 파드 내부 쉘 접속 (이름이 gitlab-postgresql-0 이라고 가정)
kubectl exec -it -n gitlab gitlab-postgresql-0 -- bash
3. GitLab 접속 정보 확인
GitLab이 완전히 구동되는 데에는 약 5~10분이 소요됩니다.
# 1. 상태 모니터링
watch kubectl get pods -n gitlab
# 초기 ID는 root
# 2. 초기 root 비밀번호 확인
kubectl get secret gitlab-gitlab-initial-root-password \
-n gitlab -ojsonpath='{.data.password}' | base64 --decode ; echo
🚀 Phase 5: 네트워크 및 PC 접속 설정
로드밸런서나 Gateway가 아직 구성되지 않은 상태에서 웹 접속을 확인하기 위해, K8s 서비스의 포트를 임시로 포워딩하거나 NodePort를 확인합니다.
1. GitLab 서비스 노출 (임시 NodePort)
GitLab Webservice를 외부에서 접속하기 위해 NodePort로 변경합니다.
# gitlab-webservice-default 서비스 수정
kubectl patch svc gitlab-webservice-default -n gitlab -p '{"spec": {"type": "NodePort"}}'
# 할당된 포트 확인 (30000번대 포트 확인)
kubectl get svc -n gitlab gitlab-webservice-default
2. 사용자 PC Hosts 설정
사용자 PC(Windows/Mac)의 hosts 파일에 도메인을 등록합니다.
# 예시: 워커노드 IP와 NodePort 사용 시
# <Worker-Node-IP> gitlab.devops.internal
10.10.10.73 gitlab.devops.internal
이제 브라우저에서 http://gitlab.devops.internal:<NodePort> 로 접속하여 root 계정으로 로그인합니다.
🚀 Phase 6: Jenkins <-> GitLab 연동
이제 두 시스템을 연결하여 CI 파이프라인을 구성합니다.
1. GitLab: Access Token 발급
- GitLab 접속 -> 우측 상단 프로필 아이콘 -> Preferences.
- 좌측 메뉴 Personal Access Tokens.
- Add new token:
- Name:
jenkins-integration - Scopes:
api(체크) - Create personal access token 클릭 -> 토큰 값 복사.
- Name:
2. Jenkins: Credential 등록
- Jenkins 접속 (
http://<NodeIP>:30000). - Manage Jenkins -> Credentials -> System -> Global credentials (unrestricted).
- Add Credentials:
- Kind:
GitLab API token - Scope:
Global - API token: (복사한 GitLab 토큰 붙여넣기)
- ID:
gitlab-token-id - Description: GitLab Connection Token
- Create.
- Kind:
3. Jenkins: 시스템 설정
- Manage Jenkins -> System.
- 스크롤을 내려 GitLab 섹션 이동.
- Connection Name:
cmp-gitlab(파이프라인에서 사용할 이름). - GitLab host URL:
중요: Jenkins 파드 내부에서 GitLab으로 통신해야 하므로 K8s 내부 도메인을 사용합니다.
http://gitlab-webservice-default.gitlab.svc.cluster.local:8181
- Credentials:
GitLab Connection Token선택. - Test Connection ->
Success확인 후 Save.
🚀 Phase 7: 파이프라인 테스트 (검증)
실제 코드가 커밋되었을 때 Jenkins가 빌드를 수행하는지 확인합니다.
1. Jenkins Job 생성
- New Item -> 이름:
test-pipeline-> Pipeline 선택. - Build Triggers:
Build when a change is pushed to GitLab체크.- Advanced ->
Secret token을 생성하고 복사합니다.
- Advanced ->
-
Pipeline Script: 아래
image:경로는 실제 Harbor 경로로 변경해야 합니다.pipeline { agent { kubernetes { // yaml 병합을 통해 명시적으로 로컬 이미지를 사용하도록 지정 yaml """ apiVersion: v1 kind: Pod metadata: labels: app: builder spec: containers: # --------------------------------------------------------- # 1. 작업용 도구 (Golden Image) - 우리가 만든 올인원 이미지 사용 # --------------------------------------------------------- - name: shell # [중요] busybox 대신 툴이 다 설치된 우리 이미지를 지정 (레지스트리 주소 포함) image: '1.1.1.213:30002/library/cmp-jenkins-full:2.528.3' # 컨테이너가 죽지 않고 계속 살아있도록 유지 command: ['/bin/sh', '-c', 'sleep 86400'] tty: true volumeMounts: - mountPath: "/home/jenkins/agent" name: "workspace-volume" readOnly: false # --------------------------------------------------------- # 2. Jenkins 에이전트 (필수 통신용) # --------------------------------------------------------- - name: jnlp # Docker Hub 차단을 위해 로컬 레지스트리 명시 image: '1.1.1.213:30002/library/inbound-agent:latest' volumeMounts: - mountPath: "/home/jenkins/agent" name: "workspace-volume" readOnly: false """ } } stages { stage('Tool Verification') { steps { // 'shell' 컨테이너(Golden Image) 내부에서 명령어 실행 container('shell') { script { echo "🎉 1. OS 확인" sh 'cat /etc/os-release' echo "🎉 2. OpenTofu 버전 확인" sh 'tofu --version' echo "🎉 3. K8s 도구 (Kubectl & Helm) 확인" sh 'kubectl version --client' sh 'helm version' echo "🎉 4. Provider 번들링 확인" sh 'ls -al /usr/local/share/tofu-providers' } } } } } } -
Save
2. GitLab 설정 변경
- GitLab의 우측 상단의 Profile 아이콘 -> Admin 클릭
- LNB에서 Settings -> Network
- Outbound requests -> 아래 항목 체크
Allow requests to the local network from webhooks and integrationsAllow requests to the local network from system hooks
- Save
3. Webhook 등록 (GitLab)
-
Jenkins Job -> Configuration 화면의 GitLab webhook URL을 복사합니다.
- 예:
http://1.1.1.213:30000/project/test-pipeline - Floating IP로 되어있다면 위와 같이 project 앞부분을 내부 IP로 수정해야 합니다.
- 예:
-
GitLab 프로젝트 -> Project Settings -> LNB의 Webhooks -> Add new webhook
- 아래 값 설정 후, Webhook 추가
- URL: 위에서 수정한 내부 주소 입력.
- Secret token: Jenkins에서 생성한 Secret token.
- Trigger: Push events.
- Add webhook.
- Test -> Push events
HTTP 200이 뜨면 연동 성공입니다.- Jenkins 대시보드에서 빌드가 수행되는지 확인하세요.
4. Jenkins Kubernetes Cloud 설정
Webhook을 통해 들어온 요청을 처리할 K8s 에이전트(Pod) 연결 정보를 설정합니다. 이 설정이 선행되어야 Jenkins가 K8s 클러스터 내부에 에이전트를 생성할 수 있습니다.
경로: Manage Jenkins > Clouds > New cloud
-
Kubernetes 기본 설정
- Name:
Kubernetes - Kubernetes URL:
https://kubernetes.default(내부 API 통신용) - Kubernetes Namespace:
jenkins - Disable HTTPS certificate check: ✅ 체크 (Enable) ->
- Test Connection:
Credentials항목에 있는Test Connection확인 - Jenkins URL:
http://jenkins.jenkins.svc.cluster.local:8080 - Jenkins tunnel:
jenkins-agent.jenkins.svc.cluster.local:50000 - 주의:
kubectl get svc -n jenkins명령어로 50000번 포트를 가진 서비스의 정확한 이름 (예:jenkins또는cmp-jenkins)을 확인하여 입력하세요.
- Name:
-
Pod Templates 설정 (Global Default)
- Name:
kubernetes - Namespace:
jenkins - Labels:
kubernetes(파이프라인이 호출할 라벨) - Usage:
Use this node as much as possible선택
- Name:
5. Git 설치 및 소스 코드 Push (Trigger)
모든 설정이 완료되었으므로, 실제 코드를 GitLab에 푸시하여 Jenkins 빌드를 트리거합니다.
-
Git 설치
만약 Git이 설치되어 있지 않다면 폐쇄망용 git rpm을 사용해 git을 설치합니다.
-
로컬 설정
/etc/hosts파일에 GitLab 서버의 IP와 도메인을 등록합니다. -
프로젝트 Clone
-
테스트 파일 작성 및 Push
Clone 받은 폴더 안에 파일을 하나 작성합니다. 작성 후 GitLab으로 푸시합니다.
-
결과 확인
git push성공 직후 Jenkins 대시보드에서 자동으로 빌드가 시작(Pending->Running->Success)되는지 확인합니다.