트래픽 한 방에 바꾸지 마세요: Ingress NGINX → Envoy Gateway 무중단 전환 전략

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)?

제가 선호하는 의사결정 순서는 다음과 같습니다.

  1. 서비스 단위로 먼저 격리합니다. (가능하면 “서비스 A는 Envoy, 서비스 B는 NGINX”처럼)
  2. 서비스가 너무 크면, 서비스 내부에서 트래픽 양을 안정적으로 구분할 수 있는 구분자(segment key) 로 다시 쪼갭니다.
  3. 그 구분자는 “검증 품질”뿐 아니라 “롤백 용이성”까지 함께 결정합니다.

실전에서 제일 깔끔한 분할: 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로의 전환은 ‘무엇을 쓰느냐’보다 ‘어떻게 안전하게 바꾸느냐’가 더 중요합니다. 무중단을 원한다면 퍼센트 트래픽 조절부터 고민하기보다, 서비스/세션/인증/롤백까지 고려한 분할 축 설계부터 잡고 가는 것이 시행착오를 크게 줄여줍니다.

참고 자료

1 Like