K8s Networking - 09. gateway-api
Ingress의 뒤를 잇다 — Gateway API가 역할 분리로 푸는 문제
2024년 ingress-nginx에서 치명적 CVE(CVE-2025-1974)가 발견됐다 — 컨트롤 플레인 컴포넌트가 임의 코드 실행까지 허용할 수 있는 구멍이었다. 동시에 ingress-nginx의 유지보수 부담이 오랜 이슈로 떠올랐다. 커뮤니티는 한 방향으로 수렴했다: 단순히 패치를 넘어, L7 진입의 다음 세대 API인 Gateway API로의 전환. 한 팀은 이를 기회 삼아, 수백 줄의 nginx annotation을 표준 API로 재작성했다 — 더 이상 nginx 전용이 아닌, 어느 구현체든 해석하는 매니페스트로.
이 글이 푸는 것은: Gateway API가 Ingress의 어떤 근본 한계를 어떻게 해결하는가, 그리고 왜 "Ingress 다음"인가다. nginx ingress EOL 컨텍스트가 이 글의 중심이다.
Ingress 한계의 핵심 — 역할 분리가 없다
08장에서 Ingress의 표현력 한계(annotation 지옥)를 봤다. 그런데 진짜 근본 한계는 역할 분리(role separation)가 없다는 것이다.
실제 L7 인프라엔 두 역할이 있다:
- 인프라 담당(플랫폼 팀): "이 클러스터에 외부 진입점(도메인, TLS, 외부 IP)을 세팅한다."
- 앱 담당(개발 팀): "내 앱으로 오는 트래픽은 이 경로 규칙을 따른다."
Ingress API엔 이 분리가 없다 — 하나의 Ingress 객체에 도메인/TLS(인프라)와 경로 라우팅(앱)이 뒤섞인다. 그래서 개발팀이 Ingress를 고치려 할 때 인프라 속성(TLS, 도메인)까지 만질 수 있게 되거나, 반대로 인프라팀이 매번 개발팀의 경로 규칙을 대신 고쳐줘야 한다. 책임 경계가 객체 단위로 안 나뉜 것이다.
Gateway API의 답 — 객체를 쪼개서 역할을 분리한다
Gateway API는 이 분리를 객체를 쪼개서 해결한다. 인프라가 소유할 객체와 앱이 소유할 객체를 아예 분리해, 각 팀이 자기 객체만 다루게 한다. (Gateway API 공식 문서)
flowchart TD
GC["GatewayClass<br/>(인프라: '이 종류의 게이트웨이')"] --> G["Gateway<br/>(인프라: 도메인/TLS/리스너)"]
G -. 청취 .-> R["HTTPRoute<br/>(앱: 경로/헤더 규칙)"]
R --> SVC["Service: backend"]
R2["HTTPRoute (다른 앱)"] -. 같은 Gateway .-> G
- GatewayClass: "어떤 구현체(contour, envoy-gateway, nginx-gateway-fabric 등)가 이 종류의 Gateway를 구현하나". IngressClass와 비슷.
- Gateway: 실제 진입점 — 리스너(포트, 호스트, TLS). 인프라 팀이 소유.
- HTTPRoute(및 TCPRoute/GRPCRoute/UDPRoute): 라우팅 규칙 — 경로, 헤더, 가중치. 앱 팀이 소유. 하나의 Gateway에 여러 Route가 붙을 수 있다.
# Kubernetes 1.36 — Gateway (인프라 팀 소유)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata: {name: edge}
spec:
gatewayClassName: envoy-gateway
listeners:
- name: https
port: 443
protocol: HTTPS
hostname: app.example.com
tls: {mode: Terminate, certificateRefs: [{name: app-tls}]}
# HTTPRoute (앱 팀 소유) — 표준 API로 헤더/가중치 표현
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata: {name: app-routes}
spec:
parentRefs: [{name: edge}]
hostnames: [app.example.com]
rules:
- matches: [{path: {type: PathPrefix, value: /api}}]
backendRefs: [{name: backend, port: 80}]
- matches: [{path: {type: PathPrefix, value: /}}]
backendRefs: [{name: frontend, port: 80}]
- matches: [{headers: [{name: X-Canary, value: "true"}]}] # 헤더 기반 — 표준!
backendRefs: [{name: canary, port: 80}]
핵심: 헤더 매칭이 표준 API에 있다. 08장의 annotation이 아니다. 이 매니페스트는 envoy-gateway든 nginx-gateway-fabric이든 표준 API로 해석 — 이식성이 살아난다.
RBAC으로 역할 분리를 강제한다 — 객체가 나뉘었으니 권한도 나뉜다
객체가 나뉘었으니 RBAC으로 권한도 나뉜다:
- 인프라 팀: Gateway/GatewayClass 쓰기 권한.
- 앱 팀: HTTPRoute만 쓰기 권한. Gateway는 참조만(
parentRefs).
flowchart TD
INFRA["인프라 팀<br/>(Gateway, GatewayClass 쓰기)"] --> G["Gateway: 도메인/TLS/리스너"]
APP1["앱팀 A<br/>(HTTPRoute만 쓰기)"] --> R1["HTTPRoute: /api 규칙"]
APP2["앱팀 B<br/>(HTTPRoute만 쓰기)"] --> R2["HTTPRoute: /billing 규칙"]
R1 -->|parentRefs| G
R2 -->|parentRefs| G
개발팀은 HTTPRoute로 자기 경로 규칙을 고치되, 인프라 속성(Gateway의 TLS/도메인)엔 손 못 댄다. 이것이 Ingress가 못 한 역할 분리의 강제*다 — Ingress 객체에 도메인/TLS(인프라)와 경로(앱)가 뒤섞여, 한 객체를 고치려면 양쪽 권한이 다 필요했다. Gateway API가 객체를 쪼갬으로써 RBAC 분리가 *구조적으로 강제된다.
HTTPRoute가 Gateway에 붙는 조건 — parentRefs와 attachment
HTTPRoute가 parentRefs로 Gateway를 가리키지만, 무조건 붙는 게 아니다. Gateway 쪽이 "이 Route를 받을지"를 제어:
- Gateway의 리스너가 해당 호스트네임을 허용하는가?
- Route의 namespace가 Gateway의 허용 범위(
allowedRoutes)에 있는가?
이 attachment 모델이 인프라 팀에게 "어느 Route를 내 Gateway에 붙일지" 통제권을 준다. 무분별한 Route 부착을 막는 구조적 장치다.
Ingress 한계, Gateway API의 답 — 요약
| Ingress 한계 | Gateway API 해결 |
|---|---|
| 역할 분리 없음 | GatewayClass/Gateway(인프라) ↔ Route(앱) 객체 분리 + RBAC |
| 구현체 종속(annotation) | 표준 API(헤더/가중치/L7) |
| HTTP 중심 | HTTP/TCP/UDP/gRPC Route 타입 |
| 서비스 메시 미지원 | GAMMA initiative(메시 통합) |
nginx ingress EOL 컨텍스트 — 왜 지금 Gateway API로
CVE-2025-1974와 ingress-nginx의 유지보수 부담이 겹치며, 커뮤니티는 신규 L7 설계를 Gateway API 기준으로 잡는다. 구체적 EOL 일자/버전은 ingress-nginx 공식 발표로 매번 확인해야 한다(추측 금지). 핵심 방향:
- nginx-gateway-fabric: NGINX사가 Gateway API 구현체로 제공. ingress-nginx(커뮤니티)와 다름.
- envoy-gateway, Contour, Cilium Gateway 등: Gateway API 구현체 다수. 이식성이 살아난다.
중요: Gateway API가 Ingress를 즉시 대체하는 게 아니다. Ingress는 여전히 동작하고 널리 쓰인다. 다만 *신규 설계와 *이식성 중시 환경에서 Gateway API가 기준이 되는 흐름. 점진적 전환이 현실적 패턴.
TLS의 세 모드 — Terminate, Passthrough, Reencrypt
Gateway API가 TLS를 다루는 세 방식:
| 모드 | 동작 | 용도 |
|---|---|---|
| Terminate | Gateway가 TLS 종단, 백엔드엔 HTTP | 일반적. 인증서 관리 한 곳 |
| Passthrough | TLS 그대로 백엔드까지 (SNI만 라우팅) | 백엔드가 자체 인증서로 종단 (mTLS 등) |
| Reencrypt | Gateway가 종단 후 백엔드와 다시 TLS | 백엔드까지 암호화 유지하되 Gateway도 검사 |
Terminate가 가장 흔하다(인증서 관리 집중). 단 백엔드까지 평문이 흐르므로, 메시 내부가 아닌 환경에선 Reencrypt로 백엔드까지 암호화. Passthrough는 Gateway가 L7 검사를 못 하는 대신 백엔드 자체 인증서가 필요한 경우(자체 mTLS 서비스). 08장의 Ingress Terminate/Passthrough와 같은 축이지만, Reencrypt가 추가된다.
GAMMA — 외부 진입과 메시가 같은 API로
지금까지 외부 진입(Ingress/Gateway API)과 내부 메시(Istio VirtualService)는 서로 다른 API로 따로 관리해야 했다. *GAMMA**(Gateway API for Mesh Management Administration) initiative는 이 분리를 없앤다 — Gateway API 규칙이 *메시 데이터플레인(Istio/Cilium)에서도 같은 의미로 동작하게 한다. (GAMMA initiative)
구체적 예:
- 외부: 사용자 → Gateway → Service A (Gateway API HTTPRoute).
- 메시 내부: Service A → Service B 호출도 같은 HTTPRoute 규칙으로 제어(GAMMA).
이것이 "외부 진입"과 "메시 내부"가 하나의 API 모델로 통합된다는 의미다. Ingress(외부)와 Istio VirtualService(내부)가 다른 API였던 과거와 대비. GAMMA가 성숙하면 하나의 HTTPRoute로 외부/내부 트래픽을 모두 표현할 수 있게 된다. 이것이 10/11장(서비스 메시)과의 연결점이다.
GAMMA는 아직 발전 중(initiative). 정확한 GA 상태와 지원 범위는 Gateway API GAMMA 실측. 단 방향은 명확 — Ingress와 메시의 API 통합.
Ingress에서 Gateway API로의 마이그레이션
전환이 점진적이어야 하는 이유:
- 공존: 한 클러스터에 Ingress와 Gateway API가 함께. 새 서비스는 Gateway API로, 기존은 Ingress로.
- 구현체 지원: 사용 중인 Ingress Controller가 Gateway API도 지원하는지(많은 최신 컨트롤러가 둘 다).
- annotation 변환: 기존 Ingress의 nginx annotation을 Gateway API 표준 필드로 재작성 — 이게 공들인 부분.
- 트래픽 전환: 한 도메인씩 Ingress → Gateway로 점진 이동. 전체 한 번에 바꾸면 위험.
직접 확인하기
# Kubernetes 1.36 — Gateway API CRD 설치 (표준 채널)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
# (버전은 실측 시점 최신 GA로, 문서에 명시)
kubectl get gatewayclass
실제 Gateway/HTTPRoute 동작은 구현체(envoy-gateway, Cilium 등) 설치 필요.
k8s-verify스킬 참조.
# 구현체 없이 CRD만 설치해 객체 생성은 가능(단, 실제 라우팅은 안 됨)
kubectl apply -f - <<'EOF'
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata: {name: demo}
spec:
parentRefs: [{name: edge}]
hostnames: [app.example.com]
rules: [{matches: [{path: {type: PathPrefix, value: /}}], backendRefs: [{name: web, port: 80}]}]
EOF
kubectl get httproute
확인할 것: HTTPRoute 객체가 생기지만, Gateway edge와 구현체가 없으면 Accepted=False.
흔히 묻는 것, 흔히 틀리는 것
| 오해 | 정정 |
|---|---|
| "Gateway API가 Ingress를 즉시 대체한다" | 점진적 전환. Ingress는 여전히 널리 쓰임. 신규 설계 기준이 Gateway API |
| "Gateway API는 구현체다" | API 규격. 구현체는 envoy-gateway/Contour/Cilium/nginx-gateway-fabric 등 다수 |
| "HTTPRoute는 Ingress와 같다" | 비슷하지만 더 강력(헤더/가중치 표준). 그리고 Gateway와 분리 |
| "nginx-gateway-fabric = ingress-nginx" | 다름. 전자는 NGINX사의 Gateway API 구현체, 후자는 커뮤니티 Ingress Controller |
| "Gateway API는 외부 진입만" | GAMMA로 메시 내부도 확장 |
| "Gateway API를 쓰면 RBAC이 자동 분리된다" | 객체가 나뉘어 분리가 가능해진 것. RBAC 설정은 별도 |
요약 — 이 글의 결론
- Gateway API의 핵심은 역할 분리 — GatewayClass/Gateway(인프라)와 HTTPRoute(앱)를 객체로 쪼개, RBAC으로 권한까지 분리. Ingress가 못 한 것.
- 표현력이 표준 API에 — 헤더 매칭, 가중치, canary가 annotation이 아니라 API 필드. 이식성이 살아남(envoy-gateway/Cilium/nginx-gateway-fabric 공통 해석).
- nginx ingress EOL 컨텍스트 — CVE-2025-1974와 유지보수 부담이 겹쳐 신규 L7 설계를 Gateway API 기준으로. 단 즉시 대체가 아니라 점진적 전환.
- 멀티 프로토콜 — HTTP/TCP/UDP/gRPC Route 타입. Ingress의 HTTP 중심 한계 넘음.
- TLS 세 모드(Terminate/Passthrough/Reencrypt)로 백엔드 암호화를 유지하면서 Gateway 검사까지.
- GAMMA initiative가 서비스 메시로 확장 — 외부 진입과 메시 내부를 하나의 API 모델로.
- Gateway API는 규격, 구현체는 다수. 이식성이 살아나는 것이 Ingress 대비 가장 큰 실익.
생각해 볼 문제
- 인프라 팀과 앱 팀이 같은 Ingress 객체를 고치는 구조의 구체적 위험을 시나리오로 그려라.
- HTTPRoute의 헤더 매칭으로 canary를 구현했다. Ingress의 annotation 방식과 비교해 이식성 측면에서 차이는?
- ingress-nginx에서 Gateway API로 전환할 때, 기존 annotation 기반 기능(속도 제한 등)은 어떻게 되나?
- Gateway API가 메시(GAMMA)까지 다룬다는 것의 의미를, 외부 진입과 내부 메시를 같은 API로 본다는 관점에서 설명하라.
- Gateway와 HTTPRoute를 분리했더니 개발팀이 자기 Route를 자유롭게 만든다. 남용을 막으려면? (RBAC + attachment 정책)
- Gateway API 구현체를 바꾸(envoy-gateway → Cilium)고 싶다. 매니페스트는 얼마나 바뀌어야 하나?
참고
- Gateway API 공식 문서 - 접근 2026-07-13 (역할 분리, API 모델)
- Gateway API - GatewayClass/Gateway/HTTPRoute - 접근 2026-07-13
- GAMMA initiative - 접근 2026-07-13 (메시 확장)
- ingress-nginx 보안 발표 / CVE-2025-1974 - 접근 2026-07-13 (EOL 컨텍스트, 공식 발표로 확인)
- Kubernetes 공식 문서 - Ingress에서 Gateway API로 전환 - 접근 2026-07-13
- Gateway API implementations - 접근 2026-07-13 (envoy-gateway, Contour, Cilium, nginx-gateway-fabric)
'Tech Artifacts > K8s Networking' 카테고리의 다른 글
| K8s Networking - 11. istio (0) | 2026.07.14 |
|---|---|
| K8s Networking - 10. service-mesh concepts (0) | 2026.07.14 |
| K8s Networking - 08. ingress (1) | 2026.07.14 |
| K8s Networking - 07. calico advanced-policy (0) | 2026.07.14 |
| K8s Networking - 06. network-policy (0) | 2026.07.14 |