본문 바로가기

카테고리 없음

CI/CD Tools

1. CI/CD Tools 종류

1-1. GitHub Actions

  • 장점: GitHub과 완벽 통합, 간단한 설정 (.yml), Docker build/push 쉬움
  • 단점: GitHub에 코드가 있어야 유리, 병렬 워크플로우는 요금제 제한
  • 도커 친화도: ★★★★★

💡 추천 상황: GitHub에서 코드 관리 중이고 Docker 이미지 빌드/배포도 함께 하고 싶을 때

1-2. GitLab CI/CD

  • 장점: GitLab과 완벽 통합, 강력한 권한 제어, 무료로도 강력한 기능 제공
  • 단점: GitLab EE는 비쌈, 러닝커브 있음
  • 도커 친화도: ★★★★★

💡 추천 상황: 자체 GitLab 운영 중인 기업, 보안/권한 제어가 중요한 환경

 

GitHub Actions와 GitLab CI/CD 차이 (실제 기업에서 GitLab을 많이 사용하는 이유)

더보기
더보기

GitHub Actions

운영 주체 : Microsoft

CI/CD 기능 : GitHub Actions 내장 (최근 빠르게 발전)

DevOps 통합성 : Actions + Copilot 등 최근 통합형 기능 강화

권한/권리 모델 : 권한 관리 단순 (협업에 최적)

사용자 인터페이스 : 직관적이고 깔끔

커뮤니티/생태계 : 오픈소스 커뮤니티 중심, 가장 활성화됨

GitLab CI/CD

운영 주체 : GitLab Inc.

CI/CD 기능 : GitLab CI/CD 내장 (초기부터 강력함)

DevOps 통합성 : 올인원 DevOps 플랫폼(코드→빌드→배포→모니터링)

권한/권리 모델 : 프로젝트·그룹 단위로 세밀한 권한 설정 가능

사용자 인터페이스 : 기능은 많지만 UI는 다소 복잡

커뮤니티/생태계 : 자체 호스팅에 강점(사내망 자체 서버에 GitLab 자체 설치 가능, 인터넷 없이 운영 가능)

  • 그에 반해 GitHub는 ...
  • Enterprise를 사용하면 자체 서버에 설치 가능(But 제약 많음)
  • 인터넷 없이 Actions 사용 불가능

자체 호스팅이란? (Github 입장)

  • GitHub.com 없이, 모든 GitHub 플랫폼 기능을 직접 사내에 설치
    • 저장소
    • PR 관리
    • Actions 서버
    • Runner Queue (자체 관리)
    • 등등
  • 인터넷 없이도 완전 독립 운영 가능
  • 보통 보안상 사내망에서 GitHub을 완전히 자체 구축해야 할 때 사용
  • GitHub Enterprise Server 라이선스가 필요
  • 설치, 유지보수, 업그레이드도 전부 직접 해야 함
  • 📌 즉: GitHub.com을 흉내 낸 자체 GitHub 클론을 회사 내부에서 운영하는 것  (Actions 서버도 직접 돌림, Runners도 내부적으로 관리)

요약

기준 GitHub GitLab
SaaS 중심
자체 서버 설치 제한적 🔥 강력
CI/CD GitHub Actions 🔥 GitLab CI/CD 내장
DevOps 통합성 낮음 🔥 전체 사이클 통합
보안/망분리 환경 제한적 🔥 최적
커스터마이징 제한적 가능 (오픈소스 기반)

1-3. Jenkins

  • 장점: 오래된 레거시 시스템에도 적합, 강력한 플러그인 생태계
  • 단점: 관리가 힘듦 (서버 유지보수, 플러그인 충돌 등), 느릴 수 있음
  • 도커 친화도: ★★★☆☆ (Docker로 돌릴 수는 있지만, 친화적이지는 않음)
    • 도커 친화도가 낮은 이유
      • 젠킨스는 서버에 설치해서 돌리는 설치형 프로그램이지만, 요즘은 모든걸 Docker로 띄우기 때문에 Jenkins도 Docker로 띄워서 사용함. ex) docker run -d -p 8080:8080 jenkins/jenkins:lts
      • 하지만 jenkins 컨테이너에서 또 다른 Docker 명령어를 실행하려고 할 때(docker build -t my-app .) 컨테이너 안에서 Docker를 사용할 수 없기 때문에 문제가 발생함.
      • 보통 DinD 또는 Docker socket 공유 방법을 사용해 해결
        • DinD : Jenkins 컨테이너 안에 Docker도 설치해서, 그 안에서 Docker를 실행
        • Docker socket 공유: Jenkins 컨테이너 실행할 때, 호스트 머신의 Docker 엔진을 공유
      • 다른 툴은 보통 Docker환경에서 안전하게 Build/Deploy되도록 만들어짐
      • 그게 반해 젠킨스는 Docker 자체도 설정 필요, 실행 권한도 설정 필요 등등 고려 사항 많음

💡 추천 상황: 사내 CI/CD 시스템이 구축되어 있고 Jenkins 경험자가 많은 경우

1-4. Argo CD / Argo Workflows (쿠버네티스 중심 기업)

  • 장점: GitOps 방식 CI/CD, 쿠버네티스 완벽 연동, MSA 배포에 유리
  • 단점: 초심자에겐 러닝커브 있음
  • 도커 친화도: ★★★★★ (K8s 기반이므로 Docker 전제)

💡 추천 상황: 클러스터 단위 GitOps CD 구축하고 싶을 때

1-5. 요즘 기업들이 많이 쓰는 Tool은?

GitHub 기반 스타트업/중소기업 GitHub Actions
사내 GitLab 쓰는 대기업/기관 GitLab CI/CD
Kubernetes-heavy 기업 Argo CD / Tekton
레거시 유지 중인 기업 Jenkins
빠른 빌드가 중요한 팀 CircleCI

 

2. Git commit 트리거 방식

2-1. GitHub Actions & GitLab CI/CD

GitHub Actions나 GitLab CI/CD는 그 자체가 클라우드 서비스 안에 포함된 CI/CD 시스템이기 때문에

  • GitHub에 Push를 하면 GitHub Actions도 같은 GitHub 서버 안에서 실행됨
  • GitHub 서버는 Push 이벤트를 실시간으로 감지해서 즉시 Actions workflow를 실행

이 때 Actions workflow(테스트, 빌드, 배포 등 CI/CD 스크립트)를 실행하며 내 서버에 접속보안 문제 발생

2-1-1. 보안 문제 해결 방안

1. 역방향 터널링 (Reverse SSH Tunnel)

  • 내 서버가 GitHub 서버에 먼저 연결을 맺고, 그 연결을 통해 GitHub Actions가 내 서버에 접속하는 방식
  • 내 서버에서 **공용 중계 서버(또는 배포 게이트웨이)**로 ssh -R 터널을 연결
  • GitHub Actions는 그 중계 서버를 통해 간접적으로 내 서버에 접근
  • ex. 
  • # GitHub Actions Script
  • #- name: Deploy run: ssh -p 2222 user@relay-server.com "ssh localhost 'your deploy command'"
  • # 내 서버에서 미리 실행 
  • # ssh -R 2222:localhost:22 ubuntu@relay-server.com
  • 장점 : 서버가 외부에 열려있지 않아도 배포 가능
  • 단점 : 복잡하고 보안 설정 주의 필요 (키 인증, IP 제한 등)

2. GitHub Actions Runner를 내 서버에 설치

  • GitHub Actions는 기본적으로 클라우드(**github-hosted runner)**에서 실행되지만,
  • 내 서버에도 "self-hosted runner"를 설치할 수 있음 (GitHub 자체가 아닌, runner만 설치하면 됨)
    • GitHub Push를 감지하는 흐름 (polling + long polling : 계속 대기 상태의 연결)
      1. 내 서버의 Runner가 GitHub 서버 API에 지속적으로 연결됨 (HTTPS 요청을 통해)
      2. GitHub 저장소에 Push 발생
      3. GitHub 서버가 “이 저장소에 등록된 Runner가 있나?” 확인
      4. Runner가 주기적으로 GitHub에 job pending 여부를 물어봄
      5. 새로운 작업이 생기면 GitHub이 Runner에 작업 정보를 응답
      6. Runner는 그걸 받아서 내 서버에서 직접 실행함
      일종의 Pull 기반 이벤트 감지 방식
    • Jenkins의 SCM Polling보다 훨씬 빠르고 효율적(거의 실시간 수준).

⇒ Push 이벤트가 발생했을 때, GitHub은 내 서버에서 Actions를 실행

📌 즉, GitHub에서 내 서버로 SSH 접속하지 않고도 내 서버가 직접 Actions Script를 실행

설정 절차

  1. GitHub 저장소 → Settings → Actions → Runners → Add new self-hosted runner
  2. 안내에 따라 내 서버에 실행 파일 다운로드 & 등록
  3. actions-runner 프로세스가 내 서버에서 계속 대기
  4. Push 이벤트가 발생하면 GitHub이 내 서버에 명령을 내려줌 (방화벽 문제 없음)

장점 : 보안상 매우 유리 (외부에서 접속 불필요)

  • GitHub 서버가 내 서버에 직접 접속하지 않음
  • 내 서버는 인바운드 포트가 전혀 열릴 필요 없음
  • Runner가 GitHub에 HTTPS로만 아웃바운드 연결을 유지하므로 방화벽 문제 없음

3. CI와 CD Tool 분리

  • CI는 GitHub Actions를 사용하여 테스트를 진행
  • CD는 ArgoCd등을 이용하여 배포를 진행

2-2. Jenkins

2-2-1. 폴링(Polling, 주기적 확인)방식

  • Jenkins가 일정 시간 간격(ex. 5분, 10분)으로 Git 저장소 서버를 직접 확인해서 변경사항이 있으면 빌드를 시작하는 방법
  • 설정 방식 : Jenkins Job 설정에서 "Poll SCM" 옵션을 켜고 주기(크론 형태) 지정
  • 장점 : 간단히 설정 가능
  • 단점 : 실시간성이 떨어지고 불필요한 요청이 많아질 수 있음

2-2-2. Webhook 방식 (Push 이벤트로 바로 호출)

  • GitHub/GitLab 등에서 Webhook을 만들어 Github push가 일어나면 Webhook에 등록된 Jenkins 서버 URL로 POST 요청을 보내는 방식
  • Jenkins에 플러그인 설치 후 Webhook 이벤트 수신 시 빌드가 트리거됨
  • 대표 플러그인: GitHub Plugin, GitLab Plugin
  • 장점 : 거의 실시간으로 빌드 시작 가능
  • 단점 : Jenkins 서버가 외부에서 접속 가능해야 함 (방화벽, 보안, 복잡한 네트워크 문제)

2-2-3. Jenkins 요약

서버 방화벽·보안 이슈 때문에 외부에서 내부로 접근이 안 되는 경우

🚫 이런 상황에서는 Webhook 사용 X

  • Webhook은 GitHub/GitLab이 Jenkins에게 "야, 푸시 들어왔어!" 하고 HTTP 요청을 보내는 구조
  • 하지만 방화벽 때문에 Jenkins 서버가 외부에서 접근 불가능하면,  

→ GitHub/GitLab이 요청을 보낼 수 없기 때문에

✅ 이럴 땐 Jenkins에서는 SCM Polling 방식 사용

SCM Polling이란?

  • Jenkins가 일정 주기마다 Git 저장소 서버"새 커밋 생겼니?" 하고 확인하는 방식

예를 들어:

# cron
H/5 * * * *

→ 5분마다 SCM 저장소를 체크해서 변경 사항 있으면 빌드 트리거

📌 즉,

GitHub나 GitLab이 Jenkins를 "부르는" 방식이 아니라,

Jenkins가 GitHub에 "바뀐 거 있어?" 하고 직접 묻는 방식

 

2-3. 요약

항목 GitHub Actions / GitLab CI Jenkins

트리거 방식 Git Push 이벤트가 기본 트리거 Polling 또는 Webhook
설정 복잡성 매우 간단 (repo 내 .yml 설정으로 자동 연결) Polling은 간단, Webhook은 설정 필요
네트워크 요구사항 클라우드 서비스라 별도 서버 필요 없음 Jenkins 서버가 외부 접근 가능해야 함
실시간성 기본 실시간 Webhook 사용 시 빠름, Polling은 느림

 

2-4. GitHub Actions와 Jenkins의 Polling 방식 차이

항목 GitHub Actions Self-Hosted Runner Jenkins SCM Polling

Polling 대상 GitHub Actions API (GitHub 자체) Git 서버 (예: GitHub, GitLab 등)
Polling 주체 Runner 프로세스 Jenkins 서버 (cron 주기 등)
동작 방식 GitHub API와 장기 연결 유지(long polling or event queue) 주기적으로 Git 서버에 직접 HTTP 요청
리소스 소비 이벤트 수신 대기 상태 (Idle 대기, CPU 거의 안 씀) 주기적 Git fetch → 디스크/CPU 많이 씀
실행 지연 거의 실시간 (수 초 이내) 보통 수 분 단위 (예: 1분마다)
네트워크 부하 GitHub와만 통신 (자원 효율적) 많은 Git 서버들이 자주 pull → 부하 큼

2-4-1. GitHub Actions Runner 방식 (더 빠름)

GitHub Actions의 Runner는 단순한 polling이 아니라 GitHub Actions 서버의 이벤트 큐를 장기 대기(long polling) 합니다.

  1. Runner가 GitHub Actions API에 연결
  2. 연결을 유지하면서 "새로운 작업이 있는지" 기다림 (idle wait, CPU 거의 안 씀)
  3. Push 이벤트 발생 시 GitHub 서버가 Runner에 즉시 작업을 전달
  4. Runner는 바로 Job을 실행

장점 :

  • GitHub 서버에서 직접 이벤트 발생 시 알려주므로 지연이 거의 없음
  • 실제로는 polling보다는 event-driven 구조에 가까움
  • CPU, 네트워크 사용량이 훨씬 적음

2-4-2. Jenkins의 Poll SCM 방식

Jenkins에서 Poll SCM을 켜면 다음과 같이 작동합니다:

  1. Jenkins가 git fetch 요청을 주기적으로 보냅니다 (예: * * * * → 1분마다)
  2. 이전 커밋과 비교해서 새로운 커밋이 있으면 Job을 실행
  3. 이때 git fetch는 실제 리모트 Git 서버와 네트워크 통신 + 디스크 접근을 필요로 함

단점 :

  • Git 서버에 지속적인 부담 (모든 Jenkins 인스턴스가 매분마다 접속)
  • 실제 변경이 없어도 계속 요청함
  • Job이 즉시 실행되지 않고, polling 주기에 따라 최대 수분 지연 가능

2-4-3. 요약

  • GitHub Actions Runner = "이메일 알림이 오면 바로 알려주는 푸시 알림 시스템"
  • Jenkins Poll SCM = "매 1분마다 이메일을 확인하러 서버에 가는 사람"

 

3. 사용 후보

현재 내 서버는 외부에서 접근이 불가능하기 때문에 사용할 수 있는 방법은 아래 두 가지이다.

두 방식 모두 내 서버에서 GitHub 서버로 요청을 보내고 있어, 현재 상황에서 사용할 수 있다.

GitHub Actions의 self-Hosted Runner 방식

내 서버의 Self-Hosted Runner가 GitHub API에 접근해 Pub-Sub방식으로 연결을 맺고 이벤트 발생 시 이벤트를 받아오는 방식

Jenkins의 polling 방식

Jenkins가 Github Server에 주기적으로 POST 요청을 보내 변경 사항을 감지하는 방식

 

선택 : GitHub Actions의 self-Hosted Runner 방식

이유 : Jenkins의 polling 방식에 비해 Docker 친화적이면서 부하가 적음. 또한 주기적으로 변경사항을 체크하는 Jenkins에 비해 실시간성이 보장됨

 

4. 사용 방법

4-1. GitHub Repository 설정에서 runner 생성 후, 본인의 Host에 등록

  • runner 생성하면 아래 있는 명령어 따라 적으면 됨.

4-2. .github/workflows/deploy.yml파일을 만들어 CI/CD 스크립트 작성

  • Docker 컨텍스트 내에서 (Dockerfile위치한 곳) docker build 완료
  • docker compose로 서버 실행