지난 포스팅에서는 AWS EKS 클러스터 위에 서비스를 배포하고, 별도의 라우팅 설정 없이 트래픽이 흐르는 모습을 관찰했다. 당시 Istio 내부 설정이 없어 EKS 내부의 쿠버네티스 서비스는 모든 파드에 트래픽을 균등하게 배분하는 라운드 로빈 방식으로 동작했다.
이번 포스팅에서는 이 기본 모드를 해제하고, 엔지니어가 직접 가중치를 조정해보는 과정을 기록한다. Istio의 VirtualService를 적용하여 트래픽의 비율을 정교하게 제어하는 카나리 배포를 수행하고, 이 통제가 의도대로 이루어지는지 Prometheus와 Grafana를 통해 기술적 근거를 확보해 보겠다.
1. 카나리 배포(Canary Deployment)란?
카나리 배포는 새로운 소프트웨어 버전을 전체 사용자에게 한꺼번에 배포하기 전, 일부 사용자에게만 소량의 트래픽을 노출시켜 안정성을 검증하는 점진적 배포 전략이다.
핵심 메커니즘
- 그룹 분리: 동일한 서비스 이름 아래 기존 버전(v1)과 신규 버전(v2)의 파드를 동시에 운영
- 가중치 제어: 시스템 설정을 통해 트래픽의 비율을 결정
- 지표 분석: Prometheus와 Grafana 같은 모니터링 도구를 사용하여 v2의 성공률, 응답 속도 등을 실시간으로 감시
- 최종 전환 또는 롤백: v2이 안정적이면 가중치를 높여 100%까지 전환하고, 문제가 발견되면 즉시 가중치를 0으로 낮춰 장애 차단
장점
- 리스크의 계량화: 신규 버전에 결함이 있더라도 피해 범위를 설정한 가중치 이내로 한정할 수 있다.
- 데이터 기반 의사결정: 실제 운영 환경에서 수집된 에러율과 지연 시간 데이터를 근거로 배포 지속 여부를 결정한다.
- 무중단 배포: 사용자는 서비스 중단을 경험하지 않으며, 백그라운드에서 조용히 시스템의 세대교체가 일어난다.
EKS와 Istio 환경에서의 구현
- DestinationRule: 파드의 라벨을 기준으로 v1, v2라는 논리적 그룹을 정의한다.
- VirtualService: 각 그룹으로 향할 트래픽의 구체적인 가중치를 명시한다.
2. 카나리 배포 진행 과정
기본 라운드 로빈 방식으로 흐르던 트래픽을 제어하기 위해, 다음과 같은 YAML 파일을 작성했다.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v2
weight: 10
위 YAML 파일을 확인해 보면 DestinationRule에서는 reviews 서비스의 subsets가 v1, v2로만 정의하고 있습니다. 이로 인해 기존 bookinfo.yaml 에 포함되어 있는 v3는 라우팅 대상에서 완전히 제외되어 격리된다.
또한, VirtualService를 통해 정의된 각 subset에 대해 90:10의 가중치로 트래픽을 분리하도록 설정했다.
- 질문: 이미 배포된 서비스에 영향 없이 트래픽 비율만 바꿀 수 있나?
- 답변: 쿠버네티스의 선언적 방식 덕분에 VirtualService 파일에서 weight 필드만 수정하여 apply 하면, 파드 재시작 없이도 Envoy 프락시들이 즉시 새로운 교통 지침을 수행한다.
- 질문: 새로운 서비스는 기존 환경에 영향 없이 어떻게 추가하나?
- 답변: EKS 클러스터에 version: v2 라벨을 가진 파드를 독립적으로 배치한 뒤 Istio의 DestinationRule로 이를 논리적 그룹(Subset)으로 정의하고, 최종적으로 VirtualService를 통해 새 그룹으로 흐를 트래픽 비중을 결정함으로써 기존 환경에 영향 없이 새 버전을 준비시키는 과정이다.
3. 모니터링을 통한 가시성 확보
위와 같은 설정을 통해 실제 productpage에 들어가서 새로고침을 반복해 본 결과, 화면에 나타나는 리뷰의 별점에서 빨간색만 표시되지 않는 것을 확인할 수 있었다. v3 파드는 클러스터 내에 엄연히 존재하지만, DestinationRule의 서브셋 정의와 VirtualService의 라우팅 경로에서 의도적으로 제외했기에 단 한 건의 트래픽도 도달하지 않았음을 실제 화면을 통해 1차적으로 증명한 것이다.
이제 보이지 않는 인프라 하단의 데이터를 Grafana 대시보드로 시각화해 보았다.
SSH 터널링
AWS EKS 환경 내부의 메트릭을 관찰하기 위해 SSH 터널링 기법을 적용했다. istio-manager(EC2)와 내 로컬 PC를 연결하여, 클러스터 내부의 Grafana 대시보드를 내 로컬 PC로 가져왔다. 이후 지표를 분석한 결과 다음과 같다.

- 정교한 트래픽 분산 비율: Incoming Requests By Destination 패널을 보면 reviews-v1은 약 1.5 ops/s를 기록하는 반면, reviews-v2는 0.1~0.2 ops/s 내외의 낮은 수치를 유지하는 것을 보면 위에서 설정한 90:10의 가중치가 인프라 하단에서 정확히 실현되고 있음을 보여준다.
- 시스템 안정성 증명: Incoming Success Rate 지표에서 두 버전 모두 100%의 성공률을 기록하고 있다. 이를 통해 신규 버전인 v2가 실시간 트래픽을 받았음에도 결함 없이 동작하고 있다는 것을 확인했다.
- v3의 완벽한 격리: 대시보드 하단 범례를 확인하면 reviews-v3의 수치는 0에 수렴하여 선조차 보이지 않는 것을 보면 위 라우팅 설정이 v3로 가는 길을 완벽히 차단했음을 증명한다.
다중 가중치 설정을 통한 트래픽 핸들링
카나리 배포가 단순히 두 버전 사이의 전환을 넘어, 여러 버전의 파드에 대해 엔지니어가 의도한 대로 트래픽을 쪼개어 보낼 수 있다는 것을 확인하기 위해, Destination의 subset에 v3를 추가하고 VirtualService의 subset 추가 및 가중치를 v1(60%):v2(30%):v3(10%)으로 설정하고 그 결과를 관찰했다.

- 의도한 비율대로 정렬된 트래픽 곡선: Incoming Requests By Destination 패널을 보면, 가장 높은 위치의 초록색 선(v1), 중간의 노란색 선(v2), 그리고 가장 낮은 파란색 선(v3)이 뚜렷한 층을 이루고 있다. 이는 각 버전에 흐르는 요청 수가 설정한 비율을 정확히 추종하여 계단식 구조를 형성하고 있음을 보여준다.
- 다중 버전의 동시 검증: 이전 단계에서 격리했던 v3까지 포함하여 세 버전을 동시에 운영하면서도, 신규 버전들(v2, v3)에 노출되는 트래픽을 각각 30%와 10%로 차등 제어함으로써 리스크를 분산했다.
- 지표의 일관성: 트래픽 양은 서로 다르지만, Incoming Success Rate 패널에서 세 버전 모두 100%의 성공률을 기록하고 있다. 이는 가중치 변화와 상관없이 전체 시스템이 안정적인 상태를 유지하고 있는 것을 확인할 수 있다.
후기
이번 실습은 AWS EKS와 Istio를 활용해 인프라의 기본 설정을 넘어 엔지니어의 명시적 통제권을 확보하는 과정이었다. VirtualService 가중치 설정을 통해 트래픽 흐름을 직접 설계하고, 해당 결과를 Prometheus/Grafana를 통해 설계가 시스템 하단에 정확히 투영되었음을 확인했다. 다음번에는 단순 배포를 넘어, 지표를 근거로 안정성을 확언할 수 있는 역량을 강화하기 위해 지표 기반 자동 롤백과 조건부 라우팅을 실습하고 결과를 공유할 예정이다.
'코딩 > k8s' 카테고리의 다른 글
| [EKS/Istio] 서비스 메시와 Istio를 활용한 버전 기반 라우팅 실습 (0) | 2026.05.11 |
|---|---|
| [K8s] K8s 환경에서 Python 애플리케이션 모니터링 구축 (0) | 2026.04.16 |
| [K8s] 메모리 고갈로 인한 OOMKilled 테스팅 (0) | 2026.04.06 |
| [K8s] Minikube 환경에서 HPA와 k6로 구현하는 부하 테스트 (0) | 2026.04.02 |
| [Kubernetes] k8s namespace 와 kubectl 명령어 (0) | 2025.11.24 |