[Infra] BackEnd Blue-Green 배포

✅ [문제점]

배포되는 과정에서 서비스가 중단되거나 오류가 발생한 경우 정상적으로 동작하지 않음

특히, MSA로 아키텍처를 설계하면 마이크로 서비스가 미들웨어 서버에 등록되는 과정에서 1분간의 딜레이가 발생하여 1분동안 서비스를 이용할 수 없음

=> 무중단 배포 도입

무중단 배포

서비스 장애와 배포의 부담을 최소화하기 위해 운영 중인 서비스를 중단하지 않고 신규 소프트웨어를 배포하는 기술

종류

1. 롤링 배포

  • 사용 중인 인스턴스 내에서 새 버전을 점진적으로 교체하는 것
  • 장점
    • 인스턴스마다 차례로 배포를 진행하기 때문에 상황에 따라 손쉽게 롤백이 가능
    • 많은 서버 자원을 확보하지 않아도 됨
  • 단점
    • 배포 도중 서비스 중인 인스턴스가 줄어들면 각각의 서버가 부담하는 트래픽 양이 증가할 수도 있음
    • 호환성 문제 발생

2. 블루그린 배포

  • 구버전과 동일하게 신버전의 인스턴스를 구성한 후 로드밸런서를 통해 신버전으로 모든 트래픽 전환
  • 장점
    • 호환성 문제가 발생하지 않음
  • 단점
    • 시스템 자원이 두 배로 필요

3. 카나리 배포

  • 소수 인원에 대해서만 트래픽을 신버전으로 옮겨둔 상태에서 서비스를 운영하여 오류를 조기감지
  • 장점
    • 새로운 버전에 대한 위험 최소화
  • 단점
    • 호환성 문제 발생

 

=> EC2 서버가 한 대 임을 고려하여 호환성 문제를 최소화 하고 안정적인 배포를 보장하는 Blue-Green 배포 방식 선정

 

Blue-Green 배포 구현

Jenkins Pipeline 수정

** 이전에 올린 BackEnd Pipeline에서 수정한 내용입니다.

 

1. 현재 서버에 올라간 환경이 Blue인지 Green 인지 파악

	stage('Set Environment') {
            steps {
                script {
                    def psOutput = sh(script: "docker-compose -f docker-compose.blue.yml ps -q gateway-blue", returnStdout: true).trim()
                    curEnv = psOutput != "" ? "blue" : "green"
                    nextEnv = curEnv == "blue" ? "green" : "blue" 
                    nextPort = nextEnv == "blue" ? "8000" : "8001"
                    echo "next: ${nextEnv}"
                    echo "current: ${curEnv}"
                    echo "port: ${nextPort}"
                }
            }
        }

 

 

2. 환경에 따른 다른 yml 파일 download

=> 다른 port 번호로 띄어놓기 위함

	stage('application.yml download') {
            steps {
                dir("./backend/gatewayMS") {
                  withCredentials([file(credentialsId: "application-gateway-${nextEnv}-yml", variable: 'applicationConfigFile')]) {
                        script {
                            if (!fileExists('src/main/resources')) {
                                sh 'mkdir src/main/resources'
                            }
                            sh 'cp $applicationConfigFile src/main/resources/application.yml'
                        }
                    }
                }
            }
        }

 

** yml 파일 예시

server:
  port: 8001
server:
  port: 8000

 

3. 신버전을 서버에 올림

	stage('Deploy Backend') {
            steps {
                script {
                    sh "docker-compose -f docker-compose.${nextEnv}.yml down"
	                  sh "docker-compose -f docker-compose.${nextEnv}.yml up -d --no-deps --build"
                }
            }
        }

 

4. 신버전에 대한 health check 진행

stage('Health Check') {
            steps {
                script {
...
                    while (!success && retries < maxRetries) {
                        try {
                            def healthResponse = sh(script: "curl -s -o /dev/null -w '%{http_code}' -k {url}:${nextPort}/actuator/health", returnStdout: true).trim()
...
                }
            }
        }

 

5. Traffic Switching

  • nginx를 통해 구버전에서 신버전으로 Traffic Switching
  • 각각의 port로 향하는 nginx 파일 2개를 만들고, 해당 파일을 복사해서 원본에 삽입
  • nginx reload 필요
stage('Traffic Switching') {
            steps {
                script {
                  sleep(time: 5, unit: 'SECONDS')
                  sh "docker exec nginx-proxy cp /etc/nginx/vhost.d/{url}/${nextEnv}-{url} /etc/nginx/vhost.d/{url}"
                  sh "docker exec nginx-proxy nginx -s reload"
                  sh "docker-compose -f docker-compose.${curEnv}.yml down"
                }
            }
        }

'Infra' 카테고리의 다른 글

[Infra] SonarQube Jenkins 연동  (0) 2024.05.27
[Infra] Spring Boot Pipeline 구축  (0) 2024.05.25
[Infra] React Pipeline 구축  (0) 2024.05.25
[Infra] Nginx 설정  (0) 2024.05.25
[Infra] Docker-Compose 를 통한 DB 구축  (0) 2024.05.25