무중단 배포 실습

hongo·2023년 10월 8일
0

무중단 배포 방식에는 롤링, 블루그린, 카나리 등 여러 방식이 존재한다.

우리 서버는 점진적으로 배포하며 오류를 검증할 필요성을 느끼지 못했기에, 스위칭이 가장 간단한 블루 그린 방식을 적용해보려고 한다.

현재 Nginx를 리버스 프록시 서버로 두고 있으며, Nginx가 오리진 서버에게 요청을 전달하고 있다.

블루그린 배포를 적용하려면, 오리진 서버가 최대 두 개이상 필요하다.

서비스 규모가 적은 나는 새로운 서버 인스턴스를 증설하지 않고, 하나의 인스턴스에 포트를 두 개로 나눠 오리진 서버 cluster로 사용하려고 한다.

블루 그린 배포 시나리오는 다음과 같다.

1.블루 서버와 그린 서버 판별

2.그린 서버에 새로운 버전을 배포

3.그린 서버 헬스 체크

4.Nginx 설정을 통해 블루 서버와 연결을 끊고 그린 서버와 연결

5.블루 서버 종료

블루 서버와 그린 서버 판별

서버가 켜져있다면 블루 서버이고, 꺼져있다면 그린 서버가 된다.

이번 실습에서는 Spring boot actuator를 사용해 서버의 헬스 체크를 수행할 예정이다.

다음과 같이 application.yml에 헬스 체크를 확인하기 위한 엔드포인트를 지정하면, 해당 엔드포인트에서 서버의 on/off여부를 확인할 수 있다.

management:
	endpoints:
		web:
			base-path: /management
			path-mapping:
				health: health_check

디폴트 엔드포인트는 /management로 보안을 위해 엔드포인트를 바꿔주는 것이 좋다.

Spring boot actuator는 단순히 on/off여부를 확인하는 것 외에도 다양한 기능들을 제공하지만 블루그린 배포를 수행하기 위한 최소한의 설정을 해주었다.

Nginx 설정 파일에서 배포할 서버의 포트 스위치

Nginx 설정 파일에서 port.inc파일로 green서버의 port값을 주입하는 방식으로 서버 스위칭을 해보려고 한다.
(물론 upstream 모듈에 오리진 서버를 전부 등록해두면 Nginx가 알아서 켜져 있는 서버에게만 요청을 보내긴 한다. 명확한 게 좋아서 port.inc파일로 proxy_pass를 변경하고 nginx 설정 파일을 reload하게 했다.)

블루 서버 종료

Nginx와 연결된 서버를 블루에서 그린서버로 변경했다면, 블루 서버는 종료시켜줘야한다. 블루 서버가 처리중인 프로세스를 전부 끝내고 종료될 수 있게 application.yml에 graceful 설정을 추가해주자.

SIGKILL 명령어를 날리면 spring boot에서 graceful설정을 해줘도 강제로 프로세스를 종료하게 된다. SIGTERM 명령어를 사용해 블루 서버를 graceful하게 종료한다.

스크립트

위를 바탕으로 작성한 shell 스크립트는 다음과 같다. (bash문법... 아찔하다. if문을 사용할 때 대괄호쓰고 한 칸 띄우는 거 잊지 않기.[ ], =쓸 때 띄우지 않기! ex. RESPONSE=$(...))


spring boot actuator로 지정한 엔드포인트를 사용해서 서버의 헬스체크를 수행한다. 켜져있는 서버의 포트가 블루가 된다.

켜져있는 서버가 없다면, 아직 배포가 되지 않은 초기의 상태로 간주하고 임의로 블루와 그린 포트를 지정해주었다.

앞서 블루의 헬스 체크는 수행했지만, 그린 서버가 꺼져있는 상태인지는 확인하지 않았다. 그린 서버의 체크를 수행해준다.

현재 젠킨스에서 Nginx서버에 git clone명령어를 사용해 jar파일을 가져오고 있다. Nginx서버에 있는 jar파일을 오리진 서버로 복사하고, 실행한다.

그린 서버 헬스 체크를 수행한다. 실행되는 시간을 감안하여 10초 간격으로 총 10번의 헬스체크를 수행했다.

[수정] sudo systemctl restart nginx대신 sudo nginx -s reload를 사용하자. restart는 nginx를 재시작하고, reload는 설정파일만 다시 읽어가기에 비용이 더 적다.

tee명령어를 사용해서 port.inc파일에 그린 서버의 port를 주입한다. nginx설정 파일을 reload한다. (nginx 설정 파일이 유효한 지 검사를 추가하면 더 좋다.ㅎㅎ)

nginx가 reload되었다면 blue port를 종료한다.

추가

  • jenkins 파이프라인 스크립트에서 위에서 작성한 deploy.sh파일 sh 명령어로 실행하면 bash문법을 읽어오지 못한다. bash명령어를 사용해서 실행하자.
  • Nginx를 도커로 띄웠다면, docker exec container_name nginx reload 명령어를 사용해서 nginx을 reload하자. nginx를 띄운 도커 컨테이너 이름을 명시해주는 걸 잊지말자.
profile
https://github.com/hgo641

2개의 댓글

comment-user-thumbnail
2023년 10월 11일

인스턴스 한개에 백엔드 2개 프론트 2개 띄우는 건가요? 인스턴스가 잘 버틸 수 있을지 궁금합니다

1개의 답글