AWS - EC2에서 Jenkins Pipleline 구성 및 다양한 문제 직면 후기
간만에 하얗게 불태웠다,,,
기존에 Jenkins Pipleline을 구성한 내용을 포스팅 했었는데, Window와 maven기반에서 작성한 내용이었다.
이번에 AWS EC2 Free-tier CentOS에서 Jenkins를 설치하고, gradle기반의 빌드 배포를 Pipeline을 통해 진행하고 싶었다.
금방하고 갓겜 스타나 하려고 했는데, 예상치도 못한 문제에 직면해 삽질을 오래하여 포스팅 해보려고 한다.
Setting
먼저 Pipepline 구성전에 아래의 tool들은 설치가 되어 있어야한다.
- jdk
- gradle
- git
Pipeline 구성
pipeline {
agent any
stages {
stage('GitHub Repository Clone') {
steps {
git branch: 'master', credentialsId: 'YOU CREDENTAIL', url: 'YOUR GITHUB'
}
}
stage('Gradle build') {
steps {
sh '''
echo 'Gradle Build'
sudo chmod 777 ./gradlew
sudo ./gradlew clean bootJar --no-daemon
'''
}
}
stage('Deploy') {
steps {
sh '''
sudo sh '/home/ec2-user/deploy.sh'
'''
}
}
}
}
구성은 평양냉면처럼 담백하고 간단하게 git clone - 빌드 - 배포 순으로 진행했다.
Git Credential 설정은 기존의 포스팅을 참고하면 된다.
https://foot-develop.tistory.com/14
삽질의 시작...
빌드에서 엄청난 삽질이 시작됐다.. 차근히 삽질을 분석해보자.
권한 문제
먼저 Jenkins는 sudo 권한이 없기 때문에 다양하게 permission denied를 발생하게 된다.
빌드랑 배포시에 모두 권한 문제가 발생하였다. 그래서 일단 Jenkins에게 sudo의 권한을 준 후 해결하였다.
좀 더 엄격하게 파일별로 권한관리를 하거나 해야 하는데, 일단 sudo 권한을 주고 수행하였다.
권한은 아래와 같이 주었다.
// 유저권한 파일 실행
vim /etc/sudoers
// 마지막줄에 추가
jenkins ALL=(ALL) NOPASSWD: ALL
Gardle Daemon으로 인한 메모리 문제
Build에 권한을 부여하고 진행하는데, 서버가 자꾸 멈췄다.
AWS ec2 인스턴스 모니터링을 했을 때, cpu도 50%대를 유지하고 있어서 괜찮아보여서 뭐가 문제일까 찾아봤는데 메모리가 full이었던 것이다.
build하는데 왜이렇게 많은 메모리를 잡아먹을까?
범인은 Gradle의 Daemon 프로세스였다.
Gradle은 Daemon프로세스를 진행하는데, 이녀석은 오래동안 살아있는 프로세스로 gradle 빌드 결과물을 보관한다.
이로 인해 한번 빌드된 프로젝트는 두번째부터 빌드 속도가 엄청 빨라지게 되는데, AWS Freetier에서는 1GB의 메모리를 제공하기 때문에 Daemon을 돌리게 되면 서버가 뻑나게 된다.
먼저, 어그레시브한 투자성향으로 주식과 코인으로 인해 상황이 녹록지 않기 때문에 과금없이 메모리 용량을 늘려줘야 했다.
AWS에서 리눅스는 하드디스크를 가상 메모리로 전환시켜 사용할 수 있다는 정보를 확인했다.
참고 : aws.amazon.com/ko/premiumsupport/knowledge-center/ec2-memory-swap-file/
메모리를 스왑하는 자세한 방법은 아래에 금자씨마냥 친절하게 설명돼있다.
https://okky.kr/articles/884329
그래도 메모리가 부족할 수 있으니 그냥 Daemon을 비활성화하기로 했다.
application.properties
...
org.gradle.daemon=false
gradle 실행시 아래의 명렁어로 실행
./gradlew clean bootJar --no-daemon
위의 두가지 방법으로 메모리를 늘리고 Daemon을 비활성화하면 EC2 Freetier에서도 Gradle로 Build가 빠르게 가능하다.
배포 Shell 작성
마지막으로 아래와 같이 배포shell을 작성하여 실행시켜주었다.
deploy.sh
echo "> daeranbot pid 확인"
CURRENT_PID=$(ps -ef | grep java | grep drbot | awk '{print $2}')
echo "$CURRENT_PID"
if [ -z ${CURRENT_PID} ] ;then
echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> sudo kill -9 $CURRENT_PID"
sudo kill -9 `ps -ef | grep java | grep drbot | awk '{print $2}'`
sleep 10
fi
echo "> daeranbot 배포"
JAR_PATH=$(ls -t /var/lib/jenkins/workspace/drbot/build/libs/*.jar | head -1)
sudo nohup java -jar ${JAR_PATH} >> /home/ec2-user/drbot.log &
위와 같은 작업을 통해 빌드/배포의 자동화가 완성되었다.
추후 nginx를 통해 무중단배포까지 추가하여 마무리 하고자 한다.
일단 오늘은 끗!
참고