본문으로 건너뛰기

Jenkins Dev 파이프라인

develop 브랜치 푸시 시 Jenkins가 자동으로 빌드하고 K8s dev namespace에 배포합니다.

Jenkins 접속

항목
URL사내 Jenkins 서버 (VPN 필요)
InfoLineage
Job 목록infolineage-platform-api, infolineage-platform-worker, infolineage-platform-frontend
Credentialsharbor (Harbor 레지스트리 로그인)

Jenkinsfile 위치

infra/jenkins/
├── Jenkinsfile.api
├── Jenkinsfile.worker
└── Jenkinsfile.frontend

각 Job의 Pipeline 설정에서 SCM → 해당 Jenkinsfile 경로를 지정합니다.

podTemplate 패턴

모든 Jenkinsfile은 Kubernetes podTemplate을 사용합니다. 빌드 Pod에 컨테이너를 여러 개 묶어 단계별로 실행합니다.

podTemplate(
label: label,
containers: [
containerTemplate(name: 'java', image: 'eclipse-temurin:25-jre', ...),
containerTemplate(name: 'docker', image: 'docker:20.10', privileged: true, ...),
containerTemplate(name: 'kubectl', image: 'lachlanevenson/k8s-kubectl', ...),
],
volumes: [
hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock'),
]
)
컨테이너역할이미지
javaGradle 빌드eclipse-temurin:25-jre (API), eclipse-temurin:25 (Worker)
docker이미지 빌드 & Harbor 푸시docker:20.10
kubectlK8s 배포lachlanevenson/k8s-kubectl

API Job은 nodeSelector: jenkins.kubernetes.io/dedicated=true를 추가로 지정합니다.

파이프라인 단계

1단계: Git Pull

stage('Git Pull') {
checkout scm
}

2단계: Check Changed Paths

git diff HEAD~1 HEAD로 변경된 파일 목록을 확인합니다.

SKIP_BUILD 조건

JobSKIP_BUILD=true (건너뛰기)
APIbackend/infolineage-apibackend/infolineage-common 변경 없음
Workerbackend/infolineage-workerbackend/infolineage-common 변경 없음
Frontendfrontend/ 변경 없음

SKIP_BUILD=true이면 Gradle Build와 Docker Build를 건너뜁니다. K8s Deploy는 항상 실행됩니다.

3단계: Gradle Build (API / Worker)

./gradlew :infolineage-api:bootJar \
-x test \
--build-cache \
-Dorg.gradle.jvmargs="--enable-preview -Xmx1g"

--build-cache 옵션으로 캐시를 활용해 증분 빌드를 수행합니다. Frontend는 Docker 멀티스테이지 빌드로 처리하므로 별도 Gradle 단계가 없습니다.

4단계: Docker Build & Push

docker login scr.softcamp.co.kr -u $HARBOR_USR --password-stdin

# API / Worker
docker build -f backend/<module>/Dockerfile -t <IMAGE> backend/
# Frontend
docker build -f frontend/Dockerfile \
--build-arg VITE_USE_MOCKS=false \
--build-arg VITE_API_BASE_URL=/platform/api \
--build-arg VITE_AUTH_DISABLED=false \
--build-arg VITE_SHIELD_ID_BASE_URL=https://devlogin.softcamp.co.kr \
--build-arg VITE_CLIENT_NAME=InfoLineage \
-t <IMAGE> frontend/

docker push <IMAGE>
docker rmi <IMAGE> || true

이미지 태그는 항상 :latest를 사용합니다.

5단계: K8s Deploy

# API / Worker
kubectl apply -f infra/k8s/dev/configmap.yaml -n dev
kubectl apply -f infra/k8s/dev/secret.yaml -n dev
kubectl apply -f infra/k8s/dev/<module>-service.yaml -n dev
kubectl apply -f infra/k8s/dev/<module>-deployment.yaml -n dev
kubectl rollout restart deployment/infolineage-platform-<module> -n dev
kubectl rollout status deployment/infolineage-platform-<module> -n dev --timeout=120s

특정 브랜치 선택 빌드

Jenkins Job 설정 → Branch Specifier를 수정하여 특정 브랜치를 대상으로 빌드합니다.

*/develop          # 기본값
*/feature/api-* # feature 브랜치 패턴

수동 빌드 시 Build with Parameters → Branch 입력으로 원하는 브랜치를 지정할 수 있습니다.

트러블슈팅

containerCap 초과로 Pod 생성 실패

Jenkins Kubernetes 플러그인 설정에서 containerCap 값이 낮으면 Pod 생성이 실패합니다.

# 증상
ERROR: Error allocating a new node ... containerCap exceeded

해결: Jenkins 관리 → Clouds → Kubernetes → Container Cap 값 상향 (기본 10 → 50 이상).

이전 빌드 Pod가 Pending/Running으로 남아 있는 경우

# 정리
kubectl get pods -n jenkins | grep infolineage
kubectl delete pod <stuck-pod-name> -n jenkins

git diff HEAD~1 HEAD 실패 (첫 커밋)

최초 커밋이거나 shallow clone인 경우 HEAD~1을 참조할 수 없어 SKIP_BUILD 판단이 실패합니다. Jenkinsfile은 || git diff --name-only HEAD로 폴백합니다.