K8S Envoy Gateway 시리즈 개요: Ingress보다 더 현대적인 트래픽 진입 방식

14 min read

Kubernetes 외부 트래픽을 다뤄본 적이 있다면, 아마 Ingress부터 시작했을 가능성이 큽니다. 잘 동작하고, 많은 시나리오에서는 실제로 그것만으로도 충분합니다. 하지만 요구사항이 더 복잡해지기 시작하면, 예를 들어 여러 listener, 여러 팀의 소유권, gRPC, TCP, TLS passthrough, 세밀한 트래픽 정책 같은 것들이 들어오면 결국 "annotation으로 어떻게든 연명시키기"가 기본 전술이 되는 상황에 빠지게 됩니다. YAML은 주문서처럼 보이기 시작하고, 이를 유지보수하는 사람들은 봉인을 깨는 기분이 들죠.

바로 이 지점에서 Gateway API + Envoy Gateway가 등장합니다. 새로운 도구 세트죠. 이 조합은 일을 더 복잡하게 만드는 게 아니라, 원래 뒤엉켜 있던 책임을 깔끔하게 분리해 줍니다. 그 결과 ingress 트래픽, 라우팅 규칙, TLS 보안 설정, 프로토콜 종류, 팀별 소유 구조를 훨씬 쉽게 이해할 수 있게 됩니다.

정확히 뭐냐고요

한 문장으로 아주 직설적으로 말해보면:

  • Envoy Proxy: 실제로 트래픽을 받아 요청을 전달하는 데이터 플레인, 즉 Gateway Proxy
  • Envoy Gateway: Envoy Proxy를 대신 관리해 주는 컨트롤 플레인
  • Gateway API: Kubernetes에서 트래픽 규칙을 선언할 때 사용하는 표준 인터페이스

이렇게 생각하면 됩니다:

  • Gateway API는 요구사항을 작성하는 곳
  • Envoy Gateway는 번역하고 전달하는 관리자
  • Envoy Proxy는 실제로 문 앞을 지키는 경비원

이렇게 분리되어 있다는 장점은 저수준 Envoy 설정을 직접 손으로 짜지 않아도 되고, 여러 컨트롤러의 비공개 annotation을 외우지 않아도 된다는 점입니다. Kubernetes 리소스를 선언하면, Envoy Gateway가 이를 Envoy Proxy가 실제로 실행할 수 있는 설정으로 번역해 줍니다.

Gateway vs Ingress: 뭐가 다른가요

짧게 답하면: Ingress가 구식이 된 건 아니지만, 더 많은 거버넌스가 필요한 중대형 시스템에는 Gateway API가 더 잘 맞습니다.

비교 항목 Ingress Gateway API
Ingress 모델 보통 ingress와 routing을 하나의 객체에 함께 담음 GatewayClass, Gateway, Route를 분리
표현력 주로 HTTP/HTTPS 중심, 고급 기능은 annotation 의존 여러 Route 타입을 기본 지원하고 필드도 더 명확함
확장 모델 많은 기능이 컨트롤러 전용 비공개 annotation에 의존 표준 필드 기반, 필요 시 CRD로 확장
프로토콜 지원 주로 HTTP/Web 중심 HTTPRoute, GRPCRoute, TCPRoute, TLSRoute 지원
팀 소유권 플랫폼 설정과 앱 설정이 섞이기 쉬움 플랫폼 팀은 ingress, 앱 팀은 route를 관리하기 쉬움
이식성 annotation이 특정 컨트롤러에 묶이는 경우가 많음 더 표준화되어 있고 구현체 간 가독성이 좋음

만약 요구사항이 단순히 아래 정도라면:

  • 단일 웹사이트 또는 간단한 API
  • 기본적인 path/host 라우팅
  • 작은 팀

그렇다면 Ingress도 여전히 괜찮습니다. 하지만 요구사항이 이런 식으로 늘어나기 시작하면:

  • 하나의 ingress가 여러 프로토콜을 제공해야 함
  • 여러 listener, 도메인, 인증서를 다뤄야 함
  • HTTP와 gRPC가 공존해야 함
  • 플랫폼 ingress와 애플리케이션 route 권한을 분리해야 함
  • annotation 희망사항 목록이 아니라 제대로 된 API처럼 읽히는 설정이 필요함

그때부터 Gateway API가 매우 매력적으로 보이기 시작합니다.

왜 그냥 Ingress를 쓰지 않나요

Gateway API의 공식 목표는 규모가 커졌을 때 Ingress가 자주 겪는 몇 가지 고질적인 문제를 해결하는 것입니다:

  • 더 나은 표현력: 라우팅, TLS, 트래픽 정책, 프로토콜 타입이 더 명확하게 정의됨
  • 더 나은 이식성: 컨트롤러 전용 비공개 annotation 의존도를 줄임
  • 더 자연스러운 역할 분리: 플랫폼 팀은 ingress를, 앱 팀은 route를 담당

예를 들어 Ingress 설정은 종종 이렇게 생깁니다:

metadata:
  annotations:
    some.ingress.controller/rewrite-target: /
    some.ingress.controller/auth-type: basic
    some.ingress.controller/ssl-redirect: "true"

동작하지 않는다는 뜻은 아닙니다. 하지만 요구사항이 늘어날수록 annotation은 금방 이해하기 어려운 YAML 흑마법이 됩니다. Gateway API는 이런 요구를 정식 필드로 끌어올립니다. 읽었을 때 "설정"처럼 보이지, "희망사항 목록"처럼 보이지 않죠.

계층 구조

공식 개념 문서는 Envoy Gateway를 세 계층으로 나눠 설명합니다. 머릿속 지도처럼 외워둘 가치가 있습니다:

  • User Configuration: 여러분이 작성하는 Gateway API 리소스와 Envoy Gateway 확장 CRD
  • Envoy Gateway Controller: 이 리소스들을 읽고 실행 가능한 설정으로 번역
  • Envoy Proxy: 실제 라이브 트래픽을 처리하는 데이터 플레인

실무에서는 proxy 인스턴스에 SSH로 들어가 저수준 설정을 만지는 시간보다, 이 "선언적 계층"을 수정하는 시간이 훨씬 많습니다. 이것이 Kubernetes 네이티브 방식의 우아함입니다.

이 시리즈에서 배우게 될 것

이 시리즈는 "일단 돌려보고, 그다음 깊게 들어가기" 순서로 진행합니다. 이 개요를 포함해 총 10편입니다:

  1. 빠른 시작: Envoy Gateway를 설치하고 첫 HTTP 요청을 end-to-end로 통과시켜 보기
  2. 핵심 개념: GatewayClass, Gateway, Listener, Envoy Proxy의 역할 이해하기
  3. 실전 HTTP 라우팅: HTTPRoute를 깊게 파보기. host, path, header, filter, timeout
  4. TLS와 보안: HTTPS 구성, certificateRefs, TLS termination, TLSRoute 이해하기
  5. 모범 사례: 운영 환경에 가기 전에 갖춰야 할 핵심 습관
  6. Route 타입 치트시트: HTTPRoute, GRPCRoute, TCPRoute, TLSRoute 중 무엇을 쓸지 빠르게 판단하기
  7. Listener 설계 가이드: 멀티 포트, 멀티 hostname, 멀티 ingress 설계 패턴
  8. 멀티 네임스페이스와 팀 협업: allowedRoutes, ReferenceGrant, 공유 ingress 거버넌스 마스터하기
  9. 상태와 디버깅 핸드북: Accepted, ResolvedRefs, Programmed를 읽고 가장 짧은 문제 해결 경로 따라가기

Envoy Gateway가 어떤 느낌인지 빨리 체감하고 싶다면 바로 다음 글로 넘어가세요. 모든 용어를 먼저 외우는 것보다 실제로 한 번 띄워보는 편이 낫습니다. 헬스장도 마찬가지죠. 유튜브 30편 보는 것보다 실제로 출석하는 게 더 중요합니다.

자주 만나게 될 핵심 리소스

초보자들이 자주 헷갈리는 이유 중 하나는 Gateway API에 GatewayHTTPRoute만 있다고 생각하기 때문입니다. 실제로는 하나의 리소스군 전체입니다.

GatewayClass

"이 클러스터에서 어떤 Gateway 구현체를 쓸 것인가"를 정의합니다. Envoy Gateway에서는 controllerName이 올바른 컨트롤러를 가리키는지가 핵심입니다.

Gateway

"ingress가 어떤 모습인지"를 정의합니다. 예를 들면 어떤 포트를 열지, 어떤 프로토콜을 들을지, TLS를 어떻게 붙일지, 어떤 route를 허용할지 등이죠.

Listener

ListenerGateway 내부에서 가장 중요한 단위 중 하나입니다. Gateway 바깥으로 노출되는 슬롯이라고 생각하면 됩니다. 각 슬롯은 다음을 정의합니다:

  • port
  • protocol
  • hostname
  • TLS config
  • allowedRoutes

많은 사람이 Gateway를 하나의 블랙박스로 생각하지만, 실제로 ingress 동작을 결정하는 것은 그 안의 각각의 listener입니다.

Route 계열

  • HTTPRoute: HTTP/HTTPS 트래픽, 가장 흔함
  • GRPCRoute: gRPC 트래픽, service/method 기준 매칭 가능
  • TCPRoute: 순수 TCP 트래픽, HTTP 의미를 해석하지 않음
  • TLSRoute: TLS SNI 기준 라우팅, TLS passthrough에서 자주 사용

모든 route의 공통점: 이들은 "문을 여는" 역할이 아니라, "들어온 뒤 어떻게 보낼지"를 결정합니다.

최소한의 사고 모델

머릿속에 이 지도를 넣어두세요:

GatewayClass  # Which Gateway implementation to use in this cluster
Gateway       # Which listeners this ingress opens
Listener      # A port / protocol / hostname / TLS slot
Route         # How to distribute traffic once it enters
Service       # The backend actually serving requests in the cluster
Envoy Proxy   # The data plane that ultimately handles the traffic

가장 단순한 예시는 이렇게 생겼습니다:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: demo
spec:
  parentRefs:
    - name: eg
  hostnames:
    - "www.example.com"
  rules:
    - backendRefs:
        - name: backend
          port: 3000

지금 모든 필드를 외울 필요는 없습니다. 무엇을 하는지만 이해하면 됩니다:

  • parentRefs: 이 규칙이 어느 Gateway에 붙는지
  • hostnames: 어떤 도메인이 이 규칙과 매칭되는지
  • backendRefs: 트래픽을 어느 Service로 보낼지

한눈에 보기: 어떤 Route를 언제 쓸까

요구사항 추천 리소스
웹사이트, REST API, header/path 라우팅 HTTPRoute
gRPC service/method 라우팅 GRPCRoute
순수 TCP 서비스(커스텀 프로토콜 또는 비 HTTP) TCPRoute
end-to-end TLS 유지, Gateway에서 복호화하지 않음 TLSRoute

이 판단표는 실전에서 매우 유용합니다. YAML을 쓰기 전에 먼저 스스로에게 물어보세요:

"내가 다루는 건 HTTP, gRPC, 아니면 raw TCP/TLS 트래픽인가?"

한 줄 요약

Envoy Gateway는 그냥 새로 외워야 하는 용어 하나가 아닙니다. Kubernetes 외부 트래픽을 "그럭저럭 되는 수준"에서 "엔지니어링 시스템처럼 보이는 수준"으로 끌어올리는 방법입니다.

💡 이 스택이 처음이라면 모든 CRD를 한 번에 배우려고 하지 마세요. 먼저 설치하고 첫 요청을 통과시킨 뒤 개념을 다시 보면 훨씬 빨리 흡수됩니다.

다음 단계

다음 글에서는 손을 직접 움직여봅니다. 클러스터에 Envoy Gateway를 설치하고 첫 Gateway + HTTPRoute를 실행해 봅시다: 👉 빠른 시작