본문으로 건너뛰기

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를 기다릴 것 입니다.

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

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

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

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

실습에 사용된 코드 설명

로드 밸런서 활성화

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

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

blue-green 배포가 진행되면 1000110002 이 계속 스위칭 됩니다. 어느 포트로 스위칭 되어도 같은 접속 포트로 접속한 이펙트를 위해서 로드 밸런서가 활성화되어야 합니다. 때문에 활성화 되어있지 않으면 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