Jenkins sshPublishers의 removePrefix가 뭔지 잘 이해되지 않아 정리합니다. 추가로 remoteDirectory, sourceFiles 설정도 함께 정리하였습니다.
빌드 후 조치의 SSH Publishers 설정 🤗
예제로 사용할 Send build artifacts over SSH의 설정입니다.
Source files
Source files는 로컬 서버에서 원격지 서버로 전송할 파일을 의미합니다. 주의할 점은 위와 같이 /build/libs/*.jar를 입력할 경우 build/libs에 있는 jar 파일만 이동되는게 아닙니다. /build/libs 폴더도 이동됩니다. 😯
remoteDirectory
ssh로 연결한 원격 서버의 작업 디렉토리를 의미합니다. Source files에 입력한 파일들이 이 작업디렉토리로 이동됩니다. 앞서 /build/libs/*.jar 파일들은 Remote directory에 입력한 namevalue 디렉토리 내에 위치한 것을 확인할 수 있습니다. 참고로 작업 디렉토리의 기준이 되는 루트 디렉토리는 Jenkins의 시스템 설정에 추가한 SSH Server 의 Remote Directory 입니다.
만약 /home/sksim/application/namevalue 라는 폴더로 파일들을 복사하고 싶다면 Remote directory에 /application/namevalue를 입력하면 됩니다.
removePrefix
지금은 jar 파일과 build/libs 디렉토리를 함께 전송하고 있습니다. 사실 저는 jar 파일만 이동시키면 됩니다. build/libs라는 디렉토리까지 이동시킬 필요가 없는 것입니다. 즉, Source files 에 포함된 파일들 중 전송시키고 싶지 않는 Prefix 경로를 적어주면 removePrefix에 적어주면 Prefix에 해당하는 파일이나 디렉토리는 이동되지 않습니다. /build/libs를 입력하면 *.jar 에 해당하는 파일만 이동되는 것입니다.
- webhook이란 원격 저장소의 소스에 push, commit 등의 이벤트가 발생하면 Jenkins와 같은 CI 서버에 해당 이벤트를 전달하는 기능입니다. Jenkins에서 이 이벤트 정보를 받아 리빌드, 배포와 같은 작업을 연계하여 진행해보도록 하겠습니다.
4. Item 생성
4.1. Freestyle project를 생성합니다.
4.2. 설명 및 GitHub project url을 입력합니다. 실제로 여기에 입력한 Git 주소가 연동에 사용되진 않습니다.
4.3. 소스코드 관리로 Git을 체크한 후, 실제로 연동할 Git 주소를 입력합니다. 그럼 인증을 하라는 에러가 발생하며, Git 계정 인증 시 'password 방식'이 지원을 하지 않으니 'Token authentication 방식'을 사용하라고 합니다. 그럼 토큰을 만들어야겠죠? 토큰은 깃허브 홈페이지에서 만들 수 있습니다.
4.4. 하던 작업을 잠깐 멈추고 '깃허브 로그인 / settings / developer settings / Personal access tokens' 탭에 들어가 Generate new token 버튼을 선택합니다.
4.5. 리포지토리에 대한 전체 접근 권한 및 hook 권한을 체크한 후, Generate Token 버튼을 눌러 토큰을 생성합니다.
* repo, admin:repo_hook을 체크하면 됩니다.
* Expiration을 No expiration으로 설정하면 토큰 만료 기간 없이 계속 사용 가능합니다.
4.6. 생성된 토큰 값을 확인 후 복사합니다.
* 참고로 해당 페이지를 넘어가게 되면 현재 발급된 토큰 키값을 다시 확인할 수 없으며, 분실 시 재발급 받아야합니다.
4.7. Jenkins로 돌아가 Credentials / Add를 선택 후 Kind에는 Username with password, UserName에는 GitHub ID, Password에는 복사한 토큰 키를 입력합니다. 아래 ID와 Description은 식별자와 설명입니다. 임의로 입력 후 Add를 누릅니다. 에러가 사라졌다면 인증이 완료된 것입니다.
4.8. Branch는 Master로 설정합니다.
4.9. 빌드 유발은 GitHub hook trigger for GITScm polling을 선택합니다. 이 옵션이 있어야 webhook을 통해 Jenkins로 들어온 push 이벤트 정보를 인식하여 빌드를 유발할 수 있습니다. 실제 빌드는 다음 Build 탭에서 설정합니다.
4.10. 필자의 경우 Gradle SpringBoot 프로젝트이기때문에 Invoke Gradle Script를 선택 후 Tasks에 bootJar를 입력했습니다. build.gradle 파일에는 다음 코드를 입력하여 modu.jar라는 파일명으로 빌드되도록 설정한 상태입니다.
* jar 파일 빌드가 완료되면 빌드 후 조치 부분에 빌드된 jar 파일을 실행시키도록 하여 스프링 부트에 내장되어 있는 tomcat 서버를 통해 서비스를 기동할 예정입니다.
* Gradle Version에서는 빌드에 Gradle을 지정해줘야하는데 이는 Global Tool Configuration 탭에서 설정이 가능합니다.
4.11. 빌드 성공 시 start.sh라는 스크립트를 실행하도록 합니다. 해당 스크립트안에는 현재 실행되고 있는 프로세스가 있다면 kill 후 재시작하는 코드가 작성되어 있습니다. Script에 해당하는 경로에 start.sh 파일을 적절히 커스터마이즈하여 생성해줍시다.
* start.sh
#!/bin/bash
echo "PID Check..."
CURRENT_PID=$(ps -ef | grep java | grep modu | awk '{print $2}')
echo "Running PID: {$CURRENT_PID}"
if [ -z ${CURRENT_PID} ] ; then
echo "Project is not running"
else
echo "Kill Current PID"
kill -9 $CURRENT_PID
sleep 10
fi
echo "Deploy Project...."
nohup java -jar /var/lib/jenkins/workspace/practice-project/build/libs/modu.jar >> /home/ec2-user/practice-script/modu.log &
echo "Done"
~
이걸로 간단한 형태의 Item 생성 및 설정이 끝났습니다. 이제 마스터 브랜치로 push를 하여 자동으로 빌드 및 jar파일을 실행시켜 배포가 되는지 확인해보도록 하겠습니다.
5. Git Push
5.1. 소스코드 수정 후 GitHub Desktop 프로그램을 사용해 commit / push를 진행합니다.
6. Jenkins 자동 빌드 및 배포 확인
6.1. Push를 하면 자동으로 Jenkins 빌드가 시작됩니다. Build History에서 확인이 가능합니다.
6.2. 해당 빌드 선택 후 Console Output을 확인하면 빌드 로그를 확인할 수 있습니다. 확인 결과, 빌드에 성공하여 BUILD SUCCESSFUL를 뿌리고 있습니다. 그에 따라 start.sh 스크립트를 실행하는 로그도 확인되고 있습니다. 스크립트도 정상적으로 실행되었으니 실제로 서비스가 올라갔는지 확인해보도록 하겠습니다.
6.3. public DNS로 조회하여 서비스 확인 결과, 정상적으로 jar파일이 실행되어 tomcat 서비스가 올라간 것을 확인할 수 있습니다.
7. 마치며...
Jenkins를 사용하여 정말 간단한 구조의 DevOps 환경을 구성해보았습니다. SpringBoot / Gradle 프로젝트, Git을 통한 소스관리, Jenkins를 통한 자동 빌드 및 배포, Swagger를 통한 REST API Interface를 제공하게 되었네요.. 뿌듯..
아무래도 프리티어 서버를 통해 작업을 진행하다 보니 중간중간 메모리 부족으로 인한 문제도 발생하였습니다. 간혹가다 빌드 시 OutofMemory가 발생하거나, 서버 자체가 꺼져버리는 현상이었습니다. 그럴때마다 AWS EC2 인스턴스를 재시작했었는데, 현재는 Swap Memory를 0 > 2GB로 늘려주어 해결한 상태입니다. 관련 포스팅 다음에 진행하여 링크를 남겨놓도록 하겠습니다!