Jenkins SSH Error 트러블 슈팅
젠킨스를 통해서 gradle 프로젝트를 빌드하고 대상 서버에 ssh 를 통해 publishing하여 기동을 하는 파이프라인이 있습니다. Jenkins 빌드 중에 예상치 못한 에러가 발생하였습니다. 다음은 젠킨스 빌드 로그 중 일부분입니다.
'Did not execute build step #1' 이라고 나오는데, 이 부분은 대상 서버 ssh를 접속과 관련이 있었습니다. Jenkins 프로젝트의 빌드 로그가 아닌 젠킨스가 설치된 서버에 접속해서 에러 로그를 직접 확인을 해보니 다음과 같은 로그를 확인할 수 있었습니다.
WARNING j.p.p.BPCallablePublisher#invoke: Exception when publishing, exception message [Failure]
4: Failure
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873)
at com.jcraft.jsch.ChannelSftp.checkStatus(ChannelSftp.java:2486)
at com.jcraft.jsch.ChannelSftp._put(ChannelSftp.java:651)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:540)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:492)
at jenkins.plugins.publish_over_ssh.BapSshClient.transferFile(BapSshClient.java:184)
at jenkins.plugins.publish_over_ssh.BapSshClient.transferFile(BapSshClient.java:54)
at jenkins.plugins.publish_over.BPTransfer.transferFile(BPTransfer.java:171)
at jenkins.plugins.publish_over.BPTransfer.transfer(BPTransfer.java:155)
at jenkins.plugins.publish_over.BPTransfer.transfer(BPTransfer.java:142)
at jenkins.plugins.publish_over.BapPublisher$Performer.transfer(BapPublisher.java:276)
at jenkins.plugins.publish_over.BapPublisher$Performer.perform(BapPublisher.java:232)
at jenkins.plugins.publish_over.BapPublisher$Performer.access$000(BapPublisher.java:205)
at jenkins.plugins.publish_over.BapPublisher.perform(BapPublisher.java:158)
at jenkins.plugins.publish_over.BPCallablePublisher.invoke(BPCallablePublisher.java:65)
at jenkins.plugins.publish_over.BPCallablePublisher.invoke(BPCallablePublisher.java:38)
...
WARNING j.p.p.BPInstanceConfig#perform: An exception was caught when invoking perform
4: Failure
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873)
at com.jcraft.jsch.ChannelSftp.checkStatus(ChannelSftp.java:2486)
at com.jcraft.jsch.ChannelSftp._put(ChannelSftp.java:651)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:540)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:492)
at jenkins.plugins.publish_over_ssh.BapSshClient.transferFile(BapSshClient.java:184)
at jenkins.plugins.publish_over_ssh.BapSshClient.transferFile(BapSshClient.java:54)
at jenkins.plugins.publish_over.BPTransfer.transferFile(BPTransfer.java:171)
at jenkins.plugins.publish_over.BPTransfer.transfer(BPTransfer.java:155)
at jenkins.plugins.publish_over.BPTransfer.transfer(BPTransfer.java:142)
at jenkins.plugins.publish_over.BapPublisher$Performer.transfer(BapPublisher.java:276)
at jenkins.plugins.publish_over.BapPublisher$Performer.perform(BapPublisher.java:232)
at jenkins.plugins.publish_over.BapPublisher$Performer.access$000(BapPublisher.java:205)
at jenkins.plugins.publish_over.BapPublisher.perform(BapPublisher.java:158)
at jenkins.plugins.publish_over.BPCallablePublisher.invoke(BPCallablePublisher.java:65)
Caused: jenkins.plugins.publish_over.BapPublisherException: Exception when publishing, exception message [Failure]
at jenkins.plugins.publish_over.BPCallablePublisher.invoke(BPCallablePublisher.java:69)
at jenkins.plugins.publish_over.BPCallablePublisher.invoke(BPCallablePublisher.java:38)
at hudson.FilePath.act(FilePath.java:1200)
at hudson.FilePath.act(FilePath.java:1183)
at jenkins.plugins.publish_over.BPInstanceConfig.perform(BPInstanceConfig.java:141)
at jenkins.plugins.publish_over.BPPlugin.perform(BPPlugin.java:126)
at jenkins.tasks.SimpleBuildStep.perform(SimpleBuildStep.java:123)
at hudson.tasks.BuildStepCompatibilityLayer.perform(BuildStepCompatibilityLayer.java:79)
at jenkins.plugins.publish_over_ssh.BapSshBuilderPlugin.perform(BapSshBuilderPlugin.java:64)
at org.jenkinsci.plugins.postbuildscript.processor.Processor.processBuildSteps(Processor.java:180)
at org.jenkinsci.plugins.postbuildscript.processor.Processor.processScripts(Processor.java:91)
at org.jenkinsci.plugins.postbuildscript.processor.Processor.process(Processor.java:79)
at org.jenkinsci.plugins.postbuildscript.processor.Processor.process(Processor.java:73)
at org.jenkinsci.plugins.postbuildscript.PostBuildScript.perform(PostBuildScript.java:77)
at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20)
at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:816)
at hudson.model.AbstractBuild$AbstractBuildExecution.performAllBuildSteps(AbstractBuild.java:765)
at hudson.model.Build$BuildExecution.post2(Build.java:179)
at hudson.model.AbstractBuild$AbstractBuildExecution.post(AbstractBuild.java:709)
at hudson.model.Run.execute(Run.java:1922)
at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:44)
at hudson.model.ResourceController.execute(ResourceController.java:101)
at hudson.model.Executor.run(Executor.java:442)
root cause는 'Caused: jenkins.plugins.publish_over.BapPublisherException: Exception when publishing, exception message' 였으므로 jenkins issues라고 검색을 하여 issues.jenkins.io 에 접속한 다음 디스크와 관련된 이슈 티켓을 하나 발견했습니다.
https://issues.jenkins.io/browse/JENKINS-49582
해당 내용은 디스크 공간 부족으로 인해 publish-over-ssh 동작을 수행하지 못한다는 내용이었습니다. 이를 참고하여 대상 서버의 디스크사용량이 100%인 것을 확인하여 디스크의 용량을 6GB -> 8GB로 증량하여 문제를 해결할 수 있었습니다.
문제 해결의 방향을 디스크 용량 증가로 둔 것은 기존의 서버들의 용량 대비 문제가 된 대상 서버의 용량이 적었기 때문이었습니다. 대상 서버에 접속하여 df -h, du -d 1 . 등의 명령어로 디렉터리 용량을 확인하며 파일을 파악하였으나 특이점을 찾지 못해 내린 조치였습니다.
SSH와 Disk의 관계
디스크가 가득 차면 SSH 데몬과 관련된 다양한 작업이 실패할 수 있습니다.
주요 원인은 다음과 같습니다.
로그 파일 작성 실패
SSH 접속 과정에서 서버는 사용자 인증 시 관련된 인증 로그를 작성하고, SSH 데몬(sshd)이 시스템 로그(/var/log/auth.log 등)를 업데이트합니다. 디스크가 가득 차면 이러한 로그 파일을 생성하거나 업데이트할 수 없기 때문에 SSH 서비스가 정상적으로 동작하지 않을 수 있습니다.
사용자의 임시 파일 생성 실패
사용자가 SSH로 접속할 때, 사용자 환경 설정 파일(.bashrc, .zshrc 등)을 로드하기 위해 임시 파일을 생성하거나 작업 디렉터리를 준비해야 할 수 있습니다. /tmp 디렉터리 또는 사용자의 홈 디렉터리(/home/username)에 임시 파일을 생성하지 못하면 로그인 절차가 실패할 가능성이 있습니다.
sshd 서비스 자체 동작 장애
SSH 데몬(sshd)은 설정 파일(/etc/ssh/sshd_config)을 읽거나 인증 키 파일을 검증하기 위해 파일 시스템에 접근해야 합니다. 디스크가 가즉 차 있으면 이러한 파일 접근이 실패하거나 새로운 파일을 생성해야 하는 작업이 중단되어 서비스가 정상적으로 작동하지 않을 수 있습니다.
파일 시스템의 Inode 부족
디스크 용량이 가득 차지 않았더라도, 파일 시스템에서 사용할 수 있는 Inode(파일 메타 데이터)가 부족한 경우에도 문제가 발생할 수 있습니다. 이 경우, 새로운 파일을 생성하지 못하기 때문에 로그 작성이나 임시 파일 생성 작업이 실패하게 됩니다.
💡 Inode 란?
파일 시스템에서 파일이나 디렉터리에 대한 메타데이터를 저장하는 데이터 구조입니다. 파일 시스템의 핵심 구성 요소 중 하나로, 파일의 실제 데이터와는 별개로 파일에 대한 정보를 관리하는 역할을 합니다.
사용자 쉘 환경 초기화 실패
SSH로 접속하면 사용자의 쉘 환경이 초기화되면서 홈 디렉터리에서 설정 파일을 읽고 세션을 시작합니다. 홈 디렉터리에 필요한 파일 생성이 불가능하면 접속이 중단될 수 있습니다.
GPT