Troubleshooting 2026.11.01 7 min read

Jenkins SSH Agent를 연결하고 나서야 보인 JDK와 디스크 문제

처음 목표는 작았다. Jenkins가 원격 계정으로 접속해 Java와 Git을 실행하고, 지정한 Agent에서 Pipeline을 끝내는지 확인하려 했다. 그런데 설치 화면의 플러그인 오류부터 Agent의 작은 루트 파일시스템까지, 연결 성공 전후로 서로 다른 문제가 이어졌다.

Kubernetes에 올릴 서비스를 빌드하려고 Jenkins를 설치했다. Controller는 Terraform과 Ansible을 실행하던 자동화 서버에 두고, 실제 빌드는 별도 VM의 SSH Agent에서 실행하도록 구성했다. 빌드 부하와 작업 파일을 Agent 쪽에서 관리하려는 선택이었다.

처음 목표는 작았다. Jenkins가 원격 계정으로 접속해 Java와 Git을 실행하고, 지정한 Agent에서 Pipeline을 끝내는지 확인하려 했다. 그런데 설치 화면의 플러그인 오류부터 Agent의 작은 루트 파일시스템까지, 연결 성공 전후로 서로 다른 문제가 이어졌다.

설치 화면을 통과해도 의존성 경고가 남았다

Controller는 localhost의 8080 포트에 바인딩했다. 관리 화면은 SSH 터널을 통해 접근했다. 이 구성에서는 인터넷의 GitHub webhook이 Jenkins에 바로 들어올 수 없었고, 이후 CI는 SCM polling을 사용하는 방향으로 연결했다.

초기 설치 중 Pipeline, Git, GitHub Branch Source 등 여러 플러그인이 실패 목록에 나타났다. Retry를 거쳐 관리자와 대시보드까지 만들었지만 관리 화면에는 의존성 누락이 남아 있었다. 대표적인 경고는 다음 두 가지였다.

Git plugin: Plugin is missing: workflow-scm-step
Git client plugin: Plugin is missing: mina-sshd-api-core

상위 플러그인의 실패 목록만 보면 여러 기능이 한꺼번에 고장 난 것처럼 보였다. 실제로는 공통 의존성이 빠지면서 Pipeline 관련 플러그인까지 영향을 받는 구조였다. 원인 후보를 좁히기 위해 로그, 업데이트 사이트 응답, 디스크와 inode를 확인하는 진단 절차를 정리했다.

당시에는 Jenkins를 재시작한 뒤 의존성 경고가 해소됐다고 기록했다. 두 플러그인을 별도로 설치한 결과로 단정하지 않았다. 다운로드 실패의 네트워크 원인까지 밝혀낸 것도 아니었다. 화면 아래의 Java 지원 경고 역시 플러그인 의존성 문제와 나누어 봤다.

Jenkins 초기 플러그인 설치 실패 목록
Jenkins 초기 플러그인 설치 실패 목록.

로그인용 키와 서버 확인용 키를 구분했다

Agent VM에는 빌드 전용 OS 계정을 만들었다. Controller가 사용하는 SSH 공개키를 해당 계정에 배포하고, 개인키는 Jenkins의 SSH Credentials에 등록했다. 작업 디렉터리도 빌드 계정 소유로 준비했다.

여기서 SSH 로그인에 사용하는 개인키와 Agent 서버의 정체성을 확인하는 호스트 공개키를 구분해야 했다. Agent 등록에서는 서버의 Ed25519 호스트 공개키를 직접 제공하는 검증 방식을 선택했다. 접속이 편하다는 이유로 호스트키 검증을 생략하지 않았다.

Agent는 Permanent Agent, executor 1개, linux-ci label로 등록했다. 해당 label을 지정한 작업만 이 노드에서 실행하도록 구성했다. 초기 검증 Pipeline도 agent { label 'linux-ci' }를 사용해 실행 위치를 분명히 했다.

Jenkins Controller·Agent 온라인 상태와 linux-ci 라벨·원격 작업 경로
Jenkins Controller·Agent 온라인 상태와 linux-ci 라벨·원격 작업 경로.

실제 출력에는 Agent의 hostname과 빌드 계정, Java 21, Git 버전이 나타났고 마지막은 다음과 같았다.

Jenkins CI Pipeline OK
Finished: SUCCESS

이 결과로 원격 Agent에서 명령을 실행할 수 있다는 사실을 확인했다. 애플리케이션 소스를 컴파일하거나 테스트한 결과는 다음 단계에서 따로 확인했다. 2026년 10월 19일 읽기 전용 API에서 Controller executor는 0, Agent executor는 1인 것도 확인했다. 최종 작업은 별도 linux-ci Agent에서 실행됐다.

Java 실행 환경과 빌드 환경이 달랐다

초기 Agent 연결 시험에는 JRE로도 충분했다. Java 프로세스가 실행되면 됐기 때문이다. 실제 RCA Platform 소스를 빌드하는 단계에서는 컴파일러가 필요해 JDK를 준비했다. java -version과 함께 javac -version을 확인한 이유였다.

CI Agent의 실행 계정과 OS·CPU·메모리·Java 버전
CI Agent의 실행 계정과 OS·CPU·메모리·Java 버전.

Maven은 배포 파일과 SHA-512 체크섬을 함께 받아 검증한 뒤 설치하는 절차로 준비했다. Java가 있다는 사실, 컴파일러가 있다는 사실, Maven이 원하는 Java를 사용한다는 사실을 각각 확인해야 했다. SSH 연결이 정상이어도 이 조건이 맞지 않으면 실제 CI는 시작부터 달라질 수 있었다.

40GiB를 할당했는데 루트는 9.8G였다

Jenkins Nodes 화면에는 Agent의 여유 디스크와 임시 공간이 각각 4.43GiB로 표시됐다. VM에 40GiB 가상 디스크를 줬기 때문에 처음에는 예상보다 작은 값이었다. 게스트 안에서 계층별 용량을 확인하니 차이가 드러났다.

확인 대상 당시 출력
가상 디스크 sda 40G
LVM 파티션 sda3 17.3G
루트 LV 10G
df의 루트 ext4 9.8G, 여유 4.5G
VG의 남은 공간 약 7.32G

가상 디스크의 크기가 게스트 파티션과 LV, 파일시스템에 자동으로 모두 반영된 상태가 아니었다. 빌드 계정의 작업 경로를 일반 관리 계정으로 조회했을 때 나온 Permission denied도 별개였다. 해당 디렉터리의 접근 권한 때문에 발생한 것이어서 디스크 I/O 장애로 해석하지 않았다.

당시 확장은 파티션을 늘린 뒤 PV를 반영하고, LV와 파일시스템을 확장하는 순서로 진행했다. 작업 후 정상 확장을 보고했지만 함께 남은 최초 Pipeline 로그에는 여전히 9.8G가 찍혀 있었다. 그래서 이 로그를 확장 후 수치로 사용하지 않았다. 용량을 설명할 때는 실행 시점까지 함께 확인해야 했다.

초기 Jenkins 노드 목록과 Agent 여유 디스크
초기 Jenkins Agent 연결 상태와 여유 디스크 4.43GiB.
Jenkins Agent의 Online 상태와 linux-ci label·executor
ci-agent-01 Online, linux-ci label, executor 1개.

Jenkins를 설치한 뒤 가장 먼저 얻은 것은 자동 배포가 아니라 신뢰할 수 있는 빌드 실행 위치였다. 플러그인 경고를 정리하고, SSH 서버를 검증하고, JDK와 저장 공간을 확인한 다음에야 실제 애플리케이션 CI를 연결할 준비가 됐다.

SEARCH JOURNAL

기록 검색

글 제목, 요약, 태그에서 찾습니다.

검색을 준비하고 있어요.

검색어를 입력해 주세요.

    Ctrl/⌘ K 검색 Esc 닫기 ↑ ↓ 결과 이동