- Published on
Jenkins 에이전트 Offline 원인과 해결 체크리스트
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버는 멀쩡한데 Jenkins 노드가 갑자기 Offline 으로 바뀌면, 파이프라인은 큐에 쌓이고 배포는 멈춥니다. 문제는 원인이 매우 다양하다는 점입니다. 네트워크 단절처럼 단순한 경우도 있지만, 에이전트 런타임(Java/SSH), 인증키/시크릿, 컨테이너 리소스, 워크스페이스 권한, WebSocket/인바운드 포트 차단 등 여러 축에서 발생합니다.
이 글은 “에이전트가 왜 Offline 이 되었는지”를 빠르게 좁히는 진단 순서와, 환경별(SSH, Inbound, Docker, Kubernetes) 실전 해결책을 체크리스트 형태로 제공합니다.
Offline 상태를 먼저 분류하기
Jenkins UI에서 노드 상세로 들어가면 보통 다음 중 하나의 힌트가 남습니다.
java.io.EOFException,ChannelClosedException: 연결이 끊김(네트워크/프록시/타임아웃)Authentication failed: 키/토큰/시크릿 문제Cannot contact ...: DNS, 라우팅, 방화벽, 포트 차단Agent is running but cannot be reached: 역방향 연결(inbound) 관련Disk full,No space left on device: 디스크/워크스페이스OutOfMemoryError,Killed: 메모리 부족(OOMKill)
여기서 중요한 건 “에이전트 프로세스가 죽었는지”와 “살아 있는데 Jenkins가 못 보는지”를 먼저 가르는 것입니다.
1단계: Jenkins 컨트롤러 로그부터 확인
컨트롤러에서 에이전트 관련 로그는 가장 빠른 출발점입니다.
- 시스템 로그(서비스)
Manage Jenkins→System Log- 노드 상세 화면의 로그
리눅스에서 서비스 로그 예시:
# systemd 환경
sudo journalctl -u jenkins -n 300 --no-pager
# 컨테이너라면
docker logs --tail 300 jenkins
로그에서 다음 키워드를 찾습니다.
handshake failedSSLHandshakeExceptionConnection timed outNo route to hostinvalid agent secretRejected: ...(Remoting/JNLP 버전 불일치나 보안 정책)
2단계: 에이전트 실행 방식(SSH vs Inbound) 확인
Jenkins 에이전트는 크게 두 방식이 많습니다.
- SSH 에이전트: 컨트롤러가 에이전트로 SSH 접속해서
java -jar agent.jar를 실행 - Inbound 에이전트(JNLP/WebSocket): 에이전트가 컨트롤러로 “역방향” 연결
Offline 원인과 해결이 완전히 달라지므로, 노드 설정에서 Launch method 를 먼저 확인하세요.
3단계: 네트워크/방화벽/프록시 점검(가장 흔함)
SSH 방식일 때
컨트롤러에서 에이전트로 다음을 확인합니다.
# 컨트롤러에서 실행
ssh -vvv user@agent-host "uname -a"
주요 실패 패턴:
Connection timed out: 보안그룹/방화벽/라우팅Permission denied (publickey): 키/authorized_keys/권한no matching host key type found: 구형 SSH 서버/클라이언트 알고리즘 불일치
Inbound(JNLP) 방식일 때
Inbound는 에이전트가 컨트롤러로 나가야 하므로 에이전트 측에서 점검합니다.
# 에이전트에서 실행
curl -vk https://jenkins.example.com/login
# DNS 확인
getent hosts jenkins.example.com
특히 사내 프록시가 있으면 HTTPS_PROXY 환경변수로 인해 JNLP/WebSocket이 프록시를 타며 끊기는 경우가 많습니다. 이때는 에이전트 실행 시 프록시 예외를 명시하거나, 해당 호스트를 NO_PROXY 에 추가하세요.
export NO_PROXY="jenkins.example.com,10.0.0.0/8,127.0.0.1,localhost"
Kubernetes/EKS 환경이라면 네트워크 플러그인 이슈로 노드가 간헐적으로 외부 통신을 못 하는 경우도 있습니다. 이 유형은 Pod가 Running 인데도 통신이 깨지며 에이전트가 Offline 으로 보일 수 있습니다. 비슷한 네트워크 계열 트러블슈팅은 EKS Pod NotReady(NetworkPlugin cni) 10분 해결 글의 점검 흐름도 참고할 만합니다.
4단계: Remoting(Jenkins agent.jar) 버전 및 Java 호환성
에이전트는 Jenkins Remoting 프로토콜을 사용합니다. 컨트롤러 업그레이드 후 에이전트가 Offline 이 되는 대표 원인은 다음입니다.
- 에이전트가 너무 오래된
agent.jar를 사용 - 에이전트 Java 버전이 Jenkins 요구사항과 불일치
- TLS/인증서 체인 문제
해결: 에이전트 jar 갱신
일반적으로 Jenkins는 최신 agent.jar 다운로드 URL을 제공합니다.
# 에이전트에서 실행 (예시)
curl -fsSL -o agent.jar https://jenkins.example.com/jnlpJars/agent.jar
java -jar agent.jar -version
해결: Java 버전 정렬
Jenkins LTS는 시점에 따라 Java 최소 버전 요구사항이 바뀝니다. 컨트롤러를 Java 17 기반으로 올렸는데 에이전트가 Java 8/11에 묶여 있으면 런타임 에러 또는 핸드셰이크 실패가 발생할 수 있습니다.
java -version
권장 접근:
- 컨트롤러/에이전트 모두 Jenkins 권장 Java 버전으로 정렬
- 컨테이너 에이전트라면 베이스 이미지에서 Java 런타임을 명시적으로 고정
5단계: 인증/시크릿/키 문제(특히 Inbound)
Inbound 에이전트는 보통 secret 과 agent name 조합으로 인증합니다. 다음 상황에서 자주 깨집니다.
- 노드를 삭제 후 다시 만들었는데 예전 secret을 계속 사용
- Kubernetes Secret이 롤링 중 잘못 주입
- 환경변수/파일 마운트 경로가 바뀜
Inbound 실행 예시(시크릿 기반)
java -jar agent.jar \
-url https://jenkins.example.com/ \
-secret "$JENKINS_AGENT_SECRET" \
-name "linux-agent-01" \
-workDir "/home/jenkins"
체크 포인트:
- 노드 설정 화면의
Secret과 실제 값이 일치하는가 - 에이전트 이름이 정확히 일치하는가(대소문자 포함)
workDir에 쓰기 권한이 있는가
6단계: 디스크/워크스페이스/권한 문제
에이전트가 연결은 되지만 빌드 시작 직후 Offline 으로 떨어지거나, 반복 재접속을 하면 디스크/권한 문제가 흔합니다.
디스크 확인
df -h
du -sh /var/lib/jenkins /home/jenkins 2>/dev/null || true
워크스페이스 권한 확인
# 에이전트에서
id
ls -ld /home/jenkins
mkdir -p /home/jenkins/test && rm -rf /home/jenkins/test
해결 팁:
- 워크스페이스를 ephemeral 하게 쓰는 컨테이너 에이전트면, 볼륨 용량 제한을 늘리거나 캐시 정책을 조정
- 장기 운영 노드면
workspace cleanup전략(빌드 후 정리, 오래된 작업 삭제) 수립
7단계: 리소스 부족(OOMKill/CPU Throttling)과 에이전트 프로세스 종료
에이전트가 Offline 으로 보이는 본질이 “프로세스가 죽었다”인 경우가 많습니다. 특히 Kubernetes에서는 OOMKill이 조용히 발생하기도 합니다.
Kubernetes에서 확인
kubectl get pod -n ci
kubectl describe pod -n ci jenkins-agent-xxxx
kubectl logs -n ci jenkins-agent-xxxx --previous
Last State: Terminated 와 Reason: OOMKilled 가 보이면 메모리 리밋을 올리거나, 빌드 병렬도를 낮추거나, Gradle/Node 등 빌드 툴 메모리 옵션을 조정해야 합니다.
리소스가 부족해 Pending 에 걸려 아예 에이전트가 뜨지 않는 경우도 있는데, 이때는 스케줄링 이벤트를 보면 빠르게 원인을 찾을 수 있습니다. 관련 흐름은 EKS Pod Pending(Insufficient cpu) 원인과 해결 도 참고하세요.
8단계: Docker-in-Docker, 소켓 권한, 컨테이너 런타임 이슈
컨테이너 에이전트에서 Docker 빌드를 하면 다음으로 Offline 처럼 보이는 장애가 생깁니다.
docker명령이 hang 또는 권한 에러로 빌드가 멈춤- 빌드 시간이 길어져 에이전트가 타임아웃/재시작
/var/run/docker.sock권한 문제
체크:
# 에이전트 컨테이너 내부
docker version
ls -l /var/run/docker.sock
id
해결:
- 가능하면 Docker-in-Docker 대신 Kaniko/BuildKit 등으로 전환
- 소켓 마운트 시 사용자/그룹 권한 정렬
- 빌드 타임아웃을 Jenkins Job 레벨에서 명시
9단계: WebSocket 모드와 L7 프록시/로드밸런서 호환성
최근 Jenkins는 인바운드 에이전트를 WebSocket으로 붙이는 구성이 많습니다. 이때 L7 프록시(Nginx, ALB, 사내 WAF)가 WebSocket 업그레이드를 제대로 처리하지 못하면 연결이 불안정해져 Offline 이 됩니다.
증상:
- 처음엔 붙었다가 몇 분 후 끊김
Unexpected EOF혹은Read timed out
점검:
- 프록시에서 WebSocket
Upgrade헤더 전달 여부 - 타임아웃(Idle timeout)이 너무 짧지 않은지
Nginx/리다이렉트/프록시 계열 문제는 원인 패턴이 반복되는 편입니다. 프록시 환경에서 인증/리다이렉트가 꼬일 때의 사고방식은 Nginx 뒤 OAuth 콜백 302 무한리다이렉트 원인 글도 같이 보면 도움이 됩니다.
10단계: 재현 가능한 “표준 복구 절차” 만들기
장애가 한 번 해결돼도 재발하면 운영 비용이 커집니다. 팀에서 다음을 표준화하면 Offline 대응 시간이 확 줄어듭니다.
1) 에이전트 헬스체크 스크립트
#!/usr/bin/env bash
set -euo pipefail
echo "[1] java"
java -version
echo "[2] disk"
df -h
echo "[3] jenkins reachability"
curl -fsS https://jenkins.example.com/login >/dev/null
echo "OK"
2) 에이전트 실행 파라미터를 코드로 관리
- systemd unit 파일
- Kubernetes manifest(Deployment/StatefulSet)
- Helm values
핵심은 agent.jar 다운로드, secret 주입, workDir, 프록시 예외, 리소스 요청/제한을 모두 선언적으로 관리하는 것입니다.
3) Jenkins 노드 설정의 불변성 유지
- 노드 이름 규칙 고정
- 노드 삭제/재생성 시 secret 교체가 반드시 필요하다는 운영 규칙 문서화
빠른 결론: 가장 많이 맞는 원인 Top 5
- 네트워크/방화벽/프록시로 컨트롤러와 에이전트 간 연결이 끊김
- 컨트롤러 업그레이드 후
agent.jar또는 Java 버전 불일치 - Inbound secret 불일치(노드 재생성, Secret 주입 오류)
- 디스크 부족 또는 워크스페이스 권한 문제
- Kubernetes OOMKill/리소스 부족으로 에이전트 프로세스가 종료
Offline 은 “증상”이고, 실제 원인은 연결·인증·런타임·리소스·프록시 중 하나로 귀결되는 경우가 대부분입니다. 위 순서대로 좁혀가면, 불필요한 재시작이나 감에 의존한 설정 변경 없이도 원인을 빠르게 특정할 수 있습니다.