[AWS] 3. CI/CD 1

문정준's avatar
Jun 13, 2025
[AWS] 3. CI/CD 1
 

1. Elastic IP Address

  • 유동 IP는 IP가 수시로 바뀌기 때문에 서비스할 수 없음
    • 고객들이 변경된 IP 주소를 추적할 수 없음
  • 이 때문에 서비스를 위해서는 고정된 IP가 필요
    • 탄력적 IP = 고정 IP
 

EC2 Elastic IP 설정

  • 메뉴의 네트워크 및 보안 → 탄력적 IP 클릭
notion image
 
  • 탄력적 IP 주소 할당 클릭
notion image
 
  • 네트워크 설정 후 할당
notion image
 
  • 생성된 IP 확인
    • 생성만 해둘 경우 사용료가 청구되므로 주의
notion image
 

Elastic IP 연결

  • 생성한 IP 주소 선택 후 작업 → 탄력적 IP 주소 연결 클릭
notion image
 
  • 연결할 인스턴스 및 프라이빗 IP 주소 등록 후 연결 클릭
notion image
 
  • 연결한 인스턴스의 IP 변경 확인
    • 고정 IP로 변경됨
notion image
 

고정 IP 사용 시 주의할 점

  • 인스턴스만 종료하고 고정 IP가 남아있을 시, 유료 요금이 청구됨
  • 반드시 고정 IP 연결 해제 및 삭제를 우선 진행한 후 인스턴스 종료
 

2. JDK 설치 & 환경 설정

  • sudo apt update : apt 목록 갱신
  • sudo apt-cache search jdk | grep 21 : jdk 21 버전만 검색
notion image
  • sudo apt install openjdk-21-jdk -y : openJDK 21 설치
    • -y : 모두 동의
  • sudo apt install net-tools : 네트워크 툴 설치
    • 세션 동작 확인 가능
 

3. 백그라운드 실행

nohup

  • 프로세스를 백그라운드에서 실행시켜 터미널을 종료해도 실행이 유지되도록 하는 명령어
    • git clone 받은 후 gradlew build 필요
    • notion image
    • 없을 경우 gradlew 실행 권한 부여 후 build
    • notion image
    • 키워드 ‘&’ 필요
nohup java -jar *.jar &
 
  • 실행 시 해당 프로세스 번호 출력
notion image
 
  • nohup.out 파일에 자동으로 로그 저장
    • 따로 로그를 저장할 파일이 필요할 경우 > 연산자 사용
    • nohup java -jar *.jar 1>log.out 2>err.out &
    • 서버 로그는 정상 입출력이기 때문에 1> 사용 시 서버의 전체 로그 저장
    • 2> 사용 시 리눅스에서 발생한 오류 (서버 open 중 발생한 오류, 오타로 인한 미실행 오류 등) 저장
    • tail을 사용하여 로그 확인 가능
notion image
 
  • 터미널을 종료해도 접속 가능
notion image
 
  • 터미널 재 실행 후 네트워크 확인
    • 실행 중
notion image
 
  • 프로세스 확인
    • 실행 중
notion image
 
  • 종료 시에는 kill 사용
    • kill -9 PID (8487)
    • 세션 종료 확인 가능
notion image
 

Timezone

  • 배포 시 시간 설정 필요
    • 기본 설정은 UTC +0000 (영국)
timedatectl
notion image
 
  • 설정 가능한 시간대 리스트 확인
    • 결과가 매우 많기 때문에 검색 및 파이프라인 활용
timedatectl list-timezones
notion image
 
  • 서울 시간대 검색
timedatectl list-timezones | grep Seoul
notion image
 
  • 서울 시간대 적용
sudo timedatectl set-timezone Asia/Seoul
notion image
 

4. 스크립트 생성

pgrep

  • 검색한 결과의 프로세스 ID를 출력하는 명령어
pgrep -f .jar
notion image
  • 7446이 실제 서버 프로세스인지 확인
    • ps -ef로 확인해본 결과 아님 → .jar로만 찾는 것은 위험
    • 검색 시 실행한 프로세스의 전체 이름을 적어주는 것이 안전
notion image
 

스크립트 파일 작성

  • spring-stop.sh 파일 작성
    • 확장자의 의미는 없으나 스크립트 파일임을 나타내기 위해 추가 (Shell 파일)
echo "Springboot Stop..." SPRING_PID=$(pgrep -f 0.0.1-SNAPSHOT.jar) echo $SPRING_PID kill -9 $SPRING_PID
 
  • 실행 권한 추가 후 서버가 실행 중일 때 스크립트 실행
    • 정상적으로 종료되는 것을 확인
notion image

5. cron 주기적 실행

cron

  • 일정한 시간마다 프로세스를 예약하여 실행시킬 수 있는 스케줄러
  • /etc/crontab 내부 파일의 내용을 읽어서 프로세스 수행
 
  • crontab 편집
    • 에디터 선택 : 원하는 에디터 선택 후 확인하면 crontab 내용이 출력
notion image
crontab -e
notion image
  • 스케줄을 등록하기 위해 다음 코드 추가
* * * * * ls -l >> cron.log
  • 각 별의 위치마다 설정이 다름
    • 첫 번째 별 : 분 (0 ~ 59)
    • 두 번째 별 : 시간 (0 ~ 23)
    • 세 번째 별 : 일 (1 ~ 31)
    • 네 번째 별 : 월 (1 ~ 12)
    • 다섯 번째 별 : 요일 (0 ~ 7)
      • 0과 7은 일요일로 동일함
      notion image
       
  • 1분 후 파일 생성 확인 가능
notion image
 
  • 내용 확인 시 파일의 리스트가 저장되는 것을 확인 가능
notion image
 

스크립트로 cron 등록

  • 위 방법을 사용하면 일일이 cron에 스케줄을 등록해야 함
    • 스크립트를 통해 자동으로 cron을 등록하도록 설정
 
  • myScript.sh 생성
    • 다음 코드 입력
    • crontab -l > crontab_new
       
  • myScript.sh 실행
    • 실행 권한 우선 부여
    • crontab_new 파일 생성
notion image
 
  • crontab_new 파일 확인
    • crontab 내용 작성 확인
notion image
 
  • 스크립트로 cron에 자동 등록하기 위해 myScript.sh 수정 및 job.sh 파일 생성
    • myScript.sh
    • # Copy previous crontab into new crontab crontab -l > crontab_new # Add echo result into crontab_new echo "* * * * * /home/ubuntu/job.sh" >> crontab_new # Apply crontab_new into crontab crontab crontab_new # Remove crontab_new rm crontab_new
       
    • job.sh
    • ls -l > /home/ubuntu/cron.log
 
  • crontab에 새로 job.sh 실행 줄이 적힌 것을 확인 가능
 
  • cron.log 파일 확인
notion image
 

Restarting Server with cron

  • 스크립트를 활용하여 스프링 서버가 종료되었을 때에 재시작하는 cron 설정
 
  • 만들어둔 spring-stop.sh 옮기기
    • mkdir cron-restart
    • mv spring-stop.sh cron-restart/
notion image
 
  • spring-restart.sh 만들기
    • 다음 내용 입력
    • SPRING_PID=$(pgrep -f v1-0.0.1-SNAPSHOT.jar) SPRING_PATH="/home/ubuntu/aws-v1/build/libs/v1-0.0.1-SNAPSHOT.jar" echo $SPRING_PID echo $SPRING_PATH # Check if the server is not running # Wrap $SPRING_PID with quotes : it's not string if [ -z "$SPRING_PID" ]; then echo "Springboot is closed..." echo "Restart Springboot - $(date)" >> /home/ubuntu/cron-restart/spring-restart.log nohup java -jar $SPRING_PATH 1>log.out 2>err.out & else echo "Springboot is running..." fi
 
  • spring-restart.sh 실행
    • 실행 권한 부여
    • 실행 중일 때 : Springboot is running… 출력
    • notion image
       
    • 정지된 상태일 때 : Springboot 자동 재 시작
    • notion image
       
    • 재시작 로그 : cron-restart 폴더에서 확인 가능
    • notion image
       

6. 재배포

deploy 작성

  • 스크립트를 활용하여 모든 환경을 다시 설정하는 파일 작성
 
  • deploy.sh 불러오기
    • 외부에서 가져오기 : sftp를 활용하여 저장시키기
notion image
 
  • git에서 받은 deploy.tar 파일 넣기
    • .tar : 리눅스에서 사용하는 압축 파일
notion image
notion image
 
  • .tar 압축 풀기
tar -xvf deploy.tar
notion image
 
  • 각 파일 확인
    • var.sh : 전역 변수 지정
    • #!/bin/bash GITHUB_ID="Sxias" PROJECT_NAME="aws-v2" PROJECT_VERSION="0.0.1" PROJECT_PID="$(pgrep -f ${PROJECT_NAME}-${PROJECT_VERSION}.jar)" JAR_PATH="${HOME}/${PROJECT_NAME}/build/libs/${PROJECT_NAME}-${PROJECT_VERSION}.jar" export GITHUB_ID export PROJECT_NAME export PROJECT_VERSION export PROJECT_PID export JAR_PATH
       
    • deploy.sh : 배포
    • #!/bin/bash # 1. env variable source ./var.sh echo "1. env variable setting complete" # 2. cron delete touch crontab_delete crontab crontab_delete rm crontab_delete echo "2. cron delete complete" # 3. server checking if [ -n "${PROJECT_PID}" ]; then # re deploy kill -9 $PROJECT_PID echo "3. project kill complete" else # first deploy # 3-1 apt update sudo apt-get -y update 1>/dev/null echo "3-1. apt update complete" # 3-2 jdk install sudo apt-get -y install openjdk-21-jdk 1>/dev/null echo "3-2. jdk install complete" # 3-3 timezone sudo timedatectl set-timezone Asia/Seoul echo "3-3. timezone setting complete" fi # 4. project folder delete rm -rf ${HOME}/${PROJECT_NAME} echo "4. project folder delete complete" # 5. git clone git clone https://github.com/${GITHUB_ID}/${PROJECT_NAME}.git sleep 3s echo "5. git clone complete" # 6. gradlew +x chmod u+x ${HOME}/${PROJECT_NAME}/gradlew echo "6. gradlew u+x complete" # 7. build cd ${HOME}/${PROJECT_NAME} ./gradlew clean build echo "7. gradlew build complete" # 8. start jar nohup java -jar -Dspring.profiles.active=prod ${JAR_PATH} 1>${HOME}/log.out 2>${HOME}/err.out & echo "8. start server complete" # 9. cron registration touch crontab_new echo "* * * * * ${HOME}/check-and-restart.sh" 1>>crontab_new # register the others... you use >> (append) crontab crontab_new rm crontab_new echo "9. cron registration complete"
       
    • check-and-restart.sh : 확인 후 서버 재시작
    • #!/bin/bash source ./var.sh if [ -z "$PROJECT_PID" ]; then nohup java -jar -Dspring.profiles.active=prod ${JAR_PATH} 1>${HOME}/log.out 2>${HOME}/err.out & fi
 
  • deploy.sh 실행
    • var.sh가 스크립트에 의해 전역 변수로 등록됨
    • deploy 내부의 check-and-restart.sh 실행 코드가 cron에 등록됨
    • cron에 의해 서버가 실행되지 않았을 때 자동 재시작
    • 이후 서버 재배포가 필요할 때에도 deploy.sh 내부에 서버 정지 및 스케줄러 삭제 스크립트가 포함되어 있으므로 deploy.sh만 실행하면 됨
notion image
notion image
 
Share article

sxias