Kubernetes 네트워킹이 Gateway API로 진화하면서 Ingress NGINX에서 Envoy Gateway로 옮기려는 수요가 빠르게 늘고 있습니다. 이 글에서는 “컨트롤러 선택”보다 더 어려운 문제인 컷오버(cutover) 중 트래픽 드롭/인증 장애 같은 운영 리스크를 어떻게 줄일 것인지를 중심으로, 제가 정리한 무중단 전환 전략을 공유합니다.
왜 “무중단 전환”이 생각보다 어려울까요?
무중단 전환을 하려면 보통 다음을 동시에 만족해야 합니다.
- 기존(NGINX)과 신규(Envoy) 이중 운영(dual-run) 을 한다
- 트래픽을 “조금씩” 신규로 옮기며 검증한다
- 문제 발생 시 즉시 롤백할 수 있어야 한다
문제는 여기서 말하는 “조금씩”이 단순히 퍼센트(5% → 20% → 50%) 문제가 아니라는 점입니다. Ingress와 Gateway API는 다음과 같은 디테일에서 동작 차이가 날 수 있습니다.
- 라우팅 매칭/우선순위 규칙 차이
- path rewrite, header 처리 차이
- timeout/keepalive, HTTP/2, gRPC 옵션 차이
- forwarded 헤더(X-Forwarded-*) 및 TLS 종료 지점 변화
즉, 트래픽을 섞을수록 같은 요청이 NGINX에서는 A로, Envoy에서는 B로 처리되는 “의미 불일치” 가능성이 커지고, 그 결과는 특정 경로 404, 일부 사용자만 로그인 루프, 특정 API만 타임아웃 같은 “희귀하지만 치명적인” 형태로 나타납니다.
핵심 관점: “퍼센트 스플릿”이 아니라 “분할 축”을 먼저 정합니다
무중단을 최우선으로 할 때는 이중 운영 기간의 복잡도/검증 비용을 감수하더라도, 최소한 아래 질문에는 답이 있어야 합니다.
- 트래픽을 어떤 축(axis) 으로 나눌 것인가?
- 분할된 트래픽이 세션/캐시/레이트리밋과 충돌하지 않는가?
- 장애 시 어떤 단위로 즉시 되돌릴 수 있는가(rollback granularity)?
제가 선호하는 의사결정 순서는 다음과 같습니다.
- 서비스 단위로 먼저 격리합니다. (가능하면 “서비스 A는 Envoy, 서비스 B는 NGINX”처럼)
- 서비스가 너무 크면, 서비스 내부에서 트래픽 양을 안정적으로 구분할 수 있는 구분자(segment key) 로 다시 쪼갭니다.
- 그 구분자는 “검증 품질”뿐 아니라 “롤백 용이성”까지 함께 결정합니다.
실전에서 제일 깔끔한 분할: Host 기반(하지만 인증이 걸립니다)
대화에서 정리된 결론은 “가능하면 Host 기반이 가장 깔끔하다”였습니다. 이유는 명확합니다.
- 같은 사용자가 같은 Host로 들어오면 세션이 흔들리지 않습니다
- 쿠키/캐시/레이트리밋 정책이 한쪽으로 고정되기 쉽습니다
- 롤백도 Host 라우팅만 되돌리면 되어 되돌리기 경로가 명확합니다
예를 들면 이런 방식입니다.
- 기존:
api.example.com→ Ingress NGINX - 신규 검증용:
api-eg.example.com→ Envoy Gateway - 충분히 검증되면 최종적으로
api.example.com을 Envoy로 전환
하지만 Host 기반 전환은 서비스에서 인증(Authentication) 이 걸리는 순간 난도가 급상승합니다. 흔한 장애 포인트는 다음입니다.
- IdP(OIDC/SAML)의
redirect_uri에 신규 Host를 등록해야 함 - 쿠키 Domain/SameSite 설정 때문에 신규 Host에서 로그인 상태가 유지되지 않음
- 게이트웨이 변경으로
X-Forwarded-Proto,X-Forwarded-Host,Forwarded처리나 TLS 종료 지점이 바뀌어 무한 리다이렉트가 발생
즉, Host 기반이 “운영적으로 가장 안정적”이긴 하지만, “인증이 붙은 서비스”에서는 사전에 인증 체계까지 포함한 마이그레이션 설계가 필요합니다.
서비스가 크다면: “서비스 단위 → 서비스 내부 구분자”로 점진 전환합니다
서비스가 너무 커서 Host를 더 쪼개기 어렵거나, 인증 때문에 Host 추가가 부담된다면 다음 옵션이 현실적인 대안이 됩니다.
- 동일 Host를 유지하고 Path 기반으로 분기(예:
/v2/*만 Envoy) - 동일 Host를 유지하고 Header/Cookie 기반으로 분기(내부 사용자, 특정 테넌트, 특정 사용자군)
다만 Header/Cookie 기반 분기는 다음 단점이 있습니다.
- 분기 누락/실수 가능성이 높고, 디버깅이 어렵습니다
- 트래픽이 섞이면서 “재현이 어려운” 이슈(특정 조건에서만 302 루프 등)가 생길 수 있습니다
그래서 저는 “무중단 최우선”이라면, 가능할수록 서비스 단위 격리 + Host 기반을 기본값으로 두고, 인증 제약이 크면 그때 Path/헤더를 보조 전략으로 택하는 편입니다.
(간단 예시) Host 기반으로 NGINX/Envoy를 공존시키는 형태
아래는 “컨셉”을 보여주는 수준의 예시입니다. 핵심은 한 서비스가 바라보는 백엔드는 같아도, 진입 게이트웨이(데이터플레인)를 Host로 분리하는 것입니다.
# 1) 기존 Host: Ingress NGINX가 처리
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-nginx
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 80
# 2) 신규 Host: Envoy Gateway가 처리 (Gateway API)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-envoy
spec:
parentRefs:
- name: eg-gateway
hostnames:
- api-eg.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: api-svc
port: 80
이 방식의 포인트는 “트래픽을 퍼센트로 섞기”보다, Host 단위로 트래픽 의미를 분리해 검증 품질과 롤백 단순성을 확보하는 것입니다.
인사이트: “무중단”의 비용을 어디까지 감수할까?
처음에 던진 질문으로 돌아가면, 제 결론은 이렇습니다.
- 무중단을 최우선으로 한다면, 전환 기간의 복잡도(이중 운영)와 검증 비용은 ‘되돌리기 단위가 명확해질 때까지’는 감수할 가치가 큽니다.
- 특히 인증/세션이 있는 서비스에서는, 트래픽을 조금씩 섞는 것(퍼센트 스플릿)이 오히려 장애 분석을 어렵게 만들 수 있으니 “어떤 축으로 분할할지”를 먼저 설계하는 편이 안전합니다.
- 결과적으로 “서비스 단위 격리 → 큰 서비스는 구분자 도입 → 가능하면 Host 기반”이 운영 리스크를 가장 잘 줄여줍니다.
마무리
Ingress NGINX에서 Envoy Gateway로의 전환은 ‘무엇을 쓰느냐’보다 ‘어떻게 안전하게 바꾸느냐’가 더 중요합니다. 무중단을 원한다면 퍼센트 트래픽 조절부터 고민하기보다, 서비스/세션/인증/롤백까지 고려한 분할 축 설계부터 잡고 가는 것이 시행착오를 크게 줄여줍니다.
