Published on

Jenkins 에이전트 오프라인 - JNLP/SSH 7분 복구

Authors

서버는 멀쩡한데 Jenkins 빌드만 갑자기 멈추고, 노드 화면에는 offline 이 떠 있는 상황은 CI 운영에서 가장 흔한 장애 중 하나입니다. 특히 JNLP(WebSocket 포함) 기반 에이전트나 SSH 기반 에이전트는 끊기는 지점이 다르고, 진단 포인트도 다릅니다.

이 글은 7분 안에 다음을 끝내는 것을 목표로 합니다.

  • 오프라인 원인을 JNLP vs SSH 로 빠르게 분기
  • Jenkins 컨트롤러 로그와 에이전트 로그에서 딱 봐야 할 키워드 확인
  • 네트워크, 인증, 프로세스, 리소스 문제를 명령어로 즉시 검증
  • 재발 방지를 위한 systemd, 재연결 옵션, 타임아웃 설정 정리

장애 원인 추적 방식은 시스템 서비스 관점에서도 유사합니다. 에이전트가 자동 재시작을 반복하거나, 재시작은 되는데 계속 오프라인이면 아래 글의 접근법도 같이 참고하면 좋습니다.


0분~1분: 노드 타입부터 확인(JNLP vs SSH)

Jenkins UI에서 Manage JenkinsNodes → 해당 노드 → Configure 를 열어 다음을 확인합니다.

  • Launch method 가 Launch agent by connecting it to the controller 이면 JNLP(인바운드)
  • Launch method 가 Launch agents via SSH 이면 SSH(아웃바운드)

이 분기만 제대로 해도 로그/네트워크 확인 방향이 절반은 정리됩니다.


1분~2분: Jenkins 컨트롤러에서 즉시 보는 로그 포인트

컨트롤러에서 에이전트 연결 실패는 보통 아래 중 하나로 수렴합니다.

컨트롤러 로그에서 찾는 키워드

  • JNLP 계열
    • Connection was broken
    • Handshake error
    • Unknown client name
    • Authorization failure
    • WebSocket 관련 오류
  • SSH 계열
    • Auth fail
    • publickey
    • Connection timed out
    • No route to host

컨트롤러가 systemd 로 떠 있다면 빠르게 다음처럼 확인합니다.

sudo journalctl -u jenkins -n 200 --no-pager

컨테이너/쿠버네티스에서 운영 중이면 다음처럼 봅니다.

kubectl logs -n jenkins deploy/jenkins -c jenkins --tail=200

쿠버네티스 네트워크 이슈(예: 포트포워딩 hang, 세션 끊김)가 겹치면 진단이 꼬일 수 있습니다. 운영 환경이 EKS 이고 디버깅을 위해 kubectl port-forward 를 자주 쓴다면 아래 글도 함께 체크하세요.


2분~4분: JNLP 에이전트 3단 진단(프로세스, 토큰, 네트워크)

JNLP 인바운드 에이전트는 보통 에이전트 머신에서 agent.jar 가 컨트롤러로 접속합니다. 문제는 대부분 아래 셋 중 하나입니다.

  1. 에이전트 프로세스가 죽었거나 멈춤
  2. 시크릿(토큰) 불일치
  3. 컨트롤러까지 네트워크 경로/프록시/TLS 문제

1) 에이전트 프로세스 확인

에이전트 머신에서 자바 프로세스가 살아있는지 확인합니다.

ps aux | grep -E "agent\.jar|remoting" | grep -v grep

systemd 로 관리한다면 상태부터 확인합니다.

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

로그에서 다음이 보이면 거의 네트워크/인증 쪽입니다.

  • Connecting to 이후 재시도 반복
  • Failed to connect to 또는 handshake 관련 메시지

2) JNLP 시크릿(Secret) 불일치 점검

노드 설정 화면에서 Secret 이 바뀌었는데 에이전트 시작 스크립트가 예전 값을 들고 있으면 계속 오프라인입니다.

에이전트 시작 커맨드 예시는 보통 다음 형태입니다. 본문에 부등호가 들어가지 않도록 예시는 전부 백틱으로 처리합니다.

java -jar agent.jar \
  -url https://jenkins.example.com/ \
  -secret YOUR_SECRET \
  -name "agent-01" \
  -workDir "/var/lib/jenkins"
  • 노드 이름(-name)이 Jenkins UI의 노드 이름과 정확히 일치하는지
  • -secret 이 현재 UI 에 표시되는 값과 일치하는지
  • -workDir 권한 문제가 없는지

3) 네트워크와 TLS 확인

가장 빠른 검증은 curl 로 컨트롤러 접근과 인증서 체인을 확인하는 것입니다.

curl -vk https://jenkins.example.com/login 2>&1 | tail -n 30
  • DNS 가 틀리면 Could not resolve host
  • 방화벽/라우팅이면 Connection timed out
  • TLS 체인 문제면 SSL certificate problem

컨트롤러가 WebSocket 기반 JNLP 를 쓰는 경우, 중간 프록시가 WebSocket 업그레이드를 막으면 연결이 반복 실패합니다. 이때는 프록시(Nginx, ALB 등) 설정에서 WebSocket 헤더가 통과되는지 확인해야 합니다.


4분~5분: SSH 에이전트 3단 진단(키, 호스트키, 셸/권한)

SSH 방식은 컨트롤러가 에이전트로 접속해 java 를 실행하는 구조입니다. 따라서 컨트롤러에서 에이전트로의 네트워크/인증이 핵심입니다.

1) 컨트롤러에서 직접 SSH 접속 테스트

Jenkins 가 사용하는 계정과 동일하게 접속이 되는지 확인합니다.

ssh -vvv jenkins@agent-01.example.com

여기서 많이 나오는 실패 유형은 다음입니다.

  • Permission denied (publickey)
  • Host key verification failed
  • Connection timed out

2) 호스트키 변경으로 인한 차단

에이전트가 재설치되거나 IP 가 바뀌면 known_hosts 충돌이 납니다.

ssh-keygen -R agent-01.example.com
ssh-keyscan -H agent-01.example.com >> ~/.ssh/known_hosts

Jenkins 프로세스 사용자(예: jenkins)의 홈 디렉터리 기준 known_hosts 인지 꼭 확인하세요.

3) 원격에서 java 실행/권한 문제

SSH 는 붙는데 Jenkins 가 원격에서 java 를 못 찾으면 에이전트가 안 뜹니다.

에이전트 머신에서 다음을 확인합니다.

which java
java -version

또한 Jenkins 가 사용할 작업 디렉터리에 쓰기 권한이 있어야 합니다.

id
mkdir -p /var/lib/jenkins-agent && touch /var/lib/jenkins-agent/.perm_test

5분~6분: 흔한 원인 TOP 6와 즉시 조치

1) 에이전트 디스크 꽉 참

워크스페이스, 도커 레이어, 캐시로 디스크가 꽉 차면 에이전트가 죽거나 작업을 못 합니다.

df -h
sudo du -sh /var/lib/jenkins* 2>/dev/null

2) 시간 동기화 문제(NTP)

TLS, 토큰 만료, 서명 검증에 영향을 줍니다.

timedatectl

3) 컨트롤러 리버스 프록시의 헤더/업그레이드 설정 문제

특히 WebSocket JNLP 는 프록시 설정 한 줄 때문에 끊깁니다. Nginx 를 쓴다면 리다이렉트 루프나 업스트림 설정 이슈도 같이 확인하세요.

4) 에이전트 JVM 옵션 과도, OOM

sudo dmesg -T | tail -n 50

Out of memoryKilled process 가 보이면 JVM 힙을 줄이거나 머신 메모리를 늘려야 합니다.

5) 방화벽/보안그룹 변경

  • SSH 는 보통 22
  • JNLP 는 컨트롤러 443 또는 Jenkins 설정에 따른 포트

에이전트 머신에서 포트 연결만 확인하려면 다음처럼 테스트합니다.

nc -vz jenkins.example.com 443

6) Jenkins 업그레이드 이후 remoting 버전 불일치

오래된 agent.jar 를 고정으로 배포했다면 업그레이드 후 호환성 문제가 날 수 있습니다. 해결은 간단히 최신 agent.jar 로 교체하는 것입니다.

curl -fL -o agent.jar https://jenkins.example.com/jnlpJars/agent.jar

6분~7분: 재발 방지(가장 효과 큰 4가지)

1) 에이전트 systemd 로 감싸 자동 복구

jenkins-agent.service 예시입니다.

[Unit]
Description=Jenkins Inbound Agent
After=network-online.target
Wants=network-online.target

[Service]
User=jenkins
WorkingDirectory=/var/lib/jenkins
ExecStart=/usr/bin/java -jar /opt/jenkins/agent.jar -url https://jenkins.example.com/ -secret YOUR_SECRET -name agent-01 -workDir /var/lib/jenkins
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

적용:

sudo systemctl daemon-reload
sudo systemctl enable --now jenkins-agent

2) 워크스페이스/캐시 정리 정책

  • 오래된 워크스페이스 자동 삭제
  • 도커 사용 시 주기적 prune
docker system df
docker system prune -af --volumes

3) SSH 키/known_hosts 운영 표준화

  • 에이전트 재설치 시 호스트키 변경 절차 문서화
  • Jenkins 전용 SSH 키 롤오버 절차 마련

4) 관측성: 오프라인 감지와 알림

  • 노드 오프라인을 Slack, PagerDuty 로 알림
  • 컨트롤러 로그에서 특정 키워드 알림 룰 추가

부록: 상황별 빠른 결론(한 줄 처방)

  • JNLP 에이전트가 재시도만 반복한다: curl -vk 로 TLS/프록시부터 확인하고 agent.jar 최신화
  • SSH 가 publickey 로 실패한다: Jenkins 크리덴셜과 에이전트 authorized_keys 동기화
  • SSH 가 붙는데 에이전트가 안 뜬다: 원격 java 경로/권한/작업 디렉터리 확인
  • 자주 끊긴다: systemd Restart=always 와 네트워크 안정화, WebSocket 프록시 설정 점검

마무리

Jenkins 에이전트 오프라인은 증상이 비슷해 보여도, 실제 원인은 연결 방향인증 주체 에 따라 갈립니다. JNLP 는 에이전트에서 컨트롤러로, SSH 는 컨트롤러에서 에이전트로 붙는다는 차이를 기준으로 로그와 네트워크를 분기하면 대부분 7분 안에 복구가 가능합니다.

다음 장애를 더 빨리 끝내려면, 오늘 정리한 체크리스트를 그대로 런북으로 옮기고 systemd 자동 재시작과 로그 포인트를 표준화하는 것부터 시작하는 것을 추천합니다.