본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 23. · 3 Views
카나리 배포와 블루/그린 배포 완벽 가이드
실서비스에서 안전하게 배포하는 두 가지 핵심 전략을 배웁니다. 카나리 배포로 점진적으로 트래픽을 전환하고, 블루/그린 배포로 즉각적인 롤백을 구현하는 방법을 실무 예제와 함께 익혀봅니다.
목차
1. 카나리 배포 개념
어느 날 김개발 씨는 새로 만든 기능을 배포하려다가 큰 장애를 경험했습니다. 모든 사용자에게 한 번에 배포했다가 치명적인 버그가 발견되어 서비스 전체가 마비된 것입니다.
박시니어 씨가 다가와 말했습니다. "카나리 배포를 사용했다면 이런 일은 없었을 거예요."
카나리 배포는 새 버전을 일부 사용자에게만 먼저 배포하여 안정성을 검증하는 전략입니다. 마치 탄광에서 유독가스를 감지하기 위해 카나리아를 먼저 보내던 것처럼, 소수의 트래픽으로 먼저 테스트합니다.
문제가 없으면 점진적으로 모든 사용자에게 확대하고, 문제가 발견되면 즉시 이전 버전으로 되돌립니다.
다음 코드를 살펴봅시다.
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app
ports:
- port: 80
---
# 기존 안정 버전 (90% 트래픽)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-stable
spec:
replicas: 9
selector:
matchLabels:
app: my-app
version: stable
template:
metadata:
labels:
app: my-app
version: stable
spec:
containers:
- name: app
image: my-app:v1.0
---
# 카나리 버전 (10% 트래픽)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-canary
spec:
replicas: 1
selector:
matchLabels:
app: my-app
version: canary
template:
metadata:
labels:
app: my-app
version: canary
spec:
containers:
- name: app
image: my-app:v2.0
김개발 씨는 입사 6개월 차 개발자입니다. 며칠 전 새로운 결제 기능을 개발하여 실서비스에 배포했습니다.
그런데 배포 후 10분 만에 고객센터 전화가 빗발치기 시작했습니다. "결제가 안 돼요!" 알고 보니 특정 카드사 결제에서 오류가 발생하는 치명적인 버그가 있었습니다.
급히 이전 버전으로 롤백했지만, 이미 수백 명의 사용자가 불편을 겪었습니다. 서비스 신뢰도가 떨어지고, 매출에도 손실이 발생했습니다.
박시니어 씨가 김개발 씨를 조용히 불러 앉혔습니다. "이번 일을 계기로 카나리 배포에 대해 배워봅시다.
실무에서는 필수적인 배포 전략이에요." 그렇다면 카나리 배포란 정확히 무엇일까요? 쉽게 비유하자면, 카나리 배포는 마치 신약을 출시하기 전 임상시험을 거치는 것과 같습니다.
처음에는 소수의 자원자에게만 투여하여 부작용을 관찰하고, 안전하다고 판단되면 점차 대상을 늘려가는 것입니다. 이처럼 카나리 배포도 새 버전을 소수의 사용자에게만 먼저 제공하여 안정성을 검증하는 역할을 합니다.
카나리 배포가 없던 시절에는 어땠을까요? 개발자들은 새 버전을 배포할 때마다 전전긍긍했습니다.
테스트 환경에서는 완벽했던 코드가 실서비스에서는 예상치 못한 문제를 일으키는 경우가 많았습니다. 더 큰 문제는 문제가 발견되었을 때 이미 모든 사용자가 영향을 받는다는 점이었습니다.
금요일 저녁 배포는 공포였고, 주말 내내 장애 대응을 해야 하는 일도 잦았습니다. 바로 이런 문제를 해결하기 위해 카나리 배포가 등장했습니다.
카나리 배포를 사용하면 위험을 최소화할 수 있습니다. 새 버전에 문제가 있더라도 소수의 사용자만 영향을 받기 때문에 피해 범위를 제한할 수 있습니다.
또한 실제 사용자 환경에서 검증할 수 있다는 큰 장점이 있습니다. 무엇보다 자신감 있게 배포할 수 있다는 심리적 안정감이 생깁니다.
위의 코드를 한 줄씩 살펴보겠습니다. 먼저 Service 리소스는 app: my-app 레이블을 가진 모든 Pod에 트래픽을 분산합니다.
이 부분이 핵심입니다. version: stable과 version: canary 모두 app: my-app 레이블을 공유하므로, Service는 두 버전 모두에게 트래픽을 보냅니다.
다음으로 my-app-stable Deployment는 replicas: 9로 설정되어 있습니다. 이것은 안정 버전의 Pod 9개를 유지한다는 의미입니다.
my-app-canary Deployment는 replicas: 1로 설정되어 카나리 버전 Pod 1개만 실행됩니다. 결과적으로 전체 10개의 Pod 중 9개는 안정 버전, 1개는 카나리 버전이므로 트래픽이 자연스럽게 9:1 비율로 분산됩니다.
이것이 바로 10%의 트래픽만 새 버전으로 보내는 카나리 배포입니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 대규모 이커머스 서비스를 운영한다고 가정해봅시다. 새로운 추천 알고리즘을 배포하려고 합니다.
먼저 5%의 사용자에게만 새 알고리즘을 적용하고, 전환율과 오류율을 모니터링합니다. 문제가 없다면 50%, 100%로 점진적으로 확대합니다.
쿠팡, 네이버, 카카오 같은 대형 서비스에서 이런 패턴을 적극적으로 사용하고 있습니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 카나리 비율만 설정하고 모니터링을 제대로 하지 않는 것입니다. 이렇게 하면 문제가 발생해도 늦게 발견할 수 있습니다.
따라서 반드시 에러율, 응답 시간, 비즈니스 메트릭을 실시간으로 모니터링해야 합니다. 또 다른 주의사항은 데이터베이스 스키마 변경입니다.
카나리 배포 중에는 두 버전이 동시에 실행되므로, 스키마 변경은 하위 호환성을 유지해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다. "아, 그래서 그랬군요!
처음부터 카나리 배포를 사용했다면 소수의 사용자만 영향을 받았을 텐데요." 카나리 배포를 제대로 이해하면 더 안전하고 자신감 있는 배포가 가능합니다. 여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.
실전 팁
💡 - 처음에는 5-10% 정도의 낮은 비율로 시작하세요
- 에러율, 응답시간, 비즈니스 메트릭을 반드시 모니터링하세요
- 카나리 단계를 너무 빨리 진행하지 말고 충분한 검증 시간을 확보하세요
2. 가중치 기반 트래픽 분할
김개발 씨가 카나리 배포를 적용해보려고 하는데 문제가 생겼습니다. Pod 개수로만 트래픽을 조절하니 원하는 정확한 비율을 맞추기가 어려웠습니다.
"10%가 아니라 15%로 하고 싶은데, Pod를 몇 개로 해야 하지?" 박시니어 씨가 Istio를 소개해주었습니다.
가중치 기반 트래픽 분할은 Service Mesh를 활용하여 정확한 비율로 트래픽을 나누는 기법입니다. Pod 개수가 아닌 설정 값으로 직접 트래픽 비율을 제어할 수 있습니다.
이를 통해 1%부터 99%까지 원하는 정확한 비율로 카나리 배포를 진행할 수 있으며, 실시간으로 비율을 조정할 수도 있습니다.
다음 코드를 살펴봅시다.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-app
spec:
hosts:
- my-app
http:
- match:
- headers:
user-agent:
regex: ".*Mobile.*"
route:
- destination:
host: my-app
subset: canary
weight: 30 # 모바일 사용자의 30%를 카나리로
- destination:
host: my-app
subset: stable
weight: 70
- route:
- destination:
host: my-app
subset: canary
weight: 10 # 일반 트래픽의 10%를 카나리로
- destination:
host: my-app
subset: stable
weight: 90
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: my-app
spec:
host: my-app
subsets:
- name: stable
labels:
version: stable
- name: canary
labels:
version: canary
김개발 씨는 지난주에 배운 카나리 배포를 실제로 적용해보기로 했습니다. 그런데 막상 해보니 생각보다 복잡했습니다.
15%의 트래픽을 카나리로 보내고 싶은데, Pod 개수로는 정확히 맞추기가 어려웠습니다. 20개의 Pod 중 3개를 카나리로 하면 15%인데, 총 Pod 개수가 항상 20개일 수는 없었습니다.
더 큰 문제는 트래픽 비율을 바꾸려면 Deployment를 수정하고 Pod가 재시작되기를 기다려야 한다는 점이었습니다. "좀 더 유연하게 조절할 수 있는 방법은 없을까요?" 김개발 씨가 박시니어 씨에게 물었습니다.
"좋은 질문이에요. 바로 그런 문제를 해결하기 위해 Service Mesh가 있습니다.
Istio나 Linkerd 같은 도구를 사용하면 가중치 기반으로 정확하게 트래픽을 분할할 수 있어요." 그렇다면 가중치 기반 트래픽 분할이란 정확히 무엇일까요? 쉽게 비유하자면, 가중치 기반 트래픽 분할은 마치 교통 신호등과 같습니다.
출퇴근 시간대에는 회사 방향에 더 긴 신호를 주고, 퇴근 시간에는 주거 지역 방향에 더 긴 신호를 주는 것처럼 상황에 맞게 트래픽의 흐름을 조절합니다. 이처럼 Service Mesh도 설정 값으로 정확한 비율을 제어하는 역할을 합니다.
Pod 개수로만 트래픽을 조절하던 시절에는 어땠을까요? 개발자들은 수학 계산에 시간을 많이 써야 했습니다.
"25%를 카나리로 보내려면 Pod를 몇 개로 해야 하지? 아, 4의 배수로 맞춰야 하는구나." Auto Scaling이 활성화되어 있으면 더욱 복잡했습니다.
Pod 개수가 계속 변하는데 원하는 비율을 유지하기가 거의 불가능했습니다. 바로 이런 문제를 해결하기 위해 Service Mesh의 가중치 기반 라우팅이 등장했습니다.
가중치 기반 라우팅을 사용하면 정확한 비율 제어가 가능해집니다. 1%, 15%, 37.5% 등 어떤 비율이든 설정할 수 있습니다.
또한 실시간 조정이 가능하다는 큰 장점이 있습니다. Pod를 재시작하지 않고도 설정 파일만 수정하면 즉시 적용됩니다.
무엇보다 고급 라우팅 규칙을 적용할 수 있다는 점이 강력합니다. 위의 코드를 한 줄씩 살펴보겠습니다.
먼저 VirtualService는 Istio의 핵심 리소스로, 트래픽 라우팅 규칙을 정의합니다. 첫 번째 match 블록은 User-Agent 헤더에 "Mobile"이 포함된 요청을 필터링합니다.
이것이 조건부 라우팅의 핵심입니다. 모바일 사용자의 경우 weight: 30과 weight: 70으로 설정되어 30%는 카나리로, 70%는 안정 버전으로 라우팅됩니다.
두 번째 route 블록은 나머지 모든 트래픽(주로 데스크톱)을 처리하며, 10:90 비율로 분산합니다. DestinationRule은 subset을 정의하여 stable과 canary 버전을 구분합니다.
각 subset은 Pod의 version 레이블로 식별됩니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 음식 배달 앱을 운영한다고 가정해봅시다. 새로운 UI를 배포하는데, 젊은 층은 새로운 디자인을 선호할 것 같습니다.
User-Agent로 모바일 사용자를 필터링하고, 그중에서도 30%에게만 새 UI를 보여줍니다. 데스크톱 사용자는 좀 더 보수적으로 10%만 적용합니다.
토스, 배민, 쿠팡이츠 같은 서비스에서 이런 전략을 자주 사용합니다. 또 다른 활용 사례는 지역별 차등 배포입니다.
특정 region 헤더를 보고 서울 지역 사용자에게만 먼저 배포하거나, VIP 고객에게만 새 기능을 제공할 수도 있습니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 weight 값의 합을 100으로 맞추지 않는 것입니다. weight: 30과 weight: 50으로 설정하면 30:50 비율이 되어 약 37.5%와 62.5%로 분산됩니다.
헷갈리지 않으려면 항상 합계가 100이 되도록 설정하는 것이 좋습니다. 또 다른 주의사항은 Service Mesh를 도입하면 인프라가 복잡해진다는 점입니다.
Istio Sidecar가 모든 Pod에 추가되므로 리소스 사용량이 증가하고, 네트워크 레이턴시도 약간 늘어날 수 있습니다. 따라서 정말 필요한 경우에만 도입해야 합니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 도움으로 Istio를 도입한 김개발 씨는 이제 마음대로 트래픽 비율을 조절할 수 있게 되었습니다.
"와, 정말 편하네요! 설정 파일만 수정하면 바로 적용되다니!" 가중치 기반 트래픽 분할을 제대로 이해하면 훨씬 정교한 카나리 배포가 가능합니다.
여러분도 Service Mesh를 활용해 보세요.
실전 팁
💡 - weight 값의 합계를 항상 100으로 맞추면 비율 계산이 직관적입니다
- 헤더, 쿠키, URL 파라미터 등 다양한 조건으로 라우팅할 수 있습니다
- Istio 대시보드(Kiali)를 사용하면 트래픽 흐름을 시각적으로 확인할 수 있습니다
3. 점진적 롤아웃
김개발 씨는 카나리 배포를 성공적으로 적용했지만, 매번 수동으로 비율을 조정하는 것이 번거로웠습니다. "10%로 30분 돌리고, 문제없으면 50%로 올리고, 또 30분 후에 100%로..." 이 과정을 자동화할 수 없을까요?
박시니어 씨가 Flagger를 소개해주었습니다.
점진적 롤아웃은 카나리 배포를 자동화하여 단계적으로 트래픽을 증가시키는 전략입니다. 설정된 메트릭(에러율, 응답시간 등)을 자동으로 모니터링하며, 정상이면 다음 단계로 진행하고 문제가 발견되면 자동으로 롤백합니다.
개발자가 잠을 자는 동안에도 안전하게 배포가 완료됩니다.
다음 코드를 살펴봅시다.
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: my-app
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
service:
port: 80
analysis:
interval: 1m # 1분마다 체크
threshold: 5 # 5번 연속 성공해야 다음 단계로
maxWeight: 50 # 최대 50%까지만 카나리로
stepWeight: 10 # 10%씩 증가
metrics:
- name: request-success-rate
thresholdRange:
min: 99 # 성공률 99% 이상 유지
interval: 1m
- name: request-duration
thresholdRange:
max: 500 # 응답시간 500ms 이하 유지
interval: 1m
webhooks:
- name: load-test
url: http://flagger-loadtester/
timeout: 5s
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://my-app/"
김개발 씨는 지난 한 달간 카나리 배포를 열심히 해왔습니다. 하지만 문제가 있었습니다.
배포할 때마다 모니터링 대시보드를 계속 지켜봐야 했고, 30분마다 알람을 맞춰놓고 트래픽 비율을 수동으로 올려야 했습니다. 어느 날 저녁 9시에 배포를 시작했는데, 마지막 단계인 100% 배포는 새벽 1시에 해야 했습니다.
"이거 자동으로 할 수 없나요? 제가 잠도 자야 하는데..." 김개발 씨는 지친 목소리로 물었습니다.
박시니어 씨가 웃으며 답했습니다. "당연히 자동화할 수 있죠.
Flagger나 Argo Rollouts 같은 도구를 사용하면 점진적 롤아웃을 완전히 자동화할 수 있어요." 그렇다면 점진적 롤아웃이란 정확히 무엇일까요? 쉽게 비유하자면, 점진적 롤아웃은 마치 자동 온도 조절기와 같습니다.
원하는 온도를 설정하면 현재 온도를 체크하면서 자동으로 난방을 조절합니다. 너무 뜨거우면 난방을 줄이고, 적정 온도를 유지하면 계속 진행합니다.
이처럼 점진적 롤아웃도 메트릭을 모니터링하면서 자동으로 배포를 진행하는 역할을 합니다. 수동으로 카나리 배포를 관리하던 시절에는 어땠을까요?
개발자들은 배포 당번을 정해야 했습니다. 한 명은 모니터링 대시보드를 계속 지켜보고, 일정 시간마다 트래픽 비율을 수동으로 조정했습니다.
심야 배포는 특히 고역이었습니다. 졸음을 참으며 모니터를 지켜보다가 실수로 단계를 건너뛰거나, 문제를 늦게 발견하는 일도 있었습니다.
바로 이런 문제를 해결하기 위해 자동화된 점진적 롤아웃 도구가 등장했습니다. 점진적 롤아웃을 사용하면 완전 자동화가 가능해집니다.
한 번 설정해두면 개발자가 개입하지 않아도 배포가 진행됩니다. 또한 객관적인 판단을 할 수 있다는 큰 장점이 있습니다.
사람은 "이 정도면 괜찮겠지"라고 주관적으로 판단하지만, 자동화는 정확한 메트릭을 기준으로 판단합니다. 무엇보다 24시간 모니터링이 가능하다는 점이 강력합니다.
위의 코드를 한 줄씩 살펴보겠습니다. 먼저 Canary 리소스는 Flagger의 핵심 객체입니다.
targetRef는 배포할 대상 Deployment를 지정합니다. analysis 섹션이 자동화의 핵심입니다.
interval: 1m은 1분마다 메트릭을 체크한다는 의미입니다. threshold: 5는 5번 연속 성공해야 다음 단계로 진행한다는 뜻입니다.
이것이 안전장치 역할을 합니다. 한두 번 성공했다고 바로 진행하지 않습니다.
stepWeight: 10은 한 번에 10%씩 트래픽을 증가시킨다는 의미입니다. 즉, 0% → 10% → 20% → 30% → 40% → 50% 순서로 진행됩니다.
maxWeight: 50으로 설정되어 50%까지만 카나리로 보내고, 성공하면 완전히 교체합니다. metrics 섹션은 어떤 지표를 모니터링할지 정의합니다.
request-success-rate는 99% 이상을 유지해야 하고, request-duration은 500ms 이하를 유지해야 합니다. 하나라도 기준을 벗어나면 즉시 롤백됩니다.
webhooks는 각 단계마다 실행할 작업을 정의합니다. 여기서는 load-test를 실행하여 카나리 버전에 부하를 주고 있습니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 온라인 게임 서비스를 운영한다고 가정해봅시다.
새로운 매치메이킹 알고리즘을 배포하려고 합니다. Flagger를 설정하여 자동 배포를 시작합니다.
시스템은 1분마다 에러율, 응답시간, 매치 성공률을 체크하고, 모든 지표가 정상이면 10%씩 트래픽을 증가시킵니다. 만약 20% 단계에서 매치 실패율이 급증하면 자동으로 0%로 롤백합니다.
개발자는 아침에 출근해서 Slack 알림을 보고 "아, 롤백됐네. 버그를 찾아야겠다"라고 판단하면 됩니다.
밤새 장애 대응을 할 필요가 없습니다. 넷플릭스, 스포티파이 같은 글로벌 서비스에서 이런 자동화 전략을 적극 활용하고 있습니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 threshold를 너무 낮게 설정하는 것입니다.
threshold: 1로 하면 한 번만 성공해도 다음 단계로 넘어가서 위험합니다. 최소 3~5 정도로 설정하는 것이 안전합니다.
또 다른 주의사항은 메트릭 임계값을 너무 빡빡하게 설정하는 것입니다. request-success-rate를 99.9%로 설정하면 아주 작은 오류에도 롤백이 발생하여 배포가 거의 불가능합니다.
현실적인 기준을 설정해야 합니다. 마지막으로 stepWeight를 너무 크게 설정하지 마세요.
stepWeight: 50으로 하면 0% → 50% → 100%로 진행되는데, 이렇게 하면 카나리 배포의 의미가 퇴색됩니다. 10~20% 정도가 적당합니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. Flagger를 설정한 김개발 씨는 이제 배포를 시작하고 퇴근할 수 있게 되었습니다.
"와, 정말 편하네요! 다음 날 아침에 배포 결과만 확인하면 되다니!" 점진적 롤아웃을 제대로 이해하면 안전하고 효율적인 배포 자동화가 가능합니다.
여러분도 Flagger나 Argo Rollouts를 활용해 보세요.
실전 팁
💡 - threshold는 최소 3~5로 설정하여 안정성을 확보하세요
- stepWeight는 10~20% 정도가 적당하며, 중요한 서비스는 더 작게 설정하세요
- Slack이나 PagerDuty와 연동하여 롤백 시 즉시 알림을 받도록 설정하세요
4. 블루/그린 배포
김개발 씨는 점진적 롤아웃으로 배포를 자동화했지만, 또 다른 고민이 생겼습니다. "카나리 배포는 점진적이라 완전히 교체되기까지 시간이 걸려요.
긴급 패치는 즉시 배포하고 싶은데..." 박시니어 씨가 블루/그린 배포를 소개해주었습니다.
블루/그린 배포는 두 개의 동일한 환경을 준비하여 한 번에 전환하는 전략입니다. 기존 버전(블루)과 새 버전(그린)을 모두 실행시킨 후, 검증이 끝나면 트래픽을 한 번에 그린으로 전환합니다.
문제가 있으면 즉시 블루로 되돌릴 수 있어 다운타임이 거의 없습니다. 긴급 패치나 중요한 배포에 적합합니다.
다음 코드를 살펴봅시다.
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app
version: blue # 처음에는 blue 버전으로 트래픽 전송
ports:
- port: 80
---
# Blue (현재 운영 중인 버전)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-blue
spec:
replicas: 3
selector:
matchLabels:
app: my-app
version: blue
template:
metadata:
labels:
app: my-app
version: blue
spec:
containers:
- name: app
image: my-app:v1.0
---
# Green (새로 배포할 버전)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-green
spec:
replicas: 3
selector:
matchLabels:
app: my-app
version: green
template:
metadata:
labels:
app: my-app
version: green
spec:
containers:
- name: app
image: my-app:v2.0
# 전환: kubectl patch service my-app -p '{"spec":{"selector":{"version":"green"}}}'
# 롤백: kubectl patch service my-app -p '{"spec":{"selector":{"version":"blue"}}}'
김개발 씨는 지난주 긴급한 보안 패치를 배포해야 하는 상황을 겪었습니다. SQL Injection 취약점이 발견되어 즉시 수정 버전을 배포해야 했습니다.
하지만 카나리 배포는 점진적으로 진행되어 완전히 교체되기까지 30분 이상 걸렸습니다. "이런 긴급 상황에서는 즉시 배포하고 싶은데, 카나리는 너무 느려요.
그렇다고 한 번에 배포하면 혹시 새로운 버그가 있을 때 위험하고..." 김개발 씨는 딜레마에 빠졌습니다. 박시니어 씨가 화이트보드를 꺼내며 설명을 시작했습니다.
"이럴 때 블루/그린 배포가 완벽한 해결책이에요. 두 버전을 모두 띄워놓고, 새 버전을 충분히 테스트한 후 스위치를 전환하듯이 트래픽을 옮기는 거죠." 그렇다면 블루/그린 배포란 정확히 무엇일까요?
쉽게 비유하자면, 블루/그린 배포는 마치 무대 뒤 리허설과 같습니다. 배우들이 무대 뒤에서 충분히 연습하고 준비가 완료되면, 막을 올려 관객에게 공연을 보여줍니다.
문제가 생기면 즉시 막을 내리고 이전 공연으로 되돌릴 수 있습니다. 이처럼 블루/그린 배포도 새 버전을 미리 준비하고 검증한 후 한 번에 전환하는 역할을 합니다.
한 번에 모든 사용자를 새 버전으로 전환하던 전통적인 방식은 어땠을까요? 개발자들은 배포할 때마다 긴장해야 했습니다.
새 버전을 배포하면 이전 버전은 즉시 종료되므로, 문제가 발견되어도 다시 빌드하고 배포하기까지 시간이 걸렸습니다. 이 시간 동안 서비스는 장애 상태였습니다.
금요일 오후 배포는 절대 금기였습니다. 바로 이런 문제를 해결하기 위해 블루/그린 배포가 등장했습니다.
블루/그린 배포를 사용하면 즉각적인 전환이 가능해집니다. Service의 selector만 변경하면 몇 초 만에 모든 트래픽이 새 버전으로 이동합니다.
또한 즉각적인 롤백도 가능하다는 큰 장점이 있습니다. 문제가 발견되면 다시 selector를 이전 값으로 변경하면 됩니다.
무엇보다 다운타임이 거의 없다는 점이 강력합니다. 위의 코드를 한 줄씩 살펴보겠습니다.
먼저 Service의 selector가 핵심입니다. version: blue로 설정되어 있어서 블루 버전의 Pod로만 트래픽을 보냅니다.
이것이 블루/그린 배포의 스위치 역할을 합니다. my-app-blue Deployment는 현재 운영 중인 안정 버전입니다.
version: blue 레이블로 식별됩니다. my-app-green Deployment는 새로 배포할 버전입니다.
version: green 레이블로 식별됩니다. 핵심은 두 Deployment가 동시에 실행된다는 점입니다.
그린 버전이 완전히 준비되면, kubectl patch 명령으로 Service의 selector를 version: green으로 변경합니다. 이 순간 모든 트래픽이 그린으로 전환됩니다.
만약 문제가 발견되면 다시 kubectl patch 명령으로 selector를 version: blue로 되돌립니다. 블루 버전은 계속 실행 중이므로 즉시 롤백됩니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 금융 서비스를 운영한다고 가정해봅시다.
새로운 송금 로직을 배포하려고 합니다. 이것은 매우 중요한 기능이라 카나리 배포로 천천히 진행하기에는 너무 오래 걸립니다.
먼저 그린 버전을 배포하고, 내부 테스트 계정으로 충분히 검증합니다. QA팀이 그린 버전에 직접 접속하여 모든 시나리오를 테스트합니다.
문제가 없다고 판단되면, 서비스 전환 명령을 실행합니다. 5초 만에 모든 사용자가 새 버전을 사용하게 됩니다.
만약 배포 후 10분 뒤에 미처 발견하지 못한 버그가 나타나도 걱정 없습니다. 즉시 블루로 롤백하면 됩니다.
토스, 카카오뱅크 같은 금융 서비스에서 이런 전략을 많이 사용합니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 리소스 낭비를 고려하지 않는 것입니다. 블루/그린 배포는 두 배의 Pod를 실행하므로 리소스가 2배 필요합니다.
클러스터 용량을 미리 확인해야 합니다. 또 다른 주의사항은 데이터베이스 마이그레이션입니다.
블루와 그린이 동시에 실행되는 짧은 순간 동안, 두 버전이 같은 데이터베이스에 접근할 수 있습니다. 스키마 변경은 반드시 하위 호환성을 유지해야 합니다.
세션 문제도 조심해야 합니다. 블루에서 로그인한 사용자가 그린으로 전환되면 세션이 유지될까요?
세션 저장소(Redis 등)를 공유하지 않으면 모든 사용자가 로그아웃될 수 있습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
블루/그린 배포를 적용한 김개발 씨는 이제 긴급 패치를 자신감 있게 배포할 수 있게 되었습니다. "와, 이제 보안 패치를 5분 안에 배포할 수 있네요!
롤백도 즉시 가능하고!" 블루/그린 배포를 제대로 이해하면 빠르고 안전한 배포가 가능합니다. 여러분도 중요한 배포에 블루/그린 전략을 활용해 보세요.
실전 팁
💡 - 클러스터 리소스가 충분한지 미리 확인하세요 (Pod 수가 2배 필요)
- 전환 전에 그린 버전을 내부 도메인으로 충분히 테스트하세요
- 세션 저장소는 블루/그린이 공유하도록 설정하세요 (Redis 등)
5. 자동화된 롤백
김개발 씨는 블루/그린 배포로 빠른 전환과 롤백이 가능해졌지만, 또 다른 문제를 발견했습니다. "배포 후 10분 뒤에 문제가 발견됐는데, 제가 자리에 없으면 어떡하죠?
시스템이 자동으로 롤백할 수 없나요?" 박시니어 씨가 자동 롤백 설정을 알려주었습니다.
자동화된 롤백은 배포 후 메트릭을 지속적으로 모니터링하여 문제가 감지되면 자동으로 이전 버전으로 되돌리는 기능입니다. 에러율 급증, 응답시간 증가, 비즈니스 메트릭 이상 등을 실시간으로 감지하고, 설정된 임계값을 초과하면 즉시 롤백 명령을 실행합니다.
사람의 개입 없이도 서비스 안정성을 유지할 수 있습니다.
다음 코드를 살펴봅시다.
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: my-app
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
service:
port: 80
analysis:
interval: 30s
threshold: 3
iterations: 10 # 10번 체크 (총 5분)
metrics:
- name: error-rate
templateRef:
name: error-rate
thresholdRange:
max: 1 # 에러율 1% 초과 시 롤백
interval: 30s
- name: latency
templateRef:
name: latency
thresholdRange:
max: 500 # 지연시간 500ms 초과 시 롤백
interval: 30s
alerts:
- name: slack
severity: error
providerRef:
name: slack
namespace: flagger
---
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: error-rate
spec:
provider:
type: prometheus
address: http://prometheus:9090
query: |
100 - (
sum(rate(http_requests_total{status!~"5.*"}[1m]))
/
sum(rate(http_requests_total[1m]))
) * 100
김개발 씨는 어느 금요일 오후 4시에 새 버전을 배포했습니다. 블루/그린 배포로 빠르게 전환했고, 처음 5분간은 모든 것이 정상이었습니다.
김개발 씨는 안심하고 자리를 비웠습니다. 그런데 10분 후, 특정 시나리오에서만 발생하는 버그가 나타나기 시작했습니다.
에러율이 서서히 증가했지만, 김개발 씨는 회의 중이라 모니터링 대시보드를 보지 못했습니다. 20분이 지나자 고객 불만이 쏟아지기 시작했습니다.
"이런 일이 다시는 없어야 해요. 시스템이 자동으로 문제를 감지하고 롤백할 수는 없나요?" 김개발 씨가 박시니어 씨에게 물었습니다.
"물론입니다. 바로 자동 롤백 설정이에요.
Flagger나 Argo Rollouts에서 메트릭 기반 자동 롤백을 설정할 수 있어요." 그렇다면 자동화된 롤백이란 정확히 무엇일까요? 쉽게 비유하자면, 자동화된 롤백은 마치 자동차의 ABS 브레이크와 같습니다.
운전자가 급브레이크를 밟으면 바퀴가 잠기는 것을 감지하여 자동으로 브레이크를 풀었다 밟았다 반복합니다. 운전자가 의식하지 못해도 시스템이 위험을 감지하고 대응합니다.
이처럼 자동 롤백도 서비스 이상을 감지하여 자동으로 안전한 상태로 되돌리는 역할을 합니다. 수동으로 롤백하던 시절에는 어땠을까요?
개발자들은 배포 후 최소 1시간은 모니터링 대시보드를 계속 지켜봐야 했습니다. 에러율, 응답시간, CPU 사용률 등 수십 개의 그래프를 눈으로 확인했습니다.
퇴근 시간이 되어도 집에 갈 수 없었습니다. "혹시 문제가 생기면 어떡하지?" 하는 불안감이 항상 있었습니다.
더 큰 문제는 야간 배포였습니다. 새벽 2시에 배포하고 집에 가서 자는데, 새벽 3시에 문제가 발생하면?
아침에 출근해서야 장애를 발견하는 최악의 상황이 벌어졌습니다. 바로 이런 문제를 해결하기 위해 자동화된 롤백이 등장했습니다.
자동 롤백을 사용하면 무인 모니터링이 가능해집니다. 시스템이 24시간 메트릭을 감시하고 이상이 있으면 즉시 대응합니다.
또한 빠른 대응이 가능하다는 큰 장점이 있습니다. 사람이 감지하는 데 10분 걸리는 것을 시스템은 30초 만에 감지하고 롤백합니다.
무엇보다 객관적인 판단을 한다는 점이 강력합니다. 위의 코드를 한 줄씩 살펴보겠습니다.
먼저 analysis 섹션이 자동 롤백의 핵심입니다. interval: 30s는 30초마다 메트릭을 체크한다는 의미입니다.
threshold: 3은 3번 연속 실패하면 롤백한다는 뜻입니다. 한 번의 일시적인 오류로 롤백하지 않도록 안전장치를 둔 것입니다.
iterations: 10은 총 10번 체크한다는 의미입니다. 30초 × 10 = 5분간 모니터링하고, 모든 체크를 통과하면 배포 성공으로 판단합니다.
하나라도 실패하면 즉시 롤백됩니다. metrics 섹션은 어떤 지표를 감시할지 정의합니다.
error-rate는 에러율을 체크하여 1%를 초과하면 롤백합니다. latency는 응답시간을 체크하여 500ms를 초과하면 롤백합니다.
alerts 섹션은 롤백이 발생했을 때 Slack으로 알림을 보냅니다. 개발자가 자고 있어도 시스템이 자동으로 롤백하고 아침에 확인할 수 있도록 알림을 남깁니다.
MetricTemplate은 Prometheus 쿼리를 정의하여 실제 에러율을 계산합니다. http_requests_total 메트릭에서 5xx 에러가 아닌 요청의 비율을 계산하여 성공률을 산출합니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 대규모 커머스 플랫폼을 운영한다고 가정해봅시다.
블랙프라이데이를 앞두고 새로운 할인 로직을 배포합니다. 평소보다 트래픽이 10배 많은 상황입니다.
자동 롤백을 설정해두었기 때문에 안심하고 배포합니다. 배포 후 1분 만에 특정 상품 카테고리에서 에러가 급증합니다.
Flagger가 이것을 감지하고 30초 후 자동으로 롤백합니다. 전체 장애 시간은 단 1분 30초입니다.
만약 자동 롤백이 없었다면? 개발자가 알람을 확인하고 상황을 파악하고 수동으로 롤백 명령을 내리기까지 최소 5~10분이 걸렸을 것입니다.
블랙프라이데이 같은 중요한 시점에 10분은 엄청난 매출 손실입니다. 아마존, 쿠팡 같은 대형 플랫폼은 모두 자동 롤백 시스템을 갖추고 있습니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 임계값을 너무 민감하게 설정하는 것입니다.
error-rate를 0.1%로 설정하면 아주 작은 오류에도 롤백이 발생하여 배포가 거의 불가능합니다. 서비스 특성에 맞는 현실적인 기준을 찾아야 합니다.
또 다른 주의사항은 threshold를 너무 낮게 설정하는 것입니다. threshold: 1로 하면 한 번의 일시적인 네트워크 오류에도 롤백됩니다.
최소 2~3으로 설정하여 오탐을 줄여야 합니다. 마지막으로 비즈니스 메트릭도 모니터링하세요.
기술적 메트릭(에러율, 응답시간)은 정상인데 비즈니스 메트릭(주문 전환율, 결제 성공률)이 떨어지는 경우도 있습니다. Prometheus에서 커스텀 메트릭을 수집하여 함께 모니터링해야 합니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 자동 롤백을 설정한 김개발 씨는 이제 마음 편하게 배포할 수 있게 되었습니다.
"와, 이제 배포하고 회의에 가도 되겠네요! 시스템이 알아서 롤백해주니까!" 자동화된 롤백을 제대로 이해하면 24시간 안전한 서비스 운영이 가능합니다.
여러분도 메트릭 기반 자동 롤백을 적용해 보세요.
실전 팁
💡 - 임계값은 과거 데이터를 분석하여 현실적인 값으로 설정하세요
- threshold는 최소 2~3으로 설정하여 일시적인 오류에 대응하세요
- 기술 메트릭뿐만 아니라 비즈니스 메트릭도 함께 모니터링하세요
6. 배포 검증
김개발 씨는 자동 롤백까지 설정했지만, 박시니어 씨가 한 가지를 더 조언했습니다. "롤백은 문제가 발생한 후의 대응이에요.
더 좋은 방법은 배포 전에 미리 검증하는 거죠." 배포 검증이란 무엇일까요?
배포 검증은 새 버전이 프로덕션 트래픽을 받기 전에 자동화된 테스트로 검증하는 과정입니다. Smoke Test로 기본 동작을 확인하고, Integration Test로 다른 서비스와의 연동을 검증하며, Load Test로 성능을 확인합니다.
모든 테스트를 통과해야만 실제 사용자 트래픽을 받을 수 있어 사전에 문제를 차단합니다.
다음 코드를 살펴봅시다.
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: my-app
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
service:
port: 80
analysis:
interval: 1m
threshold: 5
iterations: 10
# 배포 전 검증 단계
webhooks:
# 1. Smoke Test - 기본 동작 확인
- name: smoke-test
type: pre-rollout
url: http://test-runner/smoke
timeout: 30s
metadata:
type: bash
cmd: |
# Health check
curl -f http://my-app-canary/health || exit 1
# Basic API test
curl -f http://my-app-canary/api/status || exit 1
# 2. Integration Test - 연동 검증
- name: integration-test
type: pre-rollout
url: http://test-runner/integration
timeout: 5m
metadata:
type: bash
cmd: |
# Database connection
curl -f http://my-app-canary/api/db-check || exit 1
# External API integration
curl -f http://my-app-canary/api/external-check || exit 1
# 3. Load Test - 성능 검증
- name: load-test
url: http://flagger-loadtester/
timeout: 5s
metadata:
type: cmd
cmd: "hey -z 2m -q 100 -c 10 http://my-app-canary/"
# 4. 배포 중 확인 테스트
- name: acceptance-test
type: rollout
url: http://test-runner/acceptance
timeout: 10s
metadata:
type: bash
cmd: |
# 실제 비즈니스 로직 테스트
curl -X POST http://my-app-canary/api/orders -d '{"item":"test"}' || exit 1
김개발 씨는 지난 한 달간 카나리 배포, 블루/그린 배포, 자동 롤백을 모두 적용했습니다. 배포 프로세스가 훨씬 안전해졌습니다.
하지만 여전히 가끔 롤백이 발생했습니다. "왜 자꾸 롤백되는 걸까요?
로컬에서는 다 테스트했는데..." 김개발 씨는 답답했습니다. 문제는 로컬 환경과 프로덕션 환경의 차이였습니다.
로컬에서는 외부 API 연동을 Mock으로 테스트했는데, 실제 환경에서는 네트워크 문제로 실패하는 경우가 있었습니다. 박시니어 씨가 조언했습니다.
"롤백은 문제가 발생한 후의 대응이에요. 더 좋은 방법은 배포 전에 미리 검증하는 거죠.
배포 파이프라인에 자동화된 검증 단계를 추가해봅시다." 그렇다면 배포 검증이란 정확히 무엇일까요? 쉽게 비유하자면, 배포 검증은 마치 비행기 이륙 전 점검과 같습니다.
조종사는 이륙하기 전에 엔진, 연료, 계기판 등 모든 시스템을 점검합니다. 문제가 하나라도 발견되면 이륙을 중단합니다.
이미 이륙한 후에 문제를 발견하면 긴급 착륙해야 하지만, 이륙 전에 발견하면 쉽게 고칠 수 있습니다. 이처럼 배포 검증도 프로덕션 트래픽을 받기 전에 문제를 찾아내는 역할을 합니다.
배포 검증 없이 바로 배포하던 시절에는 어땠을까요? 개발자들은 배포 후에야 문제를 발견했습니다.
"어? 데이터베이스 연결이 안 되네?" "외부 API 타임아웃이 발생하네?" 이런 문제들은 로컬에서는 나타나지 않았지만, 프로덕션 환경에서는 발생했습니다.
롤백하고 다시 고치고 배포하는 과정이 반복되었습니다. 더 큰 문제는 성능 이슈였습니다.
로컬에서는 데이터가 적어서 빨랐는데, 프로덕션에서는 수백만 건의 데이터로 인해 느려지는 경우가 많았습니다. 배포 후 사용자가 "왜 이렇게 느려요?"라고 불만을 제기해야 알 수 있었습니다.
바로 이런 문제를 해결하기 위해 자동화된 배포 검증이 등장했습니다. 배포 검증을 사용하면 사전 차단이 가능해집니다.
문제가 있는 버전은 아예 프로덕션 트래픽을 받지 못하도록 막습니다. 또한 실제 환경에서 테스트할 수 있다는 큰 장점이 있습니다.
카나리 Pod는 프로덕션 환경에 떠 있으므로, 실제 데이터베이스와 연동하고 실제 네트워크를 사용합니다. 무엇보다 자동화로 인한 신뢰성이 강력합니다.
위의 코드를 한 줄씩 살펴보겠습니다. 먼저 webhooks 섹션이 배포 검증의 핵심입니다.
여러 개의 webhook을 정의하여 단계적으로 검증합니다. type: pre-rollout은 카나리 배포가 시작되기 전에 실행되는 테스트입니다.
smoke-test는 가장 기본적인 검증입니다. Health check API를 호출하여 서버가 정상적으로 실행되는지 확인합니다.
만약 서버가 시작 중에 크래시되면 여기서 걸러집니다. integration-test는 외부 의존성을 검증합니다.
데이터베이스 연결, 외부 API 연동 등을 실제로 호출하여 확인합니다. 네트워크 문제, 인증 문제 등을 사전에 발견할 수 있습니다.
load-test는 성능을 검증합니다. hey 도구로 2분간 초당 100개의 요청을 보내어 부하를 줍니다.
응답시간, 에러율, 리소스 사용률 등을 확인합니다. 성능 저하가 발견되면 배포가 중단됩니다.
acceptance-test는 배포 중에 실행되는 테스트입니다. type: rollout으로 설정되어 카나리 단계마다 반복 실행됩니다.
실제 비즈니스 로직을 호출하여 end-to-end로 검증합니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 온라인 쇼핑몰을 운영한다고 가정해봅시다. 새로운 결제 모듈을 배포하려고 합니다.
이것은 매우 중요한 기능이라 철저한 검증이 필요합니다. 먼저 Smoke Test로 결제 서비스가 정상 실행되는지 확인합니다.
Integration Test로 PG사 API와 연동이 되는지 확인합니다. Load Test로 동시 결제 100건을 처리할 수 있는지 확인합니다.
Acceptance Test로 실제 결제 시나리오(카드 등록 → 결제 → 영수증 발급)를 end-to-end로 테스트합니다. 모든 테스트를 통과해야만 카나리 배포가 시작됩니다.
하나라도 실패하면 배포가 중단되고 개발자에게 알림이 갑니다. "Integration Test 실패: PG사 API 타임아웃" 같은 구체적인 에러 메시지를 받아 즉시 수정할 수 있습니다.
네이버페이, 토스페이 같은 결제 서비스는 수십 개의 검증 단계를 거칩니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 테스트를 너무 많이 추가하는 것입니다. 검증 단계가 20개가 넘으면 배포 시간이 너무 길어집니다.
핵심적인 5~7개 정도의 테스트만 추가하는 것이 좋습니다. 또 다른 주의사항은 테스트 데이터 관리입니다.
Acceptance Test에서 실제 주문을 생성하면 프로덕션 데이터베이스에 테스트 데이터가 쌓입니다. 반드시 테스트 후 정리(cleanup)하거나, 테스트 계정을 사용해야 합니다.
마지막으로 timeout을 적절히 설정하세요. timeout: 30s로 설정했는데 테스트가 1분 걸리면 항상 실패합니다.
충분한 여유를 두되, 너무 길게 설정하면 멈춘 테스트를 오래 기다리게 됩니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
배포 검증을 추가한 김개발 씨는 이제 롤백이 거의 발생하지 않게 되었습니다. "와, 이제 문제가 있는 버전은 아예 배포가 안 되네요!
훨씬 안전해졌어요!" 박시니어 씨가 웃으며 말했습니다. "이제 제대로 된 배포 파이프라인이 갖춰졌네요.
카나리 배포, 블루/그린 배포, 자동 롤백, 배포 검증까지. 이 정도면 금요일 오후에도 자신감 있게 배포할 수 있을 거예요." 배포 검증을 제대로 이해하면 문제를 사전에 차단하는 안전한 배포가 가능합니다.
여러분도 자동화된 검증 단계를 추가해 보세요.
실전 팁
💡 - 검증 단계는 5~7개 정도가 적당하며, 우선순위에 따라 선별하세요
- 테스트 데이터는 반드시 cleanup하거나 별도 테스트 계정을 사용하세요
- timeout은 여유 있게 설정하되, 무한정 기다리지 않도록 상한선을 두세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
AWS Certificate Manager로 HTTPS 인증서 발급 완벽 가이드
AWS Certificate Manager를 사용하여 무료로 SSL/TLS 인증서를 발급받고, 로드 밸런서에 적용하여 안전한 HTTPS 웹 서비스를 구축하는 방법을 초급자도 쉽게 따라 할 수 있도록 단계별로 안내합니다.
Route 53으로 도메인 연결 완벽 가이드
AWS Route 53을 사용하여 도메인을 등록하고 실제 서비스에 연결하는 전 과정을 실무 스토리와 함께 쉽게 배워봅니다. DNS의 기본 개념부터 레코드 설정, ELB 연결까지 초급 개발자도 쉽게 따라할 수 있도록 구성했습니다.
AWS RDS 관리형 데이터베이스 완벽 가이드
직접 데이터베이스를 설치하고 관리하는 것이 부담스러운 초급 개발자를 위한 RDS 가이드입니다. 데이터베이스 엔진 선택부터 인스턴스 생성, 보안 설정, 백업까지 실무에 필요한 모든 내용을 다룹니다.
AWS Auto Scaling 완벽 가이드
트래픽 급증에 대비하는 자동 확장 시스템을 단계별로 구축합니다. AMI 생성부터 Auto Scaling Group 설정, 테스트까지 초급 개발자를 위해 실무 중심으로 설명합니다.
AWS 로드 밸런서와 보안 그룹으로 트래픽 분산 구성 완벽 가이드
초급 개발자를 위한 AWS 로드 밸런서와 보안 그룹 실습 가이드입니다. Application Load Balancer와 Network Load Balancer의 차이부터 보안 그룹 설정, 대상 그룹 생성, 실제 EC2 연결까지 실무에 필요한 모든 내용을 이북처럼 술술 읽히는 스타일로 담았습니다.