Trouble Shooting

Jenkins 서버 정전 후 복구 - 플러그인 버전 불일치 해결 가이드

Somaz 2026. 1. 23. 00:00
728x90
반응형

Overview

갑작스러운 서버 정전은 Jenkins 환경에 예상치 못한 문제를 일으킬 수 있다. 특히 정전 전에 개발자가 플러그인을 업데이트한 경우, 재시작 후 플러그인 버전 불일치로 인해 Jenkins가 정상적으로 작동하지 않을 수 있다.

 

이번 글에서는 서버 정전 후 Jenkins가 깨져서 Job이 보이지 않는 문제를 Jenkins 업그레이드를 통해 해결한 경험을 공유하겠다. macOS, Linux, Docker 컨테이너, Kubernetes 환경 등 다양한 플랫폼별 해결 방법을 다룬다.

 

 

 

 

 

 

 

 


 

 

 

문제 상황

 

 

발생한 문제

  1. 갑작스러운 서버 정전으로 Jenkins가 비정상 종료
  2. 정전 전 개발자가 플러그인을 업데이트했고, 재시작 과정에서 플러그인 버전이 상승
  3. Jenkins 재시작 후 UI가 깨지면서 Job 목록이 전혀 보이지 않음
  4. 플러그인 버전 불일치로 인한 호환성 문제 발생

 

 

증상

  • Jenkins 웹 UI 접속은 가능하지만 Job 리스트가 표시되지 않음
  • 플러그인 관리 페이지에서 경고 메시지 발생
  • 일부 플러그인이 로드되지 않거나 오류 발생

 

 

 

 

 

해결 방법

 

 

1. Jenkins 백업 (필수!)

 

문제 해결을 시도하기 전에 반드시 현재 상태를 백업해야 한다.

# Jenkins 전체 백업
tar -czf ~/jenkins-backup-$(date +%Y%m%d).tar.gz ~/.jenkins

# 또는 중요한 설정만 백업
cd ~/.jenkins
tar -czf ~/jenkins-config-backup.tar.gz \
  config.xml \
  jobs/ \
  credentials.xml \
  secrets/ \
  users/

 

 

 

2. Homebrew로 설치한 경우 (권장)

 

macOS에서 Homebrew로 Jenkins를 설치한 경우 다음 절차를 따른다.

# 1. Jenkins 중지
brew services stop jenkins-lts

# 2. Java 21 설치 (의존성)
brew install openjdk@21

# 3. Homebrew 업데이트
brew update

# 4. Jenkins 업그레이드
brew upgrade jenkins-lts

# 5. Jenkins 시작
brew services start jenkins-lts

# 6. 버전 확인
brew info jenkins-lts

 

 

간소화된 버전

# Jenkins 중지
brew services stop jenkins-lts

# Homebrew 업데이트
brew update

# Jenkins 업그레이드
brew upgrade jenkins-lts

# Jenkins 재시작
brew services start jenkins-lts

# 버전 확인
brew info jenkins-lts

 

 

 

3. WAR 파일로 직접 설치한 경우

 

WAR 파일을 직접 다운로드하여 실행하는 경우

# 현재 Jenkins 중지 (실행 중인 터미널에서 Ctrl+C)

# 기존 WAR 파일 백업
cd ~/jenkins  # 또는 jenkins.war가 있는 디렉토리
mv jenkins.war jenkins.war.backup

# 최신 LTS 버전 다운로드
wget https://updates.jenkins.io/download/war/2.528.3/jenkins.war

# 또는 curl 사용
curl -L https://updates.jenkins.io/download/war/2.528.3/jenkins.war -o jenkins.war

# Jenkins 재시작
java -jar jenkins.war --httpPort=8080

 

 

 

4. Installer(.pkg)로 설치한 경우

 

macOS Installer 패키지로 설치한 경우

# 최신 Jenkins LTS Installer 다운로드
curl -L https://www.jenkins.io/download/thank-you-downloading-osx-installer-stable/ -o jenkins-installer.pkg

# 설치 (기존 버전 위에 덮어씀)
sudo installer -pkg jenkins-installer.pkg -target /

# Jenkins 재시작
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist

 

 

5. Linux - 패키지 관리자로 설치한 경우

 

 

Ubuntu/Debian

# 1. 현재 Jenkins 백업
sudo tar -czf /backup/jenkins-backup-$(date +%Y%m%d).tar.gz /var/lib/jenkins

# 2. Jenkins 중지
sudo systemctl stop jenkins

# 3. APT 업데이트
sudo apt update

# 4. Jenkins 업그레이드
sudo apt upgrade jenkins -y

# 5. Jenkins 시작
sudo systemctl start jenkins

# 6. 상태 확인
sudo systemctl status jenkins

# 7. 버전 확인
jenkins --version

 

 

CentOS/RHEL

# 1. 현재 Jenkins 백업
sudo tar -czf /backup/jenkins-backup-$(date +%Y%m%d).tar.gz /var/lib/jenkins

# 2. Jenkins 중지
sudo systemctl stop jenkins

# 3. YUM 업데이트
sudo yum update

# 4. Jenkins 업그레이드
sudo yum upgrade jenkins -y

# 5. Jenkins 시작
sudo systemctl start jenkins

# 6. 상태 확인
sudo systemctl status jenkins

# 7. 버전 확인
rpm -qa | grep jenkins

 

 

6. Docker 컨테이너 환경

 

 

단일 Docker 컨테이너

# 1. 현재 컨테이너 상태 확인
docker ps -a | grep jenkins

# 2. Jenkins 데이터 백업 (볼륨 백업)
docker run --rm \
  -v jenkins_home:/source \
  -v $(pwd):/backup \
  alpine tar -czf /backup/jenkins-backup-$(date +%Y%m%d).tar.gz -C /source .

# 3. 현재 컨테이너 중지 및 제거
docker stop jenkins
docker rm jenkins

# 4. 최신 Jenkins 이미지 Pull
docker pull jenkins/jenkins:lts

# 5. 새 컨테이너로 재시작 (기존 볼륨 재사용)
docker run -d \
  --name jenkins \
  -p 8080:8080 -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts

# 6. 로그 확인
docker logs -f jenkins

 

 

Docker Compose 사용

 

`docker-compose.yml` 업데이트

version: '3.8'

services:
  jenkins:
    image: jenkins/jenkins:lts  # 또는 jenkins/jenkins:2.528.3
    container_name: jenkins
    privileged: true
    user: root
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - JAVA_OPTS=-Djenkins.install.runSetupWizard=false
    restart: unless-stopped

volumes:
  jenkins_home:
    driver: local

 

 

업그레이드 실행

# 1. Jenkins 데이터 백업
docker run --rm \
  -v jenkins_home:/source \
  -v $(pwd):/backup \
  alpine tar -czf /backup/jenkins-backup-$(date +%Y%m%d).tar.gz -C /source .

# 2. 현재 컨테이너 중지
docker-compose down

# 3. 최신 이미지 Pull
docker-compose pull

# 4. 새 버전으로 재시작
docker-compose up -d

# 5. 로그 확인
docker-compose logs -f jenkins

 

 

7. Kubernetes 환경

 

Helm Chart 사용

# 1. 현재 Jenkins 상태 확인
kubectl get pods -n jenkins
helm list -n jenkins

# 2. Jenkins PVC 백업
kubectl get pvc -n jenkins
JENKINS_POD=$(kubectl get pod -n jenkins -l app.kubernetes.io/component=jenkins-controller -o jsonpath='{.items[0].metadata.name}')

# PVC 데이터를 로컬로 백업
kubectl exec -n jenkins $JENKINS_POD -- tar czf /tmp/jenkins-backup.tar.gz -C /var/jenkins_home .
kubectl cp jenkins/$JENKINS_POD:/tmp/jenkins-backup.tar.gz ./jenkins-backup-$(date +%Y%m%d).tar.gz

# 3. Helm Repository 업데이트
helm repo update

# 4. 현재 values.yaml 백업
helm get values jenkins -n jenkins > jenkins-values-backup.yaml

# 5. Jenkins Chart 업그레이드
helm upgrade jenkins jenkins/jenkins \
  -n jenkins \
  -f jenkins-values-backup.yaml \
  --version 5.1.0  # 최신 Chart 버전 지정

# 6. Rollout 상태 확인
kubectl rollout status statefulset/jenkins -n jenkins

# 7. Pod 상태 확인
kubectl get pods -n jenkins
kubectl logs -f $JENKINS_POD -n jenkins

 

 

`values.yaml` 예시 (이미지 버전 업데이트)

controller:
  image:
    repository: jenkins/jenkins
    tag: "2.528.3-lts"  # 최신 LTS 버전으로 업데이트
  
  # 리소스 설정
  resources:
    requests:
      cpu: "500m"
      memory: "2Gi"
    limits:
      cpu: "2000m"
      memory: "4Gi"
  
  # 백업 설정
  backup:
    enabled: true
    schedule: "0 2 * * *"
  
  # JVM 옵션
  javaOpts: "-Xmx2048m -Xms512m"
  
persistence:
  enabled: true
  size: 20Gi
  storageClass: "gp3"  # 환경에 맞게 수정

 

 

Kubernetes Manifest 사용

 

1. Deployment 업데이트

# jenkins-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      containers:
      - name: jenkins
        image: jenkins/jenkins:2.528.3-lts  # 최신 버전으로 업데이트
        ports:
        - containerPort: 8080
        - containerPort: 50000
        volumeMounts:
        - name: jenkins-home
          mountPath: /var/jenkins_home
        resources:
          requests:
            memory: "2Gi"
            cpu: "500m"
          limits:
            memory: "4Gi"
            cpu: "2000m"
      volumes:
      - name: jenkins-home
        persistentVolumeClaim:
          claimName: jenkins-pvc

 

 

2. 업그레이드 실행

# 1. 현재 PVC 백업
JENKINS_POD=$(kubectl get pod -n jenkins -l app=jenkins -o jsonpath='{.items[0].metadata.name}')
kubectl exec -n jenkins $JENKINS_POD -- tar czf /tmp/jenkins-backup.tar.gz -C /var/jenkins_home .
kubectl cp jenkins/$JENKINS_POD:/tmp/jenkins-backup.tar.gz ./jenkins-backup-$(date +%Y%m%d).tar.gz

# 2. Deployment 업데이트 적용
kubectl apply -f jenkins-deployment.yaml

# 3. Rollout 상태 모니터링
kubectl rollout status deployment/jenkins -n jenkins

# 4. 새 Pod 확인
kubectl get pods -n jenkins

# 5. 로그 확인
NEW_POD=$(kubectl get pod -n jenkins -l app=jenkins -o jsonpath='{.items[0].metadata.name}')
kubectl logs -f $NEW_POD -n jenkins

 

StatefulSet으로 운영하는 경우

# 1. 현재 StatefulSet 백업
kubectl get statefulset jenkins -n jenkins -o yaml > jenkins-statefulset-backup.yaml

# 2. PVC 백업
JENKINS_POD=$(kubectl get pod -n jenkins -l app=jenkins -o jsonpath='{.items[0].metadata.name}')
kubectl exec -n jenkins $JENKINS_POD -- tar czf /tmp/jenkins-backup.tar.gz -C /var/jenkins_home .
kubectl cp jenkins/$JENKINS_POD:/tmp/jenkins-backup.tar.gz ./jenkins-backup-$(date +%Y%m%d).tar.gz

# 3. StatefulSet 이미지 업데이트
kubectl set image statefulset/jenkins jenkins=jenkins/jenkins:2.528.3-lts -n jenkins

# 또는 직접 편집
kubectl edit statefulset jenkins -n jenkins

# 4. Rollout 상태 확인
kubectl rollout status statefulset/jenkins -n jenkins

# 5. Pod 재시작 확인
kubectl get pods -n jenkins -w

 

 

 

 

 

 

 


 

 

 

 

업그레이드 후 확인 사항

 

 

1. Jenkins 접속 확인

브라우저에서 Jenkins URL에 접속하여 정상 작동을 확인한다.

 

 

각 환경별 기본 URL

  • macOS/Linux: `http://localhost:8080`
  • Docker: `http://localhost:8080`
  • Kubernetes: Service/Ingress에 설정된 URL

 

 

2. Job 목록 확인

  • Dashboard에서 모든 Job이 정상적으로 표시되는지 확인
  • 각 Job의 설정이 유지되었는지 점검

 

 

3. 플러그인 업데이트

Jenkins가 정상적으로 작동하면 모든 플러그인을 최신 버전으로 업데이트한다.

 

플러그인 업데이트 절차

  1. Jenkins 관리 → Plugin Manager 접속
  2. "Updates" 탭에서 업데이트 가능한 플러그인 확인
  3. "Select All" 선택 후 "Download now and install after restart" 클릭
  4. 재시작 체크박스 선택하여 자동 재시작

 

 

 

4. 최종 검증

 

 

macOS/Linux

# Jenkins 로그 확인
# Homebrew 설치
tail -f /opt/homebrew/var/log/jenkins-lts/jenkins.log

# Linux systemd
sudo journalctl -u jenkins -f

# Linux 전통 방식
tail -f /var/log/jenkins/jenkins.log

 

 

Docker

# 컨테이너 로그 확인
docker logs -f jenkins

# Docker Compose
docker-compose logs -f jenkins

 

 

 

Kubernetes

# Pod 로그 확인
kubectl logs -f <jenkins-pod-name> -n jenkins

# 실시간 이벤트 모니터링
kubectl get events -n jenkins --watch

# Pod 상태 확인
kubectl describe pod <jenkins-pod-name> -n jenkins

 

 

 

 

문제 해결 팁

 

 

플러그인 버전 불일치 방지

  1. 정기적인 Jenkins 및 플러그인 업데이트: 최신 버전을 유지하여 호환성 문제 예방
  2. 업데이트 전 백업: 모든 업데이트 전에 백업 수행
  3. 점진적 업데이트: 한 번에 모든 플러그인을 업데이트하지 말고 중요도에 따라 단계적으로 진행
  4. 테스트 환경 활용: 가능하면 프로덕션 환경 적용 전 테스트 환경에서 먼저 검증

 

 

서버 정전 대비

 

인프라 레벨

  1. UPS(무정전 전원 공급 장치) 사용: 갑작스러운 정전으로부터 보호
  2. 클라우드 환경 활용: AWS/GCP/Azure 등의 고가용성 인프라 사용
  3. Multi-AZ 배포: Kubernetes 환경에서 여러 가용 영역에 분산 배치

 

 

애플리케이션 레벨

 

 

정기적인 백업 자동화

# Cron job으로 일일 백업 설정 (Linux)
0 2 * * * tar -czf ~/jenkins-backups/jenkins-$(date +\%Y\%m\%d).tar.gz /var/lib/jenkins

 

 

Kubernetes CronJob을 이용한 백업

apiVersion: batch/v1
kind: CronJob
metadata:
  name: jenkins-backup
  namespace: jenkins
spec:
  schedule: "0 2 * * *"  # 매일 새벽 2시
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: alpine
            command:
            - /bin/sh
            - -c
            - |
              tar czf /backup/jenkins-$(date +%Y%m%d).tar.gz -C /var/jenkins_home .
              # S3나 다른 스토리지로 업로드하는 로직 추가 가능
            volumeMounts:
            - name: jenkins-home
              mountPath: /var/jenkins_home
            - name: backup
              mountPath: /backup
          restartPolicy: OnFailure
          volumes:
          - name: jenkins-home
            persistentVolumeClaim:
              claimName: jenkins-pvc
          - name: backup
            persistentVolumeClaim:
              claimName: jenkins-backup-pvc

 

 

Jenkins Configuration as Code (JCasC) 사용

# jenkins.yaml
jenkins:
  systemMessage: "Jenkins configured automatically by JCasC"
  numExecutors: 5
  mode: NORMAL
  securityRealm:
    local:
      allowsSignup: false
  authorizationStrategy:
    loggedInUsersCanDoAnything:
      allowAnonymousRead: false
  
  crumbIssuer:
    standard:
      excludeClientIPFromCrumb: false

unclassified:
  location:
    url: "https://jenkins.yourdomain.com"
    adminAddress: "admin@yourdomain.com"

 

 

 

 

 

컨테이너 환경 특화 팁

 

 

Docker

  1. Named Volume 사용: 데이터 영속성 보장
  2. Health Check 설정: 컨테이너 상태 모니터링
 
services:
  jenkins:
    image: jenkins/jenkins:lts
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8080/login || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 60s

 

 

 

Kubernetes

  1. PersistentVolume 백업: 정기적인 스냅샷 생성
  2. ReadinessProbe/LivenessProbe 설정: 자동 복구 기능
  3. StorageClass 선택: 백업/스냅샷 기능을 지원하는 스토리지 사용 (AWS EBS, GCP PD 등)
 
livenessProbe:
  httpGet:
    path: /login
    port: 8080
  initialDelaySeconds: 90
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 5

readinessProbe:
  httpGet:
    path: /login
    port: 8080
  initialDelaySeconds: 60
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3

 

 

 

 

 

 


 

 

 

 

 

마무리

 

Jenkins는 DevOps 파이프라인의 핵심 도구이지만, 갑작스러운 장애 상황에서 취약할 수 있다. 특히 서버 정전과 같은 예기치 않은 상황에서는 플러그인 버전 불일치로 인한 심각한 문제가 발생할 수 있다.

 

 

이번 트러블슈팅에서 핵심은 Jenkins 자체를 최신 버전으로 업그레이드하여 플러그인 호환성을 확보하는 것이었다. 업그레이드 후 모든 플러그인을 최신 버전으로 업데이트하고 재부팅하니 정상적으로 작동했다.

 

 

교훈

  • 항상 백업을 우선시하세요
  • Jenkins와 플러그인을 최신 상태로 유지하세요
  • 정전과 같은 장애 상황에 대비한 예방책을 마련하세요
  • 문제 발생 시 단계적으로 접근하세요 (백업 → 업그레이드 → 플러그인 업데이트)

 

 

플랫폼별 권장사항

  • macOS: Homebrew를 통한 관리로 의존성 자동 해결
  • Linux: 패키지 관리자를 활용한 안정적인 업데이트
  • Docker: 이미지 버전 관리와 볼륨 백업 전략 수립
  • Kubernetes: Helm Chart 사용과 자동화된 백업 CronJob 구성

 

 

Jenkins 환경을 안정적으로 운영하기 위해서는 정기적인 유지보수와 백업 전략이 필수적이다. 특히 컨테이너 오케스트레이션 환경에서는 선언적 구성 관리(IaC)와 자동화된 백업 시스템이 더욱 중요하다. 이번 경험이 비슷한 문제를 겪는 분들께 도움이 되기를 바란다.

 

 

 

 

 

 

 

 


Reference

 

 

728x90
반응형