스터디(Study)/CI·CD Study

로컬 환경에서 Jenkins + Gogs + Kind(K8s) 기반 CI/CD 파이프라인 구축하기

Chann._.y 2025. 11. 1.
728x90
가시다님께서 진행하시는 ci/cd 스터디 3주차 주제인 jenkins와 argocd 실습 내용을 기반으로 작성하였다.
이번 글에서는 로컬 환경에서 CI/CD 전체 파이프라인을 직접 구축하는 과정을 단계별로 기록했다.

Kind(Kubernetes in Docker), Jenkins, Gogs(Git 서버), 그리고 DockerHub를 활용하며,
DevOps 파이프라인을 실제로 자동화하는 과정을 실습 중심으로 다룬다.

 


1. CI/CD 개념 정리

소프트웨어 개발 프로세스는 일반적으로 다음 단계를 자동화한다.

  1. 최신 코드 가져오기
  2. 단위 테스트 작성 및 실행
  3. 코드 개발
  4. 테스트 재실행
  5. 코드 푸시 및 병합
  6. 코드 병합 후 컴파일
  7. 통합 테스트
  8. 빌드된 아티팩트 배포
  9. E2E 테스트 실행 (예: Selenium)

이 과정을 Jenkins 파이프라인으로 자동화하면, 코드 변경 → 빌드 → 테스트 → 배포까지 전 과정을 자동으로 수행할 수 있다.

캡션: CI/CD 파이프라인은 코드 품질 향상과 배포 속도 개선을 동시에 달성한다.


2. Kind로 로컬 Kubernetes 클러스터 구성

macOS 예시

kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  apiServerAddress: "0.0.0.0"
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
- role: worker
EOF

클러스터 확인:

kind get nodes --name myk8s
kubens default
docker ps

삭제:

kind delete cluster --name myk8s

캡션: Kind는 Docker 네트워크 위에서 동작하는 경량 Kubernetes 클러스터로, 로컬 테스트에 적합하다.


3. Docker Compose로 Jenkins & Gogs 실행

작업 디렉토리 구성

mkdir cicd-labs
cd cicd-labs

docker-compose.yaml 작성:

services:
  jenkins:
    image: jenkins/jenkins
    ports:
      - "8080:8080"
    volumes:
      - ./jenkins_home:/var/jenkins_home
  gogs:
    image: gogs/gogs
    ports:
      - "3000:3000"
      - "10022:22"
    volumes:
      - ./gogs-data:/data

컨테이너 기동:

docker compose up -d

Jenkins 초기 비밀번호:

docker compose exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

접속 주소:

  • Jenkins: http://127.0.0.1:8080
  • Gogs: http://127.0.0.1:3000

캡션: Docker Compose를 사용하면 Jenkins와 Gogs 환경을 손쉽게 재현할 수 있다.


4. Jenkins 컨테이너에서 Docker CLI 연결하기

Jenkins가 호스트 Docker를 직접 제어하려면 Docker CLI를 설치하고 권한을 부여해야 한다.

docker compose exec --privileged -u root jenkins bash
apt-get update && apt install docker-ce-cli -y
groupadd -g 2000 -f docker
usermod -aG docker jenkins
exit
docker compose restart jenkins

확인:

docker compose exec jenkins docker info

캡션: Jenkins 내부에서 docker info가 정상 출력되면 설정 완료.


5. Gogs 설정 및 예제 Repository 생성

초기 설정

  1. 데이터베이스: SQLite3
  2. 관리자 계정: devops / qwe123
  3. Application URL: http://<로컬IP>:3000/

Personal Access Token 발급

Gogs > Settings > Applications > Generate Token

Repository 생성

  • dev-app (개발용)
  • ops-deploy (운영용)

예제 애플리케이션 작성

# server.py
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
from datetime import datetime
import socket
...

Dockerfile:

FROM python:3.12
COPY . /app
WORKDIR /app
CMD python3 server.py

버전 파일:

echo "0.0.1" > VERSION

커밋 및 푸시:

git add .
git commit -m "init dev-app"
git push

캡션: Gogs에서 커밋 내역을 확인하며 Jenkins와 연동 준비 완료.


6. Jenkins CI 파이프라인 구성

자격 증명 추가

  • gogs-crd: Gogs 계정 정보
  • dockerhub-crd: DockerHub Access Token

파이프라인 스크립트

pipeline {
  agent any
  environment {
    DOCKER_IMAGE = '<도커허브ID>/dev-app'
  }
  stages {
    stage('Checkout') {
      steps {
        git branch: 'main',
            url: 'http://:3000/devops/dev-app.git',
            credentialsId: 'gogs-crd'
      }
    }
    stage('Read VERSION') {
      steps {
        script {
          def version = readFile('VERSION').trim()
          env.DOCKER_TAG = version
        }
      }
    }
    stage('Build & Push') {
      steps {
        script {
          docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-crd') {
            def img = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
            img.push()
            img.push("latest")
          }
        }
      }
    }
  }
  post {
    success { echo "Build success!" }
    failure { echo "Build failed!" }
  }
}

캡션: Jenkins 파이프라인의 stage는 코드 흐름을 단계별로 정의하는 핵심 구성 요소이다.


7. Kubernetes에 배포하기

Deployment 작성:

DHUSER=<도커허브ID>
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: timeserver
spec:
  replicas: 2
  selector:
    matchLabels:
      app: timeserver
  template:
    metadata:
      labels:
        app: timeserver
    spec:
      containers:
      - name: timeserver
        image: docker.io/$DHUSER/dev-app:0.0.1
        ports:
        - containerPort: 80
EOF

Service 작성:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: timeserver
spec:
  type: NodePort
  selector:
    app: timeserver
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30000
EOF

테스트:

curl http://127.0.0.1:30000

캡션: kubectl get pods로 파드 상태를 확인하며, NodePort를 통해 로컬 접속을 테스트한다.


8. 버전 업데이트와 재배포

echo "0.0.2" > VERSION
git commit -am "Update 0.0.2"
git push
kubectl set image deployment timeserver timeserver=docker.io/$DHUSER/dev-app:0.0.2

캡션: Jenkins 파이프라인이 자동으로 새 버전 이미지를 빌드하고 배포한다.


9. 정리하며

이 과정은 단순한 도구 실습이 아니라 로컬에서 완전한 DevOps 환경을 직접 구축하는 경험이다.
실제 기업 환경에서도 이 구성은 프로토타이핑, 개발용 자동화 테스트, 교육용 CI/CD 환경 구축 등에 유용하다.

 

728x90

댓글