NGINX 무중단 배포

코딩을 합시다·2023년 1월 27일
1

CICD 배포
https://velog.io/@dirn0568/Git-Actions-S3-CodeDeploy-CICD-%EB%B0%B0%ED%8F%AC


먼저 서버에 jdk를 설치해주는것을 잊지말자

1. Nginx 설치

$ sudo apt install nginx
$ sudo service nginx start

2. 보안 그룹 추가

ec2 - 보안 그룹 - EC2 보안 그룹 선택 - 인바운드 편집에서 80번 포트에 대해 0.0.0.0/0, ::/0을 오픈한다.

-> 잘 연동이 되었다면 ec2 도메인에 접속 했을때 이런 페이지가 나올 것이다

3. nginx.conf 수정

나는 nginx.conf를 수정하는 것이 아닌 아래 명령어를 통해 여기서 대신 nignx.conf 파일을 바꿔주었다. 아래 명령어로 수정을 해도 되는 이유는 nginx.conf에 include /etc/nginx/sites-enabled/*; 가 있기 때문에 include를 통해 사용할 수 있기 때문이다.

$ cd /etc/nginx/sites-available/
$ sudo vim default
또는
$ vim /etc/nginx/sites-enabled/default

3-1. service_url 설정

vim /home/ubuntu/service_url.inc
# service_url.inc

set $service_url http://127.0.0.1:8081;

3-3. nginx 재시작 및 테스트

sudo service nginx restart
sudo nginx -t


이렇게 나오면 성공!

ec2에서 아래의 권한들을 줘야함

그리고 아래 파일들을 추가해줘야함

# appspec.yml
version: 0.0
os: linux

files:
 - source: /
   destination: /home/ubuntu/{프로젝트 경로}

hooks:
 ApplicationStart:
   - location: run_new_was.sh
     timeout: 60
     runas: ubuntu
   - location: health_check.sh
     timeout: 60
     runas: ubuntu
   - location: switch.sh
     timeout: 60
     runas: ubuntu
# health_check.sh

#!/bin/bash

# service_url.inc에서 현재 서비스를 하고 있는 WAS의 포트 번호 가져오기
CURRENT_PORT=$(cat /home/ubuntu/service_url.inc | grep -Po '[0-9]+' | tail >-1)
TARGET_PORT=0

if [ ${CURRENT_PORT} -eq 8081 ]; then
   TARGET_PORT=8082
elif [ ${CURRENT_PORT} -eq 8082 ]; then
   TARGET_PORT=8081
else
   echo "> No WAS is connected to nginx"
   exit 1
fi

# 위 커맨드들을 통해 현재 타겟 포트 가져오기

echo "> Start health check of WAS at 'http://127.0.0.1:${TARGET_PORT}' ..."

# 아래 커맨드들을 새로 열린 서버가 정상적으로 작동하는지 확인

# 해당 커맨드들을 10번씩 반복 # 배포할 서버를 10번 테스트 해서 통과하면 넘어가짐 >health_check는 응답을 보고 정상 응답인지 비정상 응답인지 확인한다는 의미?, 안전장치로 >10번 테스트
for RETRY_COUNT in 1 2 3 4 5 6 7 8 9 10
do
   echo "> #${RETRY_COUNT} trying..."
   # 테스트할 API 주소를 통해 http 상태 코드 가져오기
   RESPONSE_CODE=$(curl -s -o /dev/null -w "%{http_code}" >http://127.0.0.1:${TARGET_PORT})

   # RESPONSE_CODE의 http 상태가 200번인 경우
   if [ ${RESPONSE_CODE} -eq 200 ]; then
       echo "> New WAS successfully running"
       exit 0
   elif [ ${RETRY_COUNT} -eq 10 ]; then
       echo "> Health check failed."
       exit 1
   fi
   # 아직 열려있지 않았다면 sleep
   sleep 15
done
# run_new_was.sh

#!/bin/bash

PROJECT_ROOT="/home/ubuntu/{프로젝트 폴더}" # 프로젝트 루트
JAR_FILE="$PROJECT_ROOT/build/libs/{배포용 jar 파일}" # JAR_FILE (어쩌구저쩌구.jar)

# service_url.inc 에서 현재 서비스를 하고 있는 WAS의 포트 번호 가져오기
CURRENT_PORT=$(cat /home/ubuntu/service_url.inc | grep -Po '[0-9]+' | tail -1)
TARGET_PORT=0

echo "> Current port of running WAS is ${CURRENT_PORT}."

if [ ${CURRENT_PORT} -eq 8081 ]; then
  TARGET_PORT=8082 # 현재 포트가 8081이면 8082로 배포
elif [ ${CURRENT_PORT} -eq 8082 ]; then
  TARGET_PORT=8081 # 현재 포트가 8082라면 8081로 배포
else
  echo "> Not connected to nginx" # nginx가 실행되고 있지 않다면 에러 코드
fi # 없으면 에러남???

# 현재 포트의 PID를 불러온다
TARGET_PID=$(lsof -Fp -i TCP:${TARGET_PORT} | grep -Po 'p[0-9]+' | grep -Po '[0-9]+')

# PID를 이용해 해당 포트 서버 Kill
if [ ! -z ${TARGET_PID} ]; then
  echo "> Kill ${TARGET_PORT}."
  sudo kill ${TARGET_PID}
fi

# 타켓 포트에 jar파일을 이용해 새로운 서버 실행
nohup java -jar -Dserver.port=${TARGET_PORT} ${JAR_FILE} > /home/ubuntu/nohup.out 2>&1 &
echo "> Now new WAS runs at ${TARGET_PORT}."
exit 0
# switch.sh

#!/bin/bash

# service_url.inc에서 현재 서비스를 하고 있는 WAS의 포트 번호 가져오기
CURRENT_PORT=$(cat /home/ubuntu/service_url.inc  | grep -Po '[0-9]+' | tail -1)
TARGET_PORT=0

echo "> Nginx currently proxies to ${CURRENT_PORT}."

if [ ${CURRENT_PORT} -eq 8081 ]; then
    TARGET_PORT=8082
elif [ ${CURRENT_PORT} -eq 8082 ]; then
    TARGET_PORT=8081
else
    echo "> No WAS is connected to nginx"
    exit 1
fi

# 위 커맨드들을 통해 현재 타겟 포트 가져오기

# $ service_url.inc 파일을 현재 바뀐 서버의 포트로 변경
echo "set \$service_url http://127.0.0.1:${TARGET_PORT};" | tee /home/ubuntu/service_url.inc

echo "> Now Nginx proxies to ${TARGET_PORT}."

# nginx를 reload 해준다.
sudo service nginx reload

echo "> Nginx reloaded."

# -9 SIGKILL 은 서버를 바로 종료하므로
# -15 SIGTERM  안전 종료인 SIGTERM을 사용하여 이전 포트 프로세스를 제거한다.

CURRENT_PID=$(lsof -Fp -i TCP:${CURRENT_PORT} | grep -Po 'p[0-9]+' | grep -Po '[0-9]+')

sudo kill -15 ${CURRENT_PID}

설정변경후 nginx와 ec2 인스턴스를 재실행 해주자!


만약 스프링 시큐리티를 사용하고 있다면
health_check.sh의 아래 코드가 가리키는 url을 permitAll() 처리를 해야 200 응답을 받고 넘어 갈 수 있다.

RESPONSE_CODE=$(curl -s -o /dev/null -w "%{http_code}"  http://127.0.0.1:${TARGET_PORT}/)

이걸 하면서 알아낸 잡다한것들

  • appspec.yml은 프로젝트 최상단 dir에 있어야함
  • 제거 명령어:sudo rm -r ./shadi
  • ec2에서 포트번호 8081과 8082도 열어줘야함

포트포워딩

  • sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080

포트포워딩 확인하는 명령어

  • $sudo iptables -t nat -L --line-numbers

127.0.0.1로 적어줘야함 localhost로 바꿔서 적으면 오류남

cpu 사용량이 높으면 인스턴스가 꺼짐 인스턴스 재부팅하면 다시 복구 가능 하지만 근본적인 해결이 아니었기 때문에 아래 방법을 통해 해결했다

  • 인스턴스가 꺼지는 문제가 메모리 때문에 발생하는 것을 발견하고 해결하기 위해 swap memory를 사용했다.

    swap memory란?
    Swap Memory란 하드디스크의 일부 용량을 RAM처럼 사용할 수 있게 하는 방법입니다. 즉, 시스템에 RAM 용량이 부족해도 하드디스크를 활용하여 프로그램을 계속 실행시킬 수 있습니다.

# 서버에 차례대로 적어주면 된다
# 스왑 파일은 4GB(128MB x 16)
$ sudo dd if=/dev/zero of=/swapfile bs=128M count=16

# 스왑 파일의 읽기 및 쓰기 권한을 업데이트
$ sudo chmod 600 /swapfile

# Linux 스왑 영역을 설정합니다.
$ sudo mkswap /swapfile

# 스왑 공간에 스왑 파일을 추가하여 스왑 파일을 즉시 사용할 수 있도록 한다.
$ sudo swapon /swapfile

# 프로시저가 성공적인지 확인
$ sudo swapon -s

# /etc/fstab 파일을 편집하여 부팅 시 스왑 파일을 활성화 한다.
$ sudo vi /etc/fstab

# 맨 아랫줄에 추가후 저장
$ /swapfile swap swap defaults 0 0

메모리가 약간이지만 늘어난 것을 확인 할 수 있다.

1개의 댓글

comment-user-thumbnail
2023년 3월 2일

애기관우님 화이팅♥♥♥♥♥

답글 달기