본문으로 건너뛰기

Blue-Green 배포 방법을 이용하여 무중단 배포를 구현해보기 (with docker)

 · reading-time-plural

Blue-Green 배포 방법을 이용하여 무중단 배포를 구현해 보겠습니다.

메커니즘​

로드 밸런서가 blue 컨테이너 와 green 컨테이너 를 로드 밸런싱 합니다.

배포되는 순간 blue 컨테이너 가 활성화 되어있으면 배포해야하는 새로운 파일을 green 컨테이너 로 실행시킵니다. 이 순간에만 blue와 green컨테이너가 up됩니다. 또한, 두개의 컨테이너가 로드 밸런싱이 진행됩니다.

일정 시간이 지난뒤 blue 컨테이너 을 down시킵니다. down 하더라도 이전에 배포된 green 컨테이너 가 up 되어있기 때문에 연결이 중단되지 않습니다. 반대로 green 컨테이너 가 up되어있으면 위의 작업이 반대로 진행됩니다.

소스코드 작성​

info

실습이 진행된 코드는 parkgang/helloworld-docker-blue-green 에서 확인하실 수 있습니다.

deploy.sh​

Travis CI, AWS CodeDeploy, Docker 로 배포 자동화 및 무중단 배포 환경 구축하기 - (2) 글을 참고하여 작성되었습니다.

다만, 다른 점은 docker image를 build후 사용하기 때문에 up할 때 --build 가 추가되어 있습니다.

docker-compose.yml 시리즈​

위의 글을 참고하여 작성되었습니다.

version을 3.3으로 작성해야합니다. docker version 맞게 3.8으로 작성시 오류가 발생합니다.

shell script​

chmod +x ./deploy.sh
./deploy.sh

로드밸런서 구축​

위의 아키텍처 처럼 blue에서 green으로 스위칭 되는 순간 로드밸런싱이 필요합니다.

이전에 포스트 되었던 nginx를 이용해 Load Balancer 구현 해보기 (with docker) 를 응용해서 로드 밸런서 구축하도록 합니다.

/nginx/nginx.conf
user  nginx;
worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
upstream tomcat-project {
# least_conn;
# ip_hash;
# server 52.231.50.84:10001 weight=1 max_fails=1 fail_timeout=1s;
# server 52.231.50.84:10002 weight=1 max_fails=1 fail_timeout=1s;
server 52.231.50.84:10001;
server 52.231.50.84:10002;
}

server {
listen 80;
server_name 52.231.50.84;
location / {
proxy_pass http://tomcat-project;
# port 스위칭 후 사용되지 않는 포트를 구분하기 위해 timeout을 1초로 설정
proxy_connect_timeout 1s;
proxy_send_timeout 1s;
proxy_read_timeout 1s;
send_timeout 1s;
}
}
}

docker in docker volume mount 문제​

로드 밸런서의 기법을 바꾸고 싶으면 어떻게 해야 할까요? 가장 편리한 방법은 config 를 따로 관리하는 것입니다. config 가 변경될 때만 로드 밸런서가 알아서 restart되면 좋겟지만 추가적인 shell 작업이 필요할 겁니다.

때문에 현재 source code는 config 만 따로 관리하는 전략인데 문제는 jenkins가 DinD 형태라 볼륨 마운트가 host로 바인딩되어 git내부로 작성된 config 를 연결할 수가 없습니다.

해결방법은 DinD를 사용하지 않거나 심볼릭 링크를 사용 혹은 image으로 해당 config 를 추가하는 방법이 있습니다. 현재는 비효율적이지만 문서화가 가능하도록 docker-compose를 작성하고 로드 밸런서를 rebuild 할 때마다 image를 생성하도록 되어있습니다.

note

image의 ADD는 현재 컨테이너로 정상적으로 추가가 가능합니다.

다른 우회방법으로 docker-compose를 사용하지 않고 command으로 하는 방법이 존재합니다.
  1. -v 를 docker-compose으로 동일하게 작성하더라도 동작되지 않습니다.
  2. 볼륨 마운트를 jenkins가 host와 볼륨 마운트된 경로에 추가적으로 붙인 형태입니다. \ 가 아닌 / 으로 명시해야합니다.
docker run -d --name test123 -p 80:80 -v C:/Resources/docker/jenkins/jenkins_home/workspace/helloworld-docker-blue-green/nginx/nginx.conf:/etc/nginx/nginx.conf nginx

사용하지 않는 port 스위칭 문제​

10001 (blue)와 10002 (green)포트를 사용합니다.

blue를 컨테이너가 up되면 green 컨테이너는 down됩니다. 하지만 down 되었다고해서 10002 port가 사용이 불가능 하지는 않습니다. 다만 해당 포트로 포워딩 해야 할 자원은 없기 때문에 오랜시간 동안 response를 기다릴 것 입니다.

로드 밸런서에 10001 과 10002 를 로드 밸런싱 하도록 되어있기 때문에 blue-green 배포 시 필연적으로 하나의 port는 제대로된 역할을 못하여 새로고침시 오랜시간동안 기달려야 합니다.

로드 밸런서는 하나의 포트가 사용되지 않더라도 접속은 되기 때문에 요청이 들어올 때 까지 기다리는 것입니다.

정상적인 방법은 아직 찾지 못하였으나 사용하지 않는 포트에 접속할 수 없는 상태코드를 뿌려주는 것이 맞아보입니다.

현재는 conf 에서 timeout이 1초 이상 넘어가면 접속하지 않도록 되어있습니다.

실습에 사용된 코드 설명​

로드 밸런서 활성화​

먼저 로드 밸런서를 활성화 해야합니다.

코드를 살펴보면 실제로 tomcat 컨테이너가 올라가는 port는 10001 (blue)과 10002 (green)입니다.

blue-green 배포가 진행되면 10001 과 10002 이 계속 스위칭 됩니다. 어느 포트로 스위칭 되어도 같은 접속 포트로 접속한 이펙트를 위해서 로드 밸런서가 활성화되어야 합니다. 때문에 활성화 되어있지 않으면 80 (http)으로 접속하더라도 not getway가 출력됩니다.

Webhook​

Webhook으로 jenkins가 trigger되면 chmod +x ./deploy.sh 으로 실행권한을 주고 ./deploy.sh 으로 shell script를 실행합니다.

해당 script가 하는 action는 blue가 up이면 green실행 아니면 반대가 전부입니다.

shellscript에 대한 자세한 설명은 docker-compose,springboot무중단배포 을 참고합니다.

Reference​

  1. 추후, spring으로 무중단 배포시 살펴보기

parkgang