무중단 배포 전략하고 이어지는 글입니다!
이전 논의 사항을 바탕으로 우리팀 백엔드 최종 전략은 블루그린이다
현재는 DEV 서버에만 적용되어 있으며, L4 로드밸런싱중 포트를 활용한다.
3일정도 DEV에 신기능 머지 진행 후 에러가 없다고 판단되면 PROD 서버에도 적용할 예정이다. 이전 게시글에서도 말했듯 가해지는 부하가 적고 한정적일 예정이라 현실적으로는 포트단위로 해도 좋을 듯 하나 fail over 대비차원에서 IP단위로도 해볼까 싶다.(아니면 L7에 URL버저닝해서 프엔이랑 같이 돌아가는걸 구상해보아도 좋을 듯 하다.)
아 몰라 아무튼 지금 우리는 포트 8080과 8081을 번갈아서 사용한다.
설계해서 구현한 로직은 다음과 같다.
1. 깃허브에 머지
2. 젠킨스에 트리거 동작해서 빌드 시작
3. 빌드 완료 → jar 파일 생성
4. 현재 WAS에서 실행중인 포트가 어떤 포트(blue)인지 확인
1. 그림내에선 8080 이라고 가정
5. 실행중이지 않은 포트(green) 지정
1. 그림내에선 8081 이라고 가정
6. green에 방금 빌드한 jar파일 실행
1. 젠킨스에서는 실행이 정상적으로 되는지 15초 간격으로 확인
7. 실행이 확인되면 nginx가 바라보는 포트를 green으로 변경해줌
8. blue 포트가 실행중인 PID 확인 후 프로세스 종료
쉘에 쓰이는 콘솔 문법들은 직관적이라 따로 설명은 안할거고 궁금한 사람은 추가적으로 찾아보면 좋을 것 같음.
blue_port = default_port, green_port=secondary_port 젠킨스 환경변수로 저장해뒀음
if curl -s "http://WAS:${blue_port}" > /dev/null
then
deployment_target_port=$green_port
else
deployment_target_port=$blue_port
fi
cd
scp -i 팸키.pem /var/lib/jenkins/workspace/ternoko/backend/build/libs/ternoko-0.0.1-SNAPSHOT.jar ubuntu@WAS:~
export TERM=xterm
ssh -i 팸키.pem -T ubuntu@WAS
ssh -i 팸키.pem ubuntu@WAS ./deploy.sh
WAS내에서 죽어있는 포트가 어디인지 확인하고 BLUE_PORT로 지정한뒤 Jar파일 실행
잘됐는지 아닌지는 문구로 표시했음.
10번 시도했는데 안되면 Fail나면서 실패
for retry_count in $(seq 10)
do
if curl -s "http://WAS:${deployment_target_port}" > /dev/null
then
echo "새로운 포트 ${deployment_target_port}로 잘 올라갔음"
/// 여기서부턴 밑에서 따로 설명할 것
ssh -o StrictHostKeyChecking=no -i key-ternoko.pem -T ubuntu@Nginx
ssh -o StrictHostKeyChecking=no -i key-ternoko.pem ubuntu@Nginx "echo 'set \$service_port ${deployment_target_port};' > /etc/nginx/conf.d/service-port.inc && sudo service nginx reload"
echo "Nginx가 바라보는 포트를 ${deployment_target_port}로 변경"
if [ ${deployment_target_port} -eq default_port ]
then
ssh -i key-ternoko.pem -T ubuntu@WAS
ssh -i key-ternoko.pem ubuntu@WAS sudo kill -9 $(ssh -i key-ternoko.pem ubuntu@WAS sudo lsof -i:secondary_port -t) 2> /dev/null
else
ssh -i key-ternoko.pem -T ubuntu@WAS
ssh -i key-ternoko.pem ubuntu@WAS sudo kill -9 $(ssh -i key-ternoko.pem ubuntu@WAS sudo lsof -i:defualt_port -t) 2> /dev/null
fi
echo "구버전 포트 죽임"
break
fi
/// 여기까지
if [ $retry_count -eq 10 ]
then
echo "아직 새로운 버전 안올라감"
exit 1
fi
echo "15초 후 재시도, 현재까지 $retry_count번 시도함"
sleep 15
done
echo "새로운 포트 ${deployment_target_port}로 잘 올라갔음"
ssh -i 팸키.pem -T ubuntu@Nginx
ssh -i 팸키.pem ubuntu@Nginx "echo 'set \$service_port ${deployment_target_port};' > /etc/nginx/conf.d/service-port.inc && sudo service nginx reload"
echo "Nginx가 바라보는 포트를 ${deployment_target_port}로 변경"
엔진엑스 설정파일임. 여기서는 include로 파일을 부르고 proxy_pass에 파일 내의 변수를 박아주게끔 설정했다.
이건 포트번호 있는 파일. 임의로 고치면 nginx가 보는 포트가 바뀌게 되니까 젠킨스랑 WAS랑 싱크가 안맞을수도 있다.
if [ ${deployment_target_port} -eq defualt_port ]
then
ssh -i 팸키.pem -T ubuntu@WAS
ssh -i 팸키.pem ubuntu@WAS sudo kill -9 $(ssh -i 팸키.pem ubuntu@WAS sudo lsof -i:secondary_port -t) 2> /dev/null
else
ssh -i 팸키.pem -T ubuntu@WAS
ssh -i 팸키.pem ubuntu@WAS sudo kill -9 $(ssh -i 팸키.pem ubuntu@WAS sudo lsof -i:default_port -t) 2> /dev/null
fi
echo "구버전 포트 죽임"
break
됐다ㅎㅅㅎ 실제 Jenkins 에서 출력되는 프린트문이다.
도메인네임으로 접근시 어떤 포트인지 몰라도 되니까 아무 상관 없다.
어차피 도메인네임으로 접근하면 NginX가 알아서 포트맞춰 요청 보내준다.
포트로 접근할때는 sudo lsof-i:default_port
과 sudo lsof-i:secondary_port
로 지금 올라가있는 포트가 어떤 포트인지 확인해야한다.