- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 들어가며
- 트래픽 분할의 기본 개념
- ingress-nginx 카나리 어노테이션 상세
- Argo Rollouts와 Ingress 연동
- 컨트롤러별 트래픽 분할 방식 비교
- 블루그린 패턴
- 메트릭 기반 자동 승격
- Gateway API의 weight 기반 라우팅
- 함정과 트러블슈팅
- 운영 체크리스트
- 마치며
- 참고 자료
들어가며
새 버전을 프로덕션에 배포하는 일은 언제나 긴장됩니다. 단위 테스트와 통합 테스트를 모두 통과했더라도, 실제 트래픽 앞에서만 드러나는 문제가 분명히 존재하기 때문입니다. 메모리 누수, 특정 클라이언트에서만 재현되는 직렬화 버그, 예상보다 느린 외부 API 응답 같은 것들은 스테이징에서 좀처럼 잡히지 않습니다.
이런 위험을 줄이는 가장 검증된 방법이 바로 점진적 배포입니다. 새 버전에 전체 트래픽의 1퍼센트만 흘려보내고, 지표가 정상인지 확인한 뒤 5퍼센트, 25퍼센트, 50퍼센트로 천천히 늘려가는 카나리(canary) 배포가 대표적입니다. 문제가 발견되면 즉시 0퍼센트로 되돌리면 됩니다. 영향 범위가 작고, 롤백이 빠릅니다.
쿠버네티스 환경에서 이 트래픽 분할을 구현하는 핵심 지점이 바로 Ingress 계층입니다. 클러스터로 들어오는 외부 트래픽이 어느 백엔드로 향할지를 결정하는 곳이기 때문입니다. 이 글에서는 ingress-nginx의 카나리 어노테이션부터 시작해, Argo Rollouts 같은 자동화 도구와의 연동, 컨트롤러별 트래픽 분할 방식의 차이, 블루그린 패턴, 그리고 메트릭 기반 자동 승격까지 실무에서 바로 쓸 수 있는 형태로 정리합니다.
한 가지 중요한 맥락을 먼저 짚고 갑니다. 2026년 현재 Ingress API는 사실상 frozen 상태입니다. 더 이상 새 기능이 추가되지 않으며, 쿠버네티스 네트워킹의 후계 표준은 Gateway API입니다. ingress-nginx 프로젝트 역시 유지보수 모드로 전환되어 주로 보안 패치 중심으로 운영되고 있습니다. 그럼에도 현장에는 여전히 막대한 양의 Ingress 기반 인프라가 돌아가고 있으므로, 기존 자산을 안전하게 운영하면서 Gateway API native 트래픽 분할로 이행하는 양쪽 관점을 모두 다루겠습니다.
트래픽 분할의 기본 개념
트래픽 분할은 동일한 호스트나 경로로 들어온 요청을 여러 백엔드 버전에 나누어 보내는 기법입니다. 크게 두 가지 축으로 나눌 수 있습니다.
첫째는 가중치 기반(weight-based) 분할입니다. 전체 요청 중 일정 비율을 새 버전으로 보냅니다. 예를 들어 90 대 10이라면 열 번 중 한 번꼴로 새 버전이 응답합니다. 무작위 분배이므로 실제 사용자 행동과 무관하게 균등한 샘플을 얻을 수 있습니다.
둘째는 규칙 기반(rule-based) 분할입니다. 특정 헤더, 쿠키, 클라이언트 특성에 따라 라우팅합니다. 예를 들어 내부 직원의 요청에만 베타 버전을 보여주거나, 특정 쿠키를 가진 사용자만 새 UI를 경험하게 하는 식입니다. 이는 가중치 분할보다 통제력이 높지만, 표본이 편향될 수 있다는 단점이 있습니다.
┌─────────────────────┐
사용자 요청 ───────▶ │ Ingress 컨트롤러 │
└──────────┬──────────┘
│ 가중치/헤더/쿠키로 판단
┌────────────┴────────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ stable (v1) │ │ canary (v2) │
│ 90% 트래픽 │ │ 10% 트래픽 │
└─────────────────┘ └─────────────────┘
카나리와 블루그린은 이 트래픽 분할을 활용하는 대표적인 두 가지 전략입니다. 카나리는 비율을 점진적으로 늘려가며 위험을 분산하고, 블루그린은 두 환경을 동시에 띄워두고 한 번에 전환합니다. 각각의 장단점은 글 후반부에서 자세히 비교합니다.
ingress-nginx 카나리 어노테이션 상세
ingress-nginx는 별도의 CRD 없이 어노테이션만으로 카나리 배포를 구현할 수 있습니다. 핵심은 동일한 호스트와 경로를 가진 Ingress를 두 개 만들고, 그중 하나에 카나리 어노테이션을 붙이는 구조입니다.
기본 구조
먼저 안정(stable) 버전을 가리키는 일반 Ingress가 있습니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-stable
namespace: production
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v1
port:
number: 80
그리고 동일한 호스트와 경로를 가지되, 카나리 어노테이션이 붙은 두 번째 Ingress를 추가합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-canary
namespace: production
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v2
port:
number: 80
이렇게 하면 app.example.com으로 들어오는 트래픽의 10퍼센트가 app-v2로, 나머지 90퍼센트가 app-v1로 흘러갑니다. canary-weight 값을 바꾸기만 하면 비율이 즉시 조정됩니다.
canary-by-header 어노테이션
특정 헤더를 가진 요청만 카나리로 보내고 싶을 때 사용합니다. 가중치 기반보다 정밀하게 통제할 수 있어, QA 팀이나 내부 사용자 대상 테스트에 적합합니다.
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "always"
이 설정에서는 X-Canary 헤더 값이 always인 요청만 카나리 백엔드로 향합니다. header-value를 지정하지 않으면 기본값으로 always와 never를 인식하며, always면 카나리로, never면 무조건 안정 버전으로 보냅니다. 헤더 값에 정규식 매칭을 적용하고 싶다면 canary-by-header-pattern 어노테이션을 사용할 수 있습니다.
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "X-Region"
nginx.ingress.kubernetes.io/canary-by-header-pattern: "ap-.*"
canary-by-cookie 어노테이션
쿠키 기반 분할은 한 번 카나리로 라우팅된 사용자가 세션 동안 계속 같은 버전을 경험하도록 만들 때 유용합니다.
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "canary-user"
canary-user라는 이름의 쿠키 값이 always면 카나리로, never면 안정 버전으로 향합니다. 쿠키 값이 없거나 다른 값이면 가중치 규칙으로 폴백합니다.
어노테이션 우선순위
여러 카나리 어노테이션을 동시에 사용할 경우 평가 순서가 정해져 있습니다. 이를 모르면 의도와 다른 라우팅이 발생할 수 있습니다.
| 우선순위 | 어노테이션 | 동작 |
|---|---|---|
| 1 (최우선) | canary-by-header | 헤더 일치 시 즉시 카나리/안정 결정 |
| 2 | canary-by-cookie | 쿠키 값으로 결정 |
| 3 (최후) | canary-weight | 위 규칙에 안 걸리면 가중치로 확률 분배 |
즉 헤더 규칙이 가장 먼저 평가되고, 쿠키, 마지막으로 가중치 순입니다. 헤더로 always가 지정되면 가중치가 0이어도 해당 요청은 카나리로 갑니다. 이 점은 트러블슈팅 시 자주 혼동을 일으키므로 반드시 기억해 두는 것이 좋습니다.
어노테이션 방식의 한계
어노테이션 방식은 설정이 간단하지만 몇 가지 명확한 한계가 있습니다. 가중치를 바꾸려면 매번 Ingress 리소스를 수정하고 적용해야 하므로, 자동화된 점진적 승격에는 부적합합니다. 또한 카나리 Ingress는 동일 호스트/경로당 하나만 허용되므로, 세 개 이상의 버전을 동시에 비교하는 시나리오는 구현할 수 없습니다. 이러한 한계 때문에 실무에서는 Argo Rollouts 같은 도구로 가중치 조정을 자동화하는 경우가 많습니다.
Argo Rollouts와 Ingress 연동
Argo Rollouts는 쿠버네티스의 Deployment를 대체하는 Rollout이라는 CRD를 제공합니다. 가중치를 단계적으로 올리고, 각 단계에서 일시 정지하거나 자동 승격하는 일을 컨트롤러가 알아서 처리합니다. ingress-nginx와 연동하면 앞서 본 canary-weight 어노테이션을 Argo Rollouts가 자동으로 조정해 줍니다.
Rollout CRD 기본 구조
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: app
namespace: production
spec:
replicas: 5
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: registry.example.com/app:v2
ports:
- containerPort: 80
strategy:
canary:
canaryService: app-canary
stableService: app-stable
trafficRouting:
nginx:
stableIngress: app-stable
steps:
- setWeight: 5
- pause: { duration: 5m }
- setWeight: 25
- pause: { duration: 5m }
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100
여기서 핵심은 trafficRouting.nginx.stableIngress 필드입니다. Argo Rollouts는 이 Ingress를 기준으로 카나리 Ingress를 자동 생성하고, steps에 정의된 가중치에 맞춰 canary-weight 어노테이션을 갱신합니다. setWeight 5는 5퍼센트, pause는 해당 시간만큼 대기를 의미합니다. duration 없는 pause는 사람이 수동으로 승격할 때까지 무한 대기합니다.
Service 구성
Rollout이 동작하려면 안정 버전과 카나리 버전을 각각 가리키는 두 개의 Service가 필요합니다.
apiVersion: v1
kind: Service
metadata:
name: app-stable
namespace: production
spec:
selector:
app: app
ports:
- port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: app-canary
namespace: production
spec:
selector:
app: app
ports:
- port: 80
targetPort: 80
Argo Rollouts 컨트롤러는 롤아웃 진행 중에 이 두 Service의 셀렉터를 동적으로 관리하여, 안정 파드와 카나리 파드를 각각 올바른 Service에 연결합니다. 운영자는 Service의 셀렉터를 직접 건드릴 필요가 없습니다.
롤아웃 진행 흐름
배포 시작
│
▼
setWeight 5 ──▶ 카나리 5%, 5분 대기
│
▼
setWeight 25 ──▶ 카나리 25%, 5분 대기
│
▼
setWeight 50 ──▶ 카나리 50%, 10분 대기
│
▼
setWeight 100 ─▶ 전량 카나리, 승격 완료
│
▼
stable로 승격 (이미지 교체 확정)
각 단계에서 문제가 감지되면 kubectl argo rollouts abort 명령으로 즉시 중단하고 가중치를 0으로 되돌릴 수 있습니다.
# 롤아웃 상태 실시간 확인
kubectl argo rollouts get rollout app -n production --watch
# 수동 승격 (pause 단계에서)
kubectl argo rollouts promote app -n production
# 중단 및 롤백
kubectl argo rollouts abort app -n production
컨트롤러별 트래픽 분할 방식 비교
트래픽 분할을 구현하는 방식은 Ingress 컨트롤러마다 상당히 다릅니다. 어노테이션을 쓰는 곳도 있고, 전용 CRD를 쓰는 곳도 있습니다. 마이그레이션이나 멀티 컨트롤러 환경에서 혼동을 막으려면 차이를 정확히 알아야 합니다.
| 컨트롤러 | 분할 방식 | 가중치 | 헤더/쿠키 | 비고 |
|---|---|---|---|---|
| ingress-nginx | 어노테이션 | 지원 | 지원 | 호스트당 카나리 하나 제한 |
| Traefik | weighted services (CRD) | 지원 | 미들웨어로 일부 | IngressRoute 또는 TraefikService 사용 |
| HAProxy Ingress | 어노테이션 | 지원 | 헤더 지원 | blue-green 어노테이션 별도 제공 |
| Contour | HTTPProxy (CRD) | 지원 | 헤더 지원 | weight 필드를 backend에 직접 명시 |
Traefik의 weighted services
Traefik은 어노테이션 대신 TraefikService라는 CRD로 가중치 분할을 표현합니다. 여러 서비스를 묶어 비율을 지정하는 구조입니다.
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: app-split
namespace: production
spec:
weighted:
services:
- name: app-v1
port: 80
weight: 90
- name: app-v2
port: 80
weight: 10
이렇게 정의한 TraefikService를 IngressRoute에서 백엔드로 참조하면, 90 대 10 비율로 트래픽이 나뉩니다. 가중치는 절대값이 아니라 상대 비율로 해석되므로, 합계가 100일 필요는 없습니다.
Contour의 HTTPProxy
Contour는 HTTPProxy CRD에서 backend의 weight 필드를 직접 지정합니다.
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: app
namespace: production
spec:
virtualhost:
fqdn: app.example.com
routes:
- conditions:
- prefix: /
services:
- name: app-v1
port: 80
weight: 90
- name: app-v2
port: 80
weight: 10
Contour 역시 weight를 상대 비율로 처리합니다. 한 가지 주의할 점은, weight를 명시하지 않은 서비스의 기본값이 컨트롤러 구현에 따라 다를 수 있으므로 모든 백엔드에 명시적으로 가중치를 지정하는 것이 안전합니다.
방식 선택 가이드
어노테이션 방식은 진입 장벽이 낮지만 표현력이 제한적입니다. CRD 방식은 더 풍부한 표현이 가능하고 선언적이지만, 별도의 리소스 타입을 학습해야 합니다. 자동화 도구(Argo Rollouts, Flagger)를 도입할 계획이라면, 해당 도구가 어떤 컨트롤러의 어떤 방식을 지원하는지 먼저 확인하는 것이 좋습니다. 그리고 장기적으로는 이 모든 벤더별 방식이 Gateway API의 표준 weight 필드로 수렴하고 있다는 점을 염두에 두어야 합니다.
블루그린 패턴
블루그린은 카나리와 다른 접근입니다. 새 버전(green)을 안정 버전(blue)과 완전히 동일한 규모로 미리 띄워두고, 검증이 끝나면 트래픽을 한 번에 전환합니다. 점진적 비율 조정이 없으므로 전환 순간의 위험이 카나리보다 크지만, 모든 사용자가 항상 일관된 버전을 보게 되며 롤백이 매우 빠르다는 장점이 있습니다.
서비스 스위칭 방식
가장 단순한 블루그린 구현은 Service의 셀렉터를 바꾸는 것입니다.
apiVersion: v1
kind: Service
metadata:
name: app
namespace: production
spec:
selector:
app: app
version: blue
ports:
- port: 80
targetPort: 80
green 환경 검증이 끝나면 셀렉터의 version을 green으로 바꿔 적용하면, Ingress 설정은 그대로 둔 채 백엔드만 즉시 전환됩니다. 롤백이 필요하면 version을 blue로 되돌리기만 하면 됩니다.
Argo Rollouts의 blueGreen 전략
Argo Rollouts는 블루그린도 선언적으로 지원합니다.
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: app
namespace: production
spec:
replicas: 5
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: registry.example.com/app:v2
strategy:
blueGreen:
activeService: app-active
previewService: app-preview
autoPromotionEnabled: false
scaleDownDelaySeconds: 300
activeService는 실제 운영 트래픽을 받는 Service이고, previewService는 새 버전을 미리 검증할 수 있는 별도 Service입니다. autoPromotionEnabled를 false로 두면, preview에서 충분히 검증한 뒤 사람이 수동으로 승격할 때까지 활성 트래픽은 기존 버전을 유지합니다. scaleDownDelaySeconds는 전환 후 이전 버전 파드를 얼마나 유지할지를 정하며, 빠른 롤백을 위해 일정 시간 살려두는 것이 좋습니다.
# preview 검증 후 활성 전환
kubectl argo rollouts promote app -n production
메트릭 기반 자동 승격
수동 승격은 안전하지만 사람의 판단과 대기 시간이 필요합니다. 운영 규모가 커지면 메트릭을 기준으로 자동 승격하거나 자동 롤백하는 체계가 필요해집니다. Argo Rollouts는 AnalysisTemplate으로 이를 지원합니다.
AnalysisTemplate 정의
Prometheus 쿼리로 성공률을 측정하고, 임계값 미달 시 롤아웃을 실패 처리하는 예시입니다.
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
namespace: production
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 1m
count: 5
successCondition: result[0] >= 0.99
failureLimit: 2
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{service="app-canary",status!~"5.."}[2m]))
/
sum(rate(http_requests_total{service="app-canary"}[2m]))
successCondition은 성공률 99퍼센트 이상을 요구합니다. interval은 측정 주기, count는 측정 횟수, failureLimit은 허용하는 실패 횟수입니다. 다섯 번 측정 중 실패가 두 번을 넘으면 롤아웃이 자동으로 중단되고 가중치가 0으로 복귀합니다.
Rollout에 분석 연결
strategy:
canary:
canaryService: app-canary
stableService: app-stable
trafficRouting:
nginx:
stableIngress: app-stable
steps:
- setWeight: 10
- pause: { duration: 5m }
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: app-canary
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100
이제 카나리 10퍼센트 단계 이후 자동으로 성공률 분석이 실행되고, 기준을 만족해야만 다음 단계로 넘어갑니다. 사람의 개입 없이 안전한 점진적 배포가 완성됩니다. Flagger 역시 비슷한 철학으로 메트릭 기반 자동 승격을 제공하므로, GitOps 워크플로에 따라 선택하면 됩니다.
Gateway API의 weight 기반 라우팅
앞서 언급했듯이 Ingress API는 frozen 상태이고, 가중치 기반 트래픽 분할은 Gateway API에서 표준 기능으로 제공됩니다. ingress-nginx의 어노테이션이나 컨트롤러별 CRD가 하던 일을, HTTPRoute의 backendRefs weight 필드 하나로 표준화해 표현할 수 있습니다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app
namespace: production
spec:
parentRefs:
- name: main-gateway
hostnames:
- "app.example.com"
rules:
- backendRefs:
- name: app-v1
port: 80
weight: 90
- name: app-v2
port: 80
weight: 10
이 한 줄짜리 weight 필드가 벤더 종속적인 어노테이션을 대체합니다. Argo Rollouts도 이미 trafficRouting.plugins를 통해 Gateway API를 지원하므로, 자동화된 카나리 워크플로를 표준 API 위에서 구성할 수 있습니다. 신규 프로젝트라면 처음부터 Gateway API 기반으로 설계하는 것을 권장하며, 기존 Ingress 자산은 ingress2gateway 같은 도구로 점진적으로 이행할 수 있습니다.
헤더 기반 분할 역시 Gateway API에서 표준 매처로 표현됩니다.
rules:
- matches:
- headers:
- name: X-Canary
value: "always"
backendRefs:
- name: app-v2
port: 80
- backendRefs:
- name: app-v1
port: 80
함정과 트러블슈팅
실무에서 트래픽 분할을 운영하다 보면 반복적으로 마주치는 함정들이 있습니다. 미리 알아두면 디버깅 시간을 크게 줄일 수 있습니다.
세션 어피니티와 sticky cookie 충돌
ingress-nginx의 세션 어피니티(sticky session) 기능을 켜두면, 클라이언트가 한 번 특정 백엔드에 고정됩니다. 그런데 카나리와 안정 버전이 별개의 Ingress이므로, sticky cookie가 카나리 라우팅과 충돌하면서 가중치가 의도대로 동작하지 않을 수 있습니다. 카나리 테스트 중에는 어피니티 설정을 신중하게 다루고, 가능하면 카나리 기간에는 어피니티를 비활성화하거나 별도의 쿠키 이름을 쓰는 것이 안전합니다.
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "stable-route"
가중치 합계 오해
ingress-nginx의 canary-weight는 0에서 100 사이의 백분율로, 카나리로 보낼 비율을 직접 지정합니다. 반면 Traefik과 Contour의 weight는 상대 비율이라 합계가 100일 필요가 없습니다. 이 차이를 혼동하면 예상과 전혀 다른 분배가 일어납니다. 예를 들어 Contour에서 50과 50으로 설정하면 절반씩 나뉘지만, 같은 의미로 ingress-nginx에 canary-weight 50을 주면 카나리에 50퍼센트만 가고 안정 버전이 50퍼센트를 받는 것은 우연히 같을 뿐, 동작 원리가 다릅니다. 컨트롤러를 바꿀 때 가중치 의미를 반드시 재확인해야 합니다.
canary-weight-total 설정
ingress-nginx는 기본적으로 가중치 총합을 100으로 보지만, canary-weight-total 어노테이션으로 분모를 바꿀 수 있습니다. 더 세밀한 비율(예: 1000분의 5)이 필요할 때 사용합니다.
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "5"
nginx.ingress.kubernetes.io/canary-weight-total: "1000"
이 설정은 1000분의 5, 즉 0.5퍼센트를 카나리로 보냅니다. 매우 낮은 비율의 카나리가 필요한 대규모 트래픽 환경에서 유용합니다.
카나리 Ingress가 무시되는 경우
카나리 Ingress의 호스트와 경로가 안정 Ingress와 정확히 일치하지 않으면 카나리 어노테이션이 무시되고 그냥 별개의 Ingress로 취급됩니다. 호스트, 경로, pathType이 모두 동일한지 반드시 확인해야 합니다. 또한 두 Ingress가 같은 ingressClassName을 가져야 같은 컨트롤러가 처리합니다.
메트릭 지연으로 인한 잘못된 승격
자동 승격 시 Prometheus 스크레이프 간격과 분석 interval이 맞지 않으면, 충분한 데이터가 쌓이기 전에 분석이 통과되어 버릴 수 있습니다. 분석 count와 interval을 스크레이프 주기보다 넉넉하게 잡고, 트래픽이 적은 시간대에는 표본 부족으로 인한 거짓 양성을 경계해야 합니다.
운영 체크리스트
실전 배포 전에 다음 항목을 점검하면 사고를 크게 줄일 수 있습니다.
- 안정/카나리 Service가 각각 올바른 셀렉터로 분리되어 있는가
- 카나리 Ingress의 호스트, 경로, pathType, ingressClassName이 안정 버전과 정확히 일치하는가
- 가중치 어노테이션의 의미(백분율 대 상대비율)를 컨트롤러별로 확인했는가
- 세션 어피니티가 켜져 있다면 카나리 기간 동안의 영향을 검토했는가
- 자동 승격을 쓴다면 AnalysisTemplate의 successCondition과 failureLimit이 적절한가
- Prometheus 쿼리가 카나리 백엔드만 정확히 선택하는가
- 롤백 절차(abort 명령, Service 셀렉터 복구)를 팀이 숙지하고 있는가
- 블루그린이라면 scaleDownDelaySeconds로 이전 버전을 충분히 유지하는가
- 모니터링 대시보드에서 버전별 지표를 분리해 볼 수 있는가
- 장기적으로 Gateway API 이행 계획이 수립되어 있는가
마치며
트래픽 분할은 배포의 위험을 통제 가능한 수준으로 낮추는 가장 실용적인 도구입니다. ingress-nginx의 간단한 어노테이션으로 시작해, Argo Rollouts로 점진적 승격을 자동화하고, 메트릭 기반 분석으로 사람의 개입까지 줄이는 단계적 성숙 경로를 그릴 수 있습니다.
다만 2026년의 현실은, Ingress API가 frozen 상태이고 ingress-nginx가 유지보수 모드로 접어들었다는 점입니다. 기존 자산은 안정적으로 운영하되, 새로운 트래픽 분할 표준은 Gateway API의 weight 기반 라우팅에 있습니다. backendRefs의 weight 필드 하나로 벤더 종속성을 걷어내고, Argo Rollouts의 Gateway API 플러그인으로 동일한 자동화를 표준 위에서 구현할 수 있습니다. 지금 운영 중인 카나리 파이프라인을 점검하면서, 동시에 Gateway API로의 이행 로드맵을 그려두는 것이 현명한 선택입니다.
참고 자료
- ingress-nginx 카나리 어노테이션: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary
- Kubernetes Ingress 공식 문서: https://kubernetes.io/docs/concepts/services-networking/ingress/
- Argo Rollouts 공식 문서: https://argoproj.github.io/argo-rollouts/
- Argo Rollouts nginx 트래픽 라우팅: https://argoproj.github.io/argo-rollouts/features/traffic-management/nginx/
- Argo Rollouts 분석과 자동 승격: https://argoproj.github.io/argo-rollouts/features/analysis/
- Traefik weighted services 문서: https://doc.traefik.io/traefik/routing/services/
- Contour HTTPProxy 문서: https://projectcontour.io/docs/main/config/request-routing/
- Gateway API 트래픽 분할: https://gateway-api.sigs.k8s.io/guides/traffic-splitting/
- Kong Ingress Controller 문서: https://docs.konghq.com/kubernetes-ingress-controller/
- Flagger 진보적 배포 문서: https://flagger.app/