본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] Blue-Green Deployment를 통한 무 중단 모델 교체 프로세스 : 4단계 해결 방법과 차이 분석

by Papa Martino V 2026. 4. 24.
728x90

Blue-Green Deployment
Blue-Green Deployment

 

 

현대 AI 서비스의 가장 큰 과제 중 하나는 '지속적인 통합 및 배포(CI/CD)'입니다. 특히 실시간으로 수만 건의 추론을 처리하는 서비스에서 모델을 업데이트할 때 발생하는 '다운타임(Downtime)'은 비즈니스에 치명적인 손실을 초래합니다. 본 아키텍처 가이드에서는 Python 환경에서 Blue-Green Deployment 전략을 활용하여 사용자에게 중단 없는 서비스를 제공하고, 안정적으로 모델을 교체하는 전문적인 해결 방법을 상세히 다룹니다.


1. Blue-Green Deployment의 핵심 개념 및 기술적 차이

Blue-Green Deployment는 동일한 환경의 두 세트(Blue와 Green)를 유지하는 방식입니다. 구 버전(Blue)이 구동 중인 상태에서 신 버전(Green)을 완벽하게 준비한 후, 트래픽의 통로를 일시에 변경함으로써 장애 리스크를 최소화합니다.

배포 전략별 상세 비교 분석

항목 In-place Deployment Rolling Deployment Blue-Green Deployment
기본 개념 기존 서버 내에서 소스 교체 순차적으로 하나씩 교체 동일한 별도 환경 구축 후 교체
무중단 여부 중단 발생 (Downtime) 무중단 가능 완벽한 무중단 보장
롤백 속도 매우 느림 (복구 필요) 보통 (순차적 롤백) 즉시 가능 (스위칭)
리소스 비용 낮음 중간 높음 (2배 인프라 필요)
테스트 환경 운영 서버 직접 테스트 일부 사용자 대상 테스트 완전 격리된 실제 환경 테스트

2. 실무 적용을 위한 Python 기반 모델 배포 7가지 솔루션

현업 개발자가 실제 인프라 및 애플리케이션 레벨에서 즉시 적용 가능한 Python 기반의 시나리오별 구현 예시입니다.

Example 1: Flask와 Nginx를 활용한 트래픽 스위칭 (Nginx Upstream 변경)

Nginx를 리버스 프록시로 두고, Python 백엔드의 포트를 변경하여 트래픽을 전환하는 가장 고전적이면서 강력한 방법입니다.


# Blue 인스턴스 (Port 5000) 구동
# Green 인스턴스 (Port 5001) 구동 후 헬스 체크 완료 가정

import subprocess

def switch_to_green():
    nginx_config = """
    upstream ai_service {
        server 127.0.0.1:5001; # Green 환경으로 변경
    }
    """
    with open("/etc/nginx/conf.d/service.conf", "w") as f:
        f.write(nginx_config)
    
    # Nginx 재로드로 무중단 적용
    subprocess.run(["sudo", "nginx", "-s", "reload"])
    print("Traffic successfully switched to Green (Port 5001)")
    

Example 2: Redis를 활용한 Dynamic Router 구현

코드 레벨에서 Redis의 플래그를 확인하여 요청을 동적으로 전달하는 방식입니다.


import redis
import requests
from flask import Flask, request

app = Flask(__name__)
r = redis.Redis(host='localhost', port=6379, db=0)

BLUE_URL = "http://10.0.0.1:8000/predict"
GREEN_URL = "http://10.0.0.2:8000/predict"

@app.route('/proxy', methods=['POST'])
def proxy_inference():
    # Redis에서 현재 활성화된 컬러를 가져옴
    active_env = r.get("active_env").decode('utf-8')
    target_url = GREEN_URL if active_env == "green" else BLUE_URL
    
    response = requests.post(target_url, json=request.json)
    return response.content, response.status_code
    

Example 3: Kubernetes Python SDK를 통한 Service Selector 업데이트

K8s 환경에서 Python 스크립트를 통해 서비스의 셀렉터를 'version: v2'로 일괄 변경합니다.


from kubernetes import client, config

def update_k8s_selector(target_version="v2"):
    config.load_kube_config()
    v1 = client.CoreV1Api()
    
    body = {
        "spec": {
            "selector": {
                "app": "ai-model",
                "version": target_version
            }
        }
    }
    
    v1.patch_namespaced_service(name="ai-service", namespace="default", body=body)
    print(f"Kubernetes Service selector updated to {target_version}")
    

Example 4: MLflow Model Registry를 이용한 단계별 배포 (Stage 전환)

MLflow API를 사용하여 모델의 스테이지를 Production으로 전환하는 자동화 코드입니다.


import mlflow.pyfunc
from mlflow.tracking import MlflowClient

client = MlflowClient()

def promote_model_to_production(model_name, version):
    # 기존 Production 모델을 Archived로 변경 (Blue)
    # 새 모델을 Production으로 격상 (Green)
    client.transition_model_version_stage(
        name=model_name,
        version=version,
        stage="Production",
        archive_existing_versions=True
    )
    print(f"Model {model_name} version {version} is now in Production")
    

Example 5: PyTorch 모델 무중단 핫로딩 (Hot-Reloading Wrapper)

메모리 내에서 모델 객체만 교체하는 초저지연 배포 방식입니다.


import torch
import threading

class ModelServer:
    def __init__(self, path):
        self.model = torch.load(path)
        self.lock = threading.Lock()

    def update_model(self, new_path):
        new_model = torch.load(new_path)
        with self.lock:
            self.model = new_model  # 원자적 교체
        print("Model object swapped in memory")

    def predict(self, input_data):
        with self.lock:
            return self.model(input_data)
    

Example 6: AWS SDK (Boto3)를 활용한 ALB Target Group 전환

AWS 클라우드 환경에서 Python으로 로드밸런서의 가중치를 변경합니다.


import boto3

def switch_alb_weight(listener_arn, blue_tg, green_tg):
    elbv2 = boto3.client('elbv2')
    elbv2.modify_listener(
        ListenerArn=listener_arn,
        DefaultActions=[{
            'Type': 'forward',
            'ForwardConfig': {
                'TargetGroups': [
                    {'TargetGroupArn': blue_tg, 'Weight': 0},
                    {'TargetGroupArn': green_tg, 'Weight': 100}
                ]
            }
        }]
    )
    

Example 7: 사전 상태 검증을 위한 자동화 테스트 스크립트

Green 환경으로 트래픽을 넘기기 전, Python의 `pytest`를 활용한 최종 무결성 검사입니다.


import requests

def test_green_readiness():
    green_url = "http://green-service-internal/health"
    response = requests.get(green_url)
    
    assert response.status_code == 200
    assert response.json()['status'] == "ready"
    
    # 추론 결과값 유효성 테스트
    predict_res = requests.post("http://green-service-internal/predict", json={"data": [1,2,3]})
    assert "prediction" in predict_res.json()
    print("Green Environment Readiness Test Passed")
    

3. 안정적인 모델 교체를 위한 아키텍처 해결 전략

성공적인 Blue-Green 배포를 위해 반드시 해결해야 할 세 가지 핵심 과제가 있습니다.

  1. 데이터 무결성: 새로운 모델이 새로운 피처 엔지니어링 방식을 사용한다면, DB 스키마나 캐시 레이어에서도 호환성을 유지해야 합니다.
  2. 세션 유지: 트래픽 전환 시 기존 진행 중인 추론 요청이 끊기지 않도록 'Graceful Shutdown' 처리가 필요합니다.
  3. 모니터링: 스위칭 직후 에러율(Error Rate)이나 추론 지연 시간(Latency)이 급증할 경우 자동으로 Blue 환경으로 롤백하는 메커니즘을 갖춰야 합니다.

4. 결론 및 향후 전망

Blue-Green Deployment는 리소스 비용이 발생하지만, 서비스의 신뢰성을 극한으로 끌어올릴 수 있는 가장 확실한 방법입니다. 특히 최근의 MLOps 환경에서는 인프라의 자동화가 가속화됨에 따라 Python 스크립트 하나로 전체 배포 과정을 제어하는 능력이 데이터 엔지니어 및 백엔드 개발자의 필수 역량이 되고 있습니다.


출처 및 참고문헌

  • Martin Fowler, "BlueGreenDeployment" (martinfowler.com)
  • Kubernetes Documentation: "Deployment Strategies"
  • MLflow Guide: "Model Registry and Deployment"
  • AWS Whitepapers: "Continuous Delivery on AWS"
728x90