Published on

Jenkins 에이전트 오프라인 원인·복구 10가지

Authors

서버는 멀쩡한데 Jenkins 에이전트가 Offline으로 바뀌면 파이프라인은 즉시 멈춥니다. 더 난감한 건 원인이 네트워크/자격증명/리소스/런타임/플러그인 등으로 넓게 퍼져 있어, 감으로 접근하면 복구 시간이 길어진다는 점입니다.

이 글은 “에이전트가 왜 오프라인이 되었는지”를 증거(로그/상태/명령어) 로 좁혀가며, 재발 방지까지 연결하는 10가지 원인·복구 시나리오를 제공합니다. (Linux 기반 에이전트 기준이지만, Windows도 개념은 동일합니다.)

빠른 분류: 오프라인 유형부터 확인

Jenkins UI에서 노드(Node) 상세로 들어가면 보통 다음 중 하나입니다.

  • Temporarily offline: 사람이 수동으로 내렸거나(설명 메시지 존재), 유지보수/스케줄러가 내렸을 수 있음
  • Disconnected / Connection terminated: 연결은 시도했으나 끊김(네트워크/SSH/JNLP/프로세스 종료)
  • Launch failed: 에이전트 실행 자체 실패(경로/권한/자바/서비스)

먼저 컨트롤러 로그와 에이전트 측 로그를 확보합니다.

  • Controller: Manage Jenkins → System Log 또는 /var/log/jenkins/jenkins.log
  • Agent(SSH/JNLP): 에이전트 프로세스 표준 출력/서비스 로그

1) 네트워크 단절(라우팅/DNS/방화벽)로 연결 불가

증상

  • java.net.UnknownHostException, No route to host, Connection timed out
  • SSH 에이전트면 ssh: connect to host ... port 22: Connection timed out

복구

에이전트에서 컨트롤러로의 기본 연결성을 확인합니다.

# DNS 확인
getent hosts jenkins.example.internal

# TCP 포트 확인(HTTP/HTTPS)
# 컨트롤러가 8080이면 8080, 리버스프록시면 443
nc -vz jenkins.example.internal 443

# 라우팅/방화벽 확인
ip route
sudo iptables -S
sudo nft list ruleset | sed -n '1,120p'
  • 사내망/클라우드 보안그룹 변경 이력 확인
  • 컨트롤러를 프록시 뒤에 두었다면, 에이전트가 접근하는 URL이 내부에서 올바른지 점검

재발 방지

  • 에이전트→컨트롤러 방향의 헬스체크를 cron/systemd 타이머로 주기 실행
  • DNS 의존이 크면 내부 DNS 장애 대비로 고정 IP/프라이빗 DNS 이중화 고려

2) 컨트롤러 URL/리버스 프록시 설정 불일치(JNLP/WebSocket 포함)

증상

  • JNLP/WebSocket 에이전트가 연결 직후 끊김
  • 로그에 Invalid JNLP URL, 403, handshake failed

복구

Manage Jenkins → System → Jenkins URL이 실제 에이전트가 접근 가능한 URL인지 확인합니다.

  • 리버스 프록시(Nginx/ALB) 뒤라면 X-Forwarded-Proto, Host 헤더 처리 필요
  • WebSocket 에이전트 사용 시 프록시가 WebSocket 업그레이드를 허용해야 함

Nginx 예시(개념):

location / {
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  # WebSocket
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";

  proxy_pass http://jenkins:8080;
}

재발 방지

  • Jenkins URL 변경 시 에이전트 연결 방식(SSH/JNLP/WebSocket)별 회귀 테스트 체크리스트 운영

3) SSH 자격증명/키 권한 문제(SSH 에이전트)

증상

  • Permission denied (publickey)
  • Jenkins에서 “Authentication failed”

복구

에이전트 대상 서버에서 SSH 데몬/권한을 점검합니다.

# 개인키 권한(너무 열려 있으면 OpenSSH가 거부)
chmod 600 ~/.ssh/id_rsa
chmod 700 ~/.ssh

# authorized_keys 권한
chmod 600 ~/.ssh/authorized_keys

# 서버 측 로그(배포판마다 경로 상이)
sudo tail -n 200 /var/log/auth.log
# 또는
sudo journalctl -u ssh -n 200 --no-pager
  • Jenkins에 등록된 Credential이 올바른 키인지, passphrase가 필요한데 미등록인지 확인
  • 계정 잠김/만료(회사 정책)도 흔한 원인

재발 방지

  • 에이전트 전용 서비스 계정 + 키 로테이션 자동화
  • SSH 접근 정책 변경 시 Jenkins 노드 연결 테스트를 CI로 포함

4) JNLP 시크릿/토큰 불일치(노드 재생성/재등록 후)

증상

  • 노드를 삭제 후 다시 만들었거나, 에이전트 설정을 바꾼 뒤부터 오프라인
  • 로그에 Authorization failure, Bad credentials 유사 메시지

복구

JNLP 방식은 노드마다 secret이 바뀔 수 있습니다. 노드 설정 화면의 “Launch agent by connecting it to the controller”에서 최신 커맨드를 다시 복사해 실행합니다.

# 예시(실제 값은 UI에서 복사)
java -jar agent.jar \
  -url https://jenkins.example.internal/ \
  -secret YOUR_SECRET \
  -name "linux-agent-01" \
  -workDir "/var/jenkins"

재발 방지

  • 노드 재생성 시 에이전트 배포 스크립트가 secret을 자동 반영하도록(예: 구성관리 도구/시크릿 매니저)

5) 에이전트 Java 버전/옵션 불일치(업그레이드 후 흔함)

증상

  • 컨트롤러 업그레이드 이후부터 에이전트만 오프라인
  • UnsupportedClassVersionError (예: class file version 61.0)
  • TLS 관련 오류(구형 JRE)

복구

에이전트의 Java 버전을 확인하고, Jenkins 권장 버전으로 맞춥니다.

java -version
which java

# Debian/Ubuntu 예시
sudo apt-get update
sudo apt-get install -y temurin-17-jre
  • 컨트롤러/에이전트 간 TLS 협상 문제면 JRE 업데이트가 가장 빠른 해결책
  • 컨테이너 에이전트라면 베이스 이미지 태그를 고정하고 주기적 업데이트

재발 방지

  • Jenkins 업그레이드 전 “에이전트 런타임 요구사항”을 릴리즈 노트로 점검

6) 디스크 부족/워크디렉터리 손상으로 에이전트 프로세스 실패

증상

  • 빌드가 돌다가 갑자기 에이전트가 끊김
  • No space left on device, IOException, cannot create temp file

복구

에이전트에서 디스크/인오드/권한을 확인하고, 워크디렉터리를 정리합니다.

df -h
df -i

# Jenkins 작업 디렉터리 예시
du -sh /var/jenkins
sudo find /var/jenkins -maxdepth 3 -type d -name "workspace" -print

# 안전하게는 오래된 워크스페이스/캐시를 정책적으로 정리
  • Docker를 쓰면 /var/lib/docker가 원인인 경우가 많으니 함께 확인

재발 방지

  • 워크스페이스/캐시 TTL 정책
  • 디스크 임계치 모니터링 + 알림(70/85/95%)

7) 메모리/CPU 압박(OOMKilled, 과부하)로 에이전트 종료

증상

  • 에이전트가 “갑자기” 죽고 자동 재연결도 실패
  • 커널 로그에 OOM

복구

# OOM 흔적 확인
sudo dmesg -T | egrep -i "killed process|oom"

# 메모리/CPU 상태
free -h
uptime
ps aux --sort=-%mem | head
  • 컨테이너 에이전트면 리소스 limit 때문에 OOMKilled가 더 흔합니다.
  • 빌드 도구(Gradle/Node/Webpack)가 순간 메모리를 크게 먹는지도 확인

재발 방지

  • 동시 실행 executor 수를 줄이거나, 큰 작업은 전용 노드로 분리
  • 컨테이너 리소스 limit 상향 + JVM/빌드 툴 메모리 플래그 조정

8) systemd/서비스 관리 문제로 에이전트가 자동 재시작 루프

증상

  • 에이전트 서비스가 “떠 있는 듯” 보이지만 연결이 안정적이지 않음
  • Restart=always로 인해 실패-재시작 반복

복구

systemd 상태/로그로 원인을 먼저 확정합니다.

sudo systemctl status jenkins-agent --no-pager
sudo journalctl -u jenkins-agent -n 200 --no-pager

# 유닛 파일 확인
systemctl cat jenkins-agent
  • WorkingDirectory, User, Environment가 실제 파일/권한과 맞는지 확인
  • 자바 경로가 바뀌었는데 유닛 파일이 옛 경로를 참조하는 경우가 많습니다.

systemd 재시작 루프 진단은 아래 글의 체크리스트를 같이 보면 속도가 납니다.

재발 방지

  • 에이전트 유닛에 StartLimitIntervalSec, StartLimitBurst 설정
  • 실패 시 알림(로그 기반)

9) 시간 오차(NTP/Clock skew)로 TLS/토큰 검증 실패

증상

  • certificate not yet valid, certificate has expired가 간헐적으로 발생
  • 토큰 기반 인증이 만료로 처리됨

복구

date

# systemd-timesyncd 사용 시
timedatectl status
sudo timedatectl set-ntp true

# chrony 사용 시
chronyc tracking
chronyc sources -v
  • VM 스냅샷 복구 후 시간이 과거로 돌아가며 발생하는 케이스도 흔합니다.

재발 방지

  • NTP 강제 + 시간 오차 모니터링
  • 인증서 갱신 자동화(만료 전 알림)

10) 플러그인/에이전트 통신 모드 변경(SSH ↔ JNLP ↔ WebSocket)로 호환성 붕괴

증상

  • 플러그인 업데이트 직후 특정 노드만 오프라인
  • 예전에는 되던 런치 방식이 더 이상 안정적이지 않음

복구

  • 최근 변경(플러그인 업데이트, Jenkins 코어 업데이트, 런치 방식 변경)을 되짚고, 직전 정상 조합으로 롤백 또는 통신 모드 변경을 검토합니다.
  • 방화벽/프록시 제약이 큰 환경이라면 SSH가 더 안정적인 경우가 있고, 반대로 인바운드가 막힌 환경이라면 WebSocket 에이전트가 유리합니다.

에이전트 연결이 불안정할 때는 “네트워크 레벨 원인”을 같이 의심해야 합니다. 특히 클러스터 환경에서 네트워크가 꼬이면 증상이 비슷하게 나타납니다. 쿠버네티스 기반 에이전트를 쓴다면 아래 글도 참고할 만합니다.

재발 방지

  • 플러그인 업데이트는 스테이징 Jenkins에서 에이전트 연결 회귀 테스트 후 프로덕션 반영
  • 에이전트 런치 방식별 표준(권장) 구성을 문서화

운영자가 바로 쓰는 “오프라인 복구” 체크리스트

아래 순서로 보면 보통 10~20분 안에 범위를 좁힐 수 있습니다.

  1. UI에서 오프라인 사유 메시지 확인(수동 offline 여부)
  2. Controller 로그에서 해당 노드명으로 검색
  3. 에이전트 서버에서 nc -vz controller port로 네트워크 확인
  4. SSH면 /var/log/auth.log 또는 journalctl -u ssh
  5. JNLP면 secret 재발급/재복사 후 재실행
  6. java -version, 인증서/TLS 오류 확인
  7. df -h, df -i로 디스크/인오드 확인
  8. dmesg로 OOM 여부 확인
  9. timedatectl로 시간 동기화 확인
  10. 최근 변경(업데이트/프록시/보안정책) 롤백 가능성 검토

에이전트 실행 예시: systemd로 안정화하기

JNLP 에이전트를 systemd로 관리하면 재부팅/장애 후 자동 복구가 쉬워집니다.

유닛 파일 예시

# /etc/systemd/system/jenkins-agent.service
[Unit]
Description=Jenkins JNLP Agent
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=jenkins
WorkingDirectory=/var/jenkins
Environment="JAVA_HOME=/usr/lib/jvm/temurin-17-jre"
ExecStart=/usr/bin/java -jar /opt/jenkins/agent.jar \
  -url https://jenkins.example.internal/ \
  -secret YOUR_SECRET \
  -name linux-agent-01 \
  -workDir /var/jenkins
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

적용:

sudo systemctl daemon-reload
sudo systemctl enable --now jenkins-agent
sudo systemctl status jenkins-agent --no-pager

마무리: “원인”을 추측하지 말고 로그로 확정하기

Jenkins 에이전트 오프라인은 원인이 다양하지만, 실제 현장에서는 (1) 네트워크/프록시, (2) 자격증명/시크릿, (3) 런타임(Java)/리소스(디스크·메모리), (4) 서비스 관리(systemd) 네 축에서 대부분 결정됩니다.

한 번 오프라인이 발생했을 때, 위 10가지 항목을 “증거 기반”으로 체크하고 재발 방지(모니터링/표준화/업데이트 정책)까지 묶어두면, 다음 장애 때는 복구 시간이 체감될 정도로 줄어듭니다.