안녕!
우아한테크코스 5기 [스탬프크러쉬]팀 깃짱이라고 합니다.
스탬프크러쉬 서비스의 소스 코드 바로가기
사장모드: stampcrush.site/admin
고객모드: stampcrush.site
[우테코] 무중단 배포 자동화(1): Github Actions workflow 생성, Secrets 설정
앞선 포스팅에 계속 이어서, 무중단 배포 자동화 파이프라인을 만들어 보려고 한다.
💋 무중단 배포 계획
✔️ 인프라 구조
무중단 배포를 위해서, 서버를 2대 둘 수도 있겠지만, 우리 팀은 돈을 못 벌고 있기 때문에 아래와 같은 구조를 사용하기로 했다.
- Nginx가 리버스 프록시 서버 역할로, 서버로 들어오는 모든 요청을 받는다.
- 매 배포마다 8080, 8081 포트에 톰캣 서버를 번갈아가면서 하나씩 띄우고, 리버스 프록시 서버로 사용중인 nginx 웹 서버가 포트 포워딩 해주는 포트를 변경하는 식으로 ‘무중단’을 구현한다.
✔️ 무중단 배포 과정
그러니깐, 구체적으로는 새로운 코드가 push된 상황에서 배포는 아래와 같은 과정으로 일어나게 된다.
- 깃허브 레포지토리에 새로운 코드가 Push된다.
- 깃허브 액션이 trigger를 감지해 동작하고, 코드를 도커 이미지로 빌드해 Docker Hub에 push한다.
- 깃허브 액션이 배포 서버의 github actions self-hosted runners에 trigger를 보내, 배포 스크립트를 실행시킨다.
✔️ 배포 스크립트의 과정
실제로 ‘무중단’에 대한 부분은 여기에 구현되어 있을 것이다.
편리한 설명을 위해 현재는 8080 포트에서 애플리케이션이 실행되고 있다고 하겠다. (반대의 경우도 똑같이 생각하면 된다.)
- 8080, 8081 중 어떤 포트에서 현재 톰캣 서버가 돌고 있는지 확인한다. → 8080에 돌고 있는 것 확인함.
- docker hub로부터 도커 이미지를 pull 받아, 톰캣 서버를 8081 포트에 띄운다.
- 새로 띄운 8081 포트에 애플리케이션이 제대로 실행 되었는지 heath check를 한다. (health check용 API를 만들어도 좋고, 그냥 아무 API나 호출해도 괜찮다.)
- 8081 포트에 제대로 애플리케이션이 실행되지 않았다면, 그냥 배포를 종료한다. (없던 일로 하고 8080 잘 살아있게 둠)
- 리버스 프록시 서버로 사용중인 nginx 웹서버의 포트 포워딩을 8080에서 8081로 변경한다.
- 8080으로 들어가는 요청이 없어지므로, 8080 포트의 애플리케이션을 내리고, docker도 내려버린다. (리소스 정리)
✔️ 배포 서버에 설정할 것들
위에서 말한 내용을 하려면, 많은 것들을 설정해야 할 것이다.
- 배포 스크립트를 작성해야 한다.
- docker-compose를 설치하고, 설정 파일을 만들어야 한다.
- nginx를 설치하고, 포트 포워딩을 바꿔줄 수 있도록 설정해야 한다.
- github actions self-hosted runners를 설치하고 labels를 설정해야 한다.
그럼 이제 진짜로 무중단 배포 자동화를 완성해 보자.
레츠기릿
💋 배포 스크립트 작성
우리 개발 서버에 배포스크립트를 먼저 넣어 놓아야 한다. 위의 backend-docker-pull-and-run
에서 실행시킬 deploy.sh
를 만들어야 한다. (ec2의 루트에 만들면 된다.) 명령어는 sudo vim [파일이름]
하고 붙여넣기 esc
, :wq
입력
deploy.sh
#1
EXIST_GITCHAN=$(sudo docker-compose -p test-gitchan -f /home/ubuntu/docker-compose.gitchan.yml ps | grep Up)
if [ -z "$EXIST_GITCHAN" ]; then
echo "GITCHAN 컨테이너 실행"
sudo docker-compose -p test-gitchan -f /home/ubuntu/docker-compose.gitchan.yml up -d
BEFORE_COLOR="leo"
AFTER_COLOR="gitchan"
BEFORE_PORT=8081
AFTER_PORT=8080
else
echo "LEO 컨테이너 실행"
sudo docker-compose -p test-leo -f /home/ubuntu/docker-compose.leo.yml up -d
BEFORE_COLOR="gitchan"
AFTER_COLOR="leo"
BEFORE_PORT=8080
AFTER_PORT=8081
fi
echo "${AFTER_COLOR} server up(port:${AFTER_PORT})"
# 2
for cnt in {1..10}
do
echo "서버 응답 확인중(${cnt}/10)";
UP=$(curl -s http://127.0.0.1:${AFTER_PORT}/health-check)
if [ "${UP}" != "up" ]
then
sleep 10
continue
else
break
fi
done
if [ $cnt -eq 10 ]
then
echo "서버가 정상적으로 구동되지 않았습니다."
exit 1
fi
# 3
sudo sed -i "s/${BEFORE_PORT}/${AFTER_PORT}/" /etc/nginx/conf.d/service-url.inc
sudo nginx -s reload
echo "Deploy Completed!!"
# 4
echo "$BEFORE_COLOR server down(port:${BEFORE_PORT})"
sudo docker-compose -p test-${BEFORE_COLOR} -f /home/ubuntu/docker-compose.${BEFORE_COLOR}.yml down
이 스크립트를 실행하기 위해서 먼저 docker-compose
설치와 파일이 필요하다.
💋 docker-compose 설치와 파일 생성
✔️ docker-compose 설치
스크립트 내 존재하는 docker-compose
명령어를 실행하기 위해서는 설치를 해야한다.
아래 명령어로 바로 설치 가능하다.
sudo apt install docker-compose
✔️ docker-compose.yml 파일 작성
이 두가지도 마찬가지로 그냥 EC2 루트에 생성해준다. 명령어는 sudo vim [파일이름]
하고 붙여넣기 esc
, :wq
입력
docker-compose.gitchan.yml
version: '3.1'
services:
api:
image: stampcrush/stampcrush-dev:latest
container_name: test-gitchan
environment:
- LANG=ko_KR.UTF-8
- HTTP_PORT=8080
ports:
- '8080:8080'
docker-compose.leo.yml
version: '3.1'
services:
api:
image: stampcrush/stampcrush-dev:latest
container_name: test-leo
environment:
- LANG=ko_KR.UTF-8
- HTTP_PORT=8081
ports:
- '8081:8080'
💋 Github Actions self-hosted runner 설정
먼저 깃허브 액션이 조종할 수 있으려면, trigger를 감지하기 위해서 Github Actions self-hosted runner가 필요하다. 이 포스팅을 따라하면 쉽게 설치할 수 있다.
정상적으로 설치되었다면 이런 화면을 볼 수 있다.
✔️ Runner Labels 설정
위의 workflows의 2번째 job에서 라벨이 필요하다.
아래의 배포 스크립트에서 확인할 수 있듯이, 우리는 self-hosted
, dev
두 개의 라벨이 붙어있는 Runner를 실행하도록 할 것이다.
backend-docker-pull-and-run:
runs-on: [self-hosted, dev]
if: ${{ needs.backend-docker-build-and-push.result == 'success' }}
needs: [ backend-docker-build-and-push ]
steps:
- name: ✨ 배포 스크립트 실행
run: |
sh /home/ubuntu/deploy.sh
긍까 지금 러너에 저 라벨을 두 개를 붙여줘야 하는 거다. 전자는 기본으로 붙게 되니깐, dev
만 새로 붙여주면 된다.
Settings > Actions > Runners
에서 설정한다.
설치할 때, label 붙일거냐 물어보는데 그때 그냥 dev
붙이겠다고 써도 되긴 한다.
💋 Nginx 설정
✔️ nginx 설치
아래 두 명령어로 간단하게 우분투 서버에 nginx를 설치할 수 있다.
물어보면 다 그냥 yes, ok 예스맨 하면 된다.
sudo apt update
sudo apt install nginx
정상 설치되었다면, cd /etc
로 이동하면 거기서 nginx
디렉토리가 생긴 것을 확인할 수 있다.
sudo service nginx start // nginx 실행 시작
sudo service nginx status // nginx 상태 확인
start
하고, status
확인하면 아래처럼 active
확인 가능
참고로 종료 명령어는 이거임.
sudo service nginx stop // nginx 실행 종료
✔️ nginx 설정 파일 변경
설정 파일은 /etc/nginx/sites-available
에 있는 default
이다.
sudo vim default
통해서 수정할 수 있고, insert 모드 아닌 일반모드에서 ggdG
입력하면 전체 삭제되니깐 삭제하고 아래 내용 입력함.
server {
include /etc/nginx/conf.d/service-url.inc;
listen 80 default_server;
listen [::]:80 default_server;
gzip on;
gzip_types application/javascript application/octet-stream;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
gzip_static on;
root /usr/share/nginx/dist;
index index.html index.htm;
try_files $uri $uri/ $uri /index.html;
}
location /api {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, DELETE, PATCH, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
add_header 'Access-Control-Max-Age' 86400;
return 204;
}
add_header 'Access-Control-Allow-Origin' '*' always;
proxy_pass $service_url;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
✔️ service-url.inc 파일 생성
여기서 사용하는 service-url.inc
파일도 별도로 만들어 주어야 한다. 이 파일을 통해서, 위의 default
파일이 외부의 다른 파일로부터 외부 변수를 가져올 수 있다. 이 부분은 이제 8080, 8081 중 포워딩할 포트를 교체해주는 역할이 된다.
/etc/nginx/conf.d/service-url.inc
set $service_url http://127.0.0.1:8080;
이 부분에서 localhost
말고, 127.0.0.1로 설정해 줘야 한다.
DNS 서버에서 주소를 찾기 때문에 localhost로 설정하는 경우에 IP를 찾을 수 없어서 동작하지 않는다.
💋 아웃트로
이제 진짜 무중단 배포 자동화가 완성되었다. 오예!
도움이 되었다면, 공감/댓글을 달아주면 깃짱에게 큰 힘이 됩니다!🌟
비밀댓글과 메일을 통해 오는 개인적인 질문은 받지 않고 있습니다. 꼭 공개댓글로 남겨주세요!
'PROJECT > Stamp Crush' 카테고리의 다른 글
[우테코] 스탬프크러쉬를 마무리하며 (2) | 2023.12.04 |
---|---|
[우테코] JWT 방식에서 로그아웃, Refresh Token 만들기(2): 구현을 해보자! (0) | 2023.11.08 |
[우테코] 무중단 배포 자동화(1): Github Actions workflow 생성, Secrets 설정 (2) | 2023.10.27 |
[우테코] 스탬프크러쉬의 HikariCP 커넥션 풀 사이즈 설정 (0) | 2023.10.17 |
[모집공고] 스탬프크러쉬 기획/영업/마케팅 팀원 모집 (0) | 2023.10.16 |