Split View: 쿠버네티스 네트워킹의 종말과 부활: 2026년 3월 이전에 반드시 알아야 할 5가지 변화
쿠버네티스 네트워킹의 종말과 부활: 2026년 3월 이전에 반드시 알아야 할 5가지 변화
- 1. 서론: 당신의 클러스터가 위험에 처해 있습니다
- 2. [Takeaway 1] 시한폭탄의 카운트다운: Ingress NGINX의 공식 은퇴
- 3. [Takeaway 2] 어노테이션(Annotation)의 늪에서 탈출하기
- 4. [Takeaway 3] 역할의 분리: 인프라 관리자와 개발자의 평화로운 공존
- 5. [Takeaway 4] 벤더 종속성을 깨는 이식성(Portability)의 실현
- 6. [Takeaway 5] 성능의 도약: HTTP/3와 QUIC의 본격 도입
- 7. 실전 마이그레이션 가이드
- 8. 종합 마이그레이션 체크리스트
- 9. 결론: 이제 행동해야 할 때입니다
- 10. 참고 자료
1. 서론: 당신의 클러스터가 위험에 처해 있습니다
2026년 3월, 쿠버네티스 생태계에서 가장 광범위하게 사용되어 온 인프라 구성 요소 중 하나가 공식적으로 생명을 다합니다. Ingress NGINX Controller(kubernetes/ingress-nginx)의 EOL(End of Life)입니다.
이것은 단순한 버전 업그레이드나 마이너 변경이 아닙니다. 인터넷에 연결된 쿠버네티스 클러스터의 약 **41~50%**가 Ingress NGINX를 사용하고 있으며, RKE2, IBM Cloud, Alibaba ACK 등 주요 플랫폼에서 기본 인그레스 컨트롤러로 탑재되어 있습니다. 이 컨트롤러가 더 이상 보안 패치, 버그 수정, 그리고 어떠한 릴리스도 받지 못하게 된다는 것은 곧 수십만 개의 프로덕션 클러스터가 보호받지 못하는 상태로 방치된다는 것을 의미합니다.
"In March 2026, Kubernetes will retire Ingress NGINX, a piece of critical infrastructure for about half of cloud native environments... Half of you will be affected. You have two months left to prepare... We cannot overstate the severity of this situation or the importance of beginning migration..."
-- Kat Cosgrove, CNCF Ambassador & DevRel Engineer
이 글에서는 이 전환의 본질을 5가지 핵심 관점에서 분석합니다:
- 시한폭탄의 카운트다운 -- Ingress NGINX의 공식 은퇴와 그 여파
- 어노테이션의 늪에서 탈출 -- 구조적 결함과 Gateway API의 해법
- 역할의 분리 -- 인프라 관리자와 개발자의 평화로운 공존
- 벤더 종속성 탈피 -- 이식성(Portability)의 실현
- 성능의 도약 -- HTTP/3와 QUIC의 본격 도입
┌─────────────────────────────────────────────────────────────────┐
│ 2026년 쿠버네티스 네트워킹 전환 로드맵 │
├──────────┬──────────┬──────────┬──────────┬──────────┬──────────┤
│ 2025.03 │ 2025.11 │ 2026.03 │ 2026.06 │ 2026.11 │ 2027+ │
│ │ │ │ │ │ │
│ Ingress │ 은퇴 │ ■ EOL ■ │ Gateway │ AKS/GKE │ Ingress │
│ Nightmare│ 공식 │ 보안패치 │ API v1.5 │ 연장지원 │ API │
│ CVE 발생 │ 발표 │ 완전종료 │ (예상) │ 종료 │ 잔존 │
│ │ │ │ │ │ 가능성↓ │
│ GW API │ GW API │ │ │ │ │
│ v1.2 │ v1.4 GA │ │ │ │ │
└──────────┴──────────┴──────────┴──────────┴──────────┴──────────┘
▲ ▲ ▲
│ │ │
CVE-2025-1974 커뮤니티 지원 클라우드 벤더
CVSS 9.8 완전 종료 연장 지원 종료
2. [Takeaway 1] 시한폭탄의 카운트다운: Ingress NGINX의 공식 은퇴
2.1 무엇이 은퇴하는가: 정확한 범위 정의
혼동을 방지하기 위해 명확히 해야 할 것이 있습니다. 은퇴하는 것은 kubernetes/ingress-nginx 컨트롤러 프로젝트입니다. GA(General Availability) 상태인 Ingress API 자체(networking.k8s.io/v1)는 쿠버네티스에서 여전히 지원됩니다. 그러나 Ingress API를 실제로 동작시키는 가장 대중적인 구현체가 사라지는 것이므로, 실질적 영향은 막대합니다.
┌─────────────────────────────────────────────────────────┐
│ 은퇴 범위 명확화 │
│ │
│ ✗ 은퇴 대상: kubernetes/ingress-nginx 컨트롤러 │
│ (커뮤니티 유지보수 프로젝트) │
│ │
│ ✓ 유지 대상: Ingress API (networking.k8s.io/v1) │
│ F5 NGINX Ingress Controller (상용) │
│ 기타 서드파티 Ingress 구현체 │
│ │
│ ★ 새 표준: Gateway API (gateway.networking.k8s.io) │
└─────────────────────────────────────────────────────────┘
2.2 왜 지금인가: 구조적 문제의 누적
Ingress NGINX 프로젝트의 은퇴는 갑작스러운 결정이 아닙니다. 수년간 누적된 구조적 문제들이 임계점에 도달한 결과입니다:
1) 유지보수 인력의 고갈
프로젝트는 오랜 기간 동안 단 한두 명의 자원봉사자에 의존해 왔습니다. 인터넷에 연결된 클러스터의 절반에 영향을 미치는 핵심 인프라가 개인의 여가 시간에 의존한다는 것은 지속 가능한 모델이 아닙니다.
"For a long time, we've considered big companies or end user companies that rely on open source not contributing back to be a moral issue. But now, I think it's very easy to make the argument that not contributing back to open source is, in fact, a security issue. You have to start considering open source contributions as part of your security plan."
-- Kat Cosgrove
2) 감당할 수 없는 기술 부채
한때 유연성으로 평가받았던 기능들, 특히 snippets 어노테이션을 통한 임의의 NGINX 설정 주입 기능이 이제는 감당할 수 없는 보안 취약점으로 인식됩니다. 이 문제는 뒤에서 더 자세히 다루겠습니다.
3) IngressNightmare: CVE-2025-1974의 충격
2025년 3월에 발견된 CVE-2025-1974(CVSS 9.8)은 Ingress NGINX의 구조적 취약성을 극적으로 드러냈습니다.
2.3 IngressNightmare: 역대 최악의 쿠버네티스 취약점
CVE-2025-1974는 단독 취약점이 아니라, 5개의 연쇄 취약점(CVE-2025-1097, CVE-2025-1098, CVE-2025-24513, CVE-2025-24514, CVE-2025-1974)으로 구성된 공격 체인입니다.
| CVE ID | CVSS | 설명 |
|---|---|---|
| CVE-2025-24514 | 8.8 | auth-url 어노테이션을 통한 설정 주입 |
| CVE-2025-1097 | 8.8 | auth-tls-match-cn 어노테이션을 통한 설정 주입 |
| CVE-2025-1098 | 8.8 | mirror-target/mirror-host 어노테이션을 통한 설정 주입 |
| CVE-2025-24513 | 4.8 | auth-url 파일 경로 검증 부재 |
| CVE-2025-1974 | 9.8 | 인증 없는 원격 코드 실행(Unauthenticated RCE) |
공격 시나리오:
공격자 (Pod 네트워크 접근 가능)
│
▼
┌──────────────────────────┐
│ Admission Webhook │ ← 인증 없이 접근 가능
│ (8443 포트) │
└──────────┬───────────────┘
│ 악의적 Ingress 객체 전송
▼
┌──────────────────────────┐
│ NGINX 설정 주입 │ ← 임의의 NGINX directive 삽입
│ (CVE-2025-1097/1098/ │
│ 24514 활용) │
└──────────┬───────────────┘
│ 조작된 설정으로 RCE 달성
▼
┌──────────────────────────┐
│ 컨트롤러 Pod 장악 │ ← CVE-2025-1974
│ (CVSS 9.8) │
└──────────┬───────────────┘
│ ServiceAccount 토큰 탈취
▼
┌──────────────────────────┐
│ 전체 클러스터 시크릿 │ ← 모든 네임스페이스의
│ 접근 및 클러스터 탈취 │ Secret 열람 가능
└──────────────────────────┘
Wiz Research에 따르면, 클라우드 환경의 약 43%가 이 취약점에 노출되어 있었으며, Fortune 500 기업을 포함한 6,500개 이상의 클러스터가 취약한 Admission Controller를 퍼블릭 인터넷에 노출하고 있었습니다.
이 사건의 핵심 교훈은 명확합니다: 어노테이션 기반 설정 주입이라는 아키텍처 자체가 근본적인 보안 위협이라는 것입니다.
2.4 EOL 타임라인과 플랫폼별 영향
| 시점 | 이벤트 | 영향 |
|---|---|---|
| 2025년 3월 | IngressNightmare(CVE-2025-1974) 발표 | 긴급 패치 배포 (v1.12.1, v1.11.5) |
| 2025년 11월 | Ingress NGINX 공식 은퇴 발표 | 커뮤니티 마이그레이션 권고 시작 |
| 2026년 3월 | 커뮤니티 지원 완전 종료 | 보안 패치, 버그 수정, 릴리스 일체 중단 |
| 2026년 11월 | AKS Application Routing 연장 지원 종료 | Azure 관리형 환경도 지원 종료 |
| 2026년 11월 이후 | 모든 공식/연장 지원 종료 | 완전한 자체 책임 운영 |
"Best-effort maintenance will continue until March 2026. Afterward, there will be no further releases, no bugfixes, and no updates to resolve any security vulnerabilities that may be discovered."
-- Tabitha Sable, Kubernetes Security Response Committee
클라우드 벤더별 대응 현황:
| 클라우드 벤더 | 대응 전략 | 연장 지원 | 권장 대안 |
|---|---|---|---|
| Azure (AKS) | Application Routing Add-on 내 ingress-nginx 지원 | 2026년 11월까지 (보안 패치만) | Gateway API + NGINX Gateway Fabric |
| GCP (GKE) | GKE Gateway Controller 제공 | 벤더 자체 구현으로 전환 권고 | GKE Gateway Controller |
| AWS (EKS) | AWS Load Balancer Controller | 자체 구현으로 이미 분리 | AWS Gateway API Controller |
| 자체 호스팅 | 직접 마이그레이션 필요 | 없음 (2026년 3월 종료) | NGINX Gateway Fabric, Envoy Gateway 등 |
자체 호스팅 환경에서 운영 중인 조직에게 상황은 가장 긴급합니다. 2026년 3월 이후 발견되는 모든 보안 취약점에 대해 어떠한 공식 패치도 제공되지 않습니다.
3. [Takeaway 2] 어노테이션(Annotation)의 늪에서 탈출하기
3.1 어노테이션 기반 설정의 구조적 결함
Ingress API의 가장 근본적인 한계는 표현력의 부족입니다. Ingress 리소스의 spec은 호스트 기반 라우팅과 경로 기반 라우팅이라는 가장 기초적인 기능만을 지원합니다. 그 결과, 실무에서 필요한 거의 모든 고급 기능은 **어노테이션(annotation)**이라는 비구조적 메커니즘에 의존하게 되었습니다.
어노테이션의 근본적인 문제점을 분석하면 다음과 같습니다:
1) 타입 안전성의 부재
어노테이션은 단순한 key: value 문자열 쌍입니다. 스키마 검증이 없으므로 오타, 잘못된 값 형식, 잘못된 키 이름이 배포 시점까지 발견되지 않습니다.
# 이 오타를 발견할 수 있겠습니까?
metadata:
annotations:
# 오타: "rewrite-target" → "rewrite-traget"
nginx.ingress.kubernetes.io/rewrite-traget: /$2
# 타입 오류: 숫자여야 하지만 문자열 전달
nginx.ingress.kubernetes.io/proxy-read-timeout: 'sixhundred'
# 잘못된 prefix: "nginx.ingress.kubernetes.io" → "nginx.kubernetes.io"
nginx.kubernetes.io/ssl-redirect: 'true'
위 세 가지 모두 kubectl apply 시 아무런 오류 없이 적용됩니다. 문제는 런타임에 예상치 못한 동작으로만 나타나며, 이를 디버깅하는 데 수 시간이 소요될 수 있습니다.
2) 벤더 종속성의 강화
각 Ingress Controller는 자체적인 어노테이션 네임스페이스를 사용합니다:
# ingress-nginx 전용
nginx.ingress.kubernetes.io/canary: 'true'
nginx.ingress.kubernetes.io/canary-weight: '20'
# Traefik 전용
traefik.ingress.kubernetes.io/router.middlewares: default-rate-limit@kubernetescrd
# HAProxy 전용
haproxy.org/rate-limit-requests: '100'
# AWS ALB 전용
alb.ingress.kubernetes.io/target-type: ip
동일한 기능(카나리 배포, 속도 제한 등)을 구현하면서도 완전히 다른 어노테이션 문법을 사용합니다. 한 컨트롤러에서 다른 컨트롤러로 마이그레이션할 때, 모든 어노테이션을 수작업으로 변환해야 합니다.
3) 감사(Audit) 및 거버넌스의 불가능
어노테이션은 Ingress 리소스의 메타데이터에 평탄하게 나열됩니다. 수십 개의 어노테이션이 붙은 Ingress 객체에서 보안에 민감한 설정을 식별하는 것은 사실상 불가능합니다. RBAC으로 특정 어노테이션만 제한하는 것도 불가능합니다 -- 어노테이션을 쓸 수 있으면 모든 어노테이션을 쓸 수 있습니다.
3.2 snippets 어노테이션: 설계된 취약점
어노테이션 문제의 극단적 사례가 바로 nginx.ingress.kubernetes.io/configuration-snippet과 nginx.ingress.kubernetes.io/server-snippet입니다. 이 어노테이션들은 임의의 NGINX 설정 디렉티브를 직접 주입할 수 있게 합니다.
# 위험: 임의의 NGINX 설정 주입 가능
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
# 정상적 사용 의도: 커스텀 헤더 추가
more_set_headers "X-Custom-Header: value";
# 악의적 활용: 서버 정보 탈취
# proxy_pass http://internal-service.kube-system.svc.cluster.local;
# 악의적 활용: 인증 우회
# satisfy any;
# allow all;
이 기능은 CVE-2023-5043 등 여러 보안 취약점의 직접적인 원인이었습니다. Ingress 객체를 생성할 수 있는 권한만 있으면, 사실상 NGINX 프로세스의 전체 설정을 조작할 수 있었습니다. 이는 configuration-snippet 어노테이션이 NGINX 설정 파일의 location 블록에, server-snippet이 server 블록에 그대로 삽입되기 때문입니다.
3.3 Gateway API의 어노테이션 없는 모델(Annotation-less Model)
Gateway API는 이 문제를 구조화된 API 타입으로 해결합니다. 어노테이션에 의존하는 대신, 타입이 지정된(Typed) CRD 필드를 통해 설정을 표현합니다.
비교 예시: HTTPS 리다이렉트와 경로 재작성
기존 Ingress + 어노테이션 방식:
# Ingress 방식: 어노테이션에 의존
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/proxy-read-timeout: '600'
nginx.ingress.kubernetes.io/proxy-send-timeout: '600'
nginx.ingress.kubernetes.io/proxy-body-size: '100m'
nginx.ingress.kubernetes.io/cors-allow-origin: 'https://example.com'
nginx.ingress.kubernetes.io/cors-allow-methods: 'GET, POST, PUT'
nginx.ingress.kubernetes.io/cors-allow-headers: 'Content-Type, Authorization'
nginx.ingress.kubernetes.io/enable-cors: 'true'
nginx.ingress.kubernetes.io/limit-rps: '100'
nginx.ingress.kubernetes.io/canary: 'true'
nginx.ingress.kubernetes.io/canary-weight: '20'
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 80
Gateway API 방식:
# Gateway API 방식: 구조화된 스펙
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app
spec:
parentRefs:
- name: production-gateway
hostnames:
- app.example.com
rules:
# 규칙 1: HTTPS 리다이렉트 (어노테이션 없이 스펙으로 표현)
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
matches:
- headers:
- name: X-Forwarded-Proto
value: http
# 규칙 2: API 라우팅
- matches:
- path:
type: PathPrefix
value: /api
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: api-service
port: 80
weight: 80
- name: api-service-canary
port: 80
weight: 20
핵심 차이점 분석:
| 측면 | Ingress + 어노테이션 | Gateway API |
|---|---|---|
| 타입 안전성 | 없음 (문자열 key-value) | 있음 (CRD 스키마 검증) |
| IDE 지원 | 없음 | 자동완성, 실시간 검증 |
| 배포 시 검증 | 없음 (런타임 오류) | Admission Webhook 검증 |
| 카나리 배포 | 어노테이션 (벤더 종속) | backendRefs.weight (표준) |
| HTTPS 리다이렉트 | 어노테이션 (벤더 종속) | RequestRedirect 필터 (표준) |
| 경로 재작성 | 어노테이션 + 정규식 | URLRewrite 필터 (표준) |
| RBAC 제어 | 어노테이션 단위 제어 불가 | 리소스 단위 RBAC 가능 |
| 감사 추적 | 어렵다 | CRD 수준에서 가능 |
3.4 Policy Attachment: 어노테이션의 진정한 대안
Gateway API의 Policy Attachment 모델은 어노테이션이 담당하던 횡단 관심사(cross-cutting concerns)를 독립적인 리소스로 분리합니다.
# 타임아웃 정책: 별도의 리소스로 관리
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: BackendLBPolicy
metadata:
name: api-timeout-policy
spec:
targetRefs:
- group: ''
kind: Service
name: api-service
sessionPersistence:
sessionName: my-session
type: Cookie
---
# TLS 정책: 백엔드 TLS 설정을 별도 리소스로 분리
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
name: api-backend-tls
spec:
targetRefs:
- group: ''
kind: Service
name: api-service
validation:
caCertificateRefs:
- name: backend-ca-cert
group: ''
kind: ConfigMap
hostname: api-internal.example.com
이 모델의 장점은 명확합니다:
- 관심사의 분리: 라우팅 규칙(HTTPRoute)과 운영 정책(Policy)이 독립적으로 관리됩니다
- 재사용성: 하나의 정책을 여러 서비스에 부착(attach)할 수 있습니다
- RBAC 적용: 정책 리소스에 대해 별도의 RBAC 규칙을 적용할 수 있습니다
- 감사 용이성: 어떤 정책이 어떤 대상에 적용되어 있는지 명확하게 추적할 수 있습니다
4. [Takeaway 3] 역할의 분리: 인프라 관리자와 개발자의 평화로운 공존
4.1 Ingress의 거버넌스 문제
기존 Ingress API의 근본적인 설계 한계 중 하나는 역할 분리의 부재입니다. 단일 Ingress 리소스 안에 인프라 설정(TLS 인증서, 리스너 포트)과 애플리케이션 라우팅 규칙(경로 매칭, 백엔드 서비스)이 혼재합니다.
# Ingress: 인프라와 애플리케이션 설정이 혼재
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
# 누가 이 어노테이션을 관리하는가? 인프라팀? 개발팀?
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: 'true' # 인프라 관심사
nginx.ingress.kubernetes.io/proxy-body-size: '50m' # 인프라 관심사
nginx.ingress.kubernetes.io/rewrite-target: /$1 # 애플리케이션 관심사
nginx.ingress.kubernetes.io/canary-weight: '10' # 애플리케이션 관심사
spec:
ingressClassName: nginx # 인프라 관심사
tls:
- hosts:
- app.example.com
secretName: production-tls-cert # 인프라 관심사 (시크릿 관리)
rules:
- host: app.example.com # 혼합 관심사
http:
paths:
- path: /api/(.*) # 애플리케이션 관심사
pathType: ImplementationSpecific
backend:
service:
name: api-service # 애플리케이션 관심사
port:
number: 80
이 구조에서는 개발자가 자신의 라우팅 규칙을 변경하기 위해 인프라 설정이 포함된 동일한 리소스를 수정해야 합니다. 반대로, 인프라 관리자가 TLS 인증서를 교체하려면 애플리케이션 라우팅 규칙이 포함된 리소스에 접근해야 합니다.
4.2 Gateway API의 역할 기반 리소스 계층
Gateway API는 이 문제를 3계층 리소스 모델로 해결합니다:
┌─────────────────────────────────────────────────────────────┐
│ Layer 1: GatewayClass │
│ ───────────────────── │
│ 담당: Infrastructure Provider (클라우드 벤더, 플랫폼 팀) │
│ 역할: 데이터 플레인 구현체 정의 │
│ 예시: "nginx", "envoy", "gke-l7-global" │
│ RBAC: cluster-admin 수준 │
├─────────────────────────────────────────────────────────────┤
│ Layer 2: Gateway │
│ ───────────────── │
│ 담당: Cluster Operator (플랫폼/인프라 엔지니어) │
│ 역할: 리스너, TLS, IP 주소, 포트, 허용 네임스페이스 설정 │
│ 예시: 443 포트 HTTPS 리스너, 와일드카드 인증서 │
│ RBAC: namespace-admin 수준 (인프라 네임스페이스) │
├─────────────────────────────────────────────────────────────┤
│ Layer 3: HTTPRoute / GRPCRoute / TCPRoute │
│ ─────────────────────────────────────────── │
│ 담당: Application Developer (서비스 개발자) │
│ 역할: 라우팅 규칙, 백엔드 서비스 매핑, 트래픽 가중치 │
│ 예시: /api → api-service, 카나리 20% │
│ RBAC: namespace-editor 수준 (애플리케이션 네임스페이스) │
└─────────────────────────────────────────────────────────────┘
역할별 책임 매트릭스:
| 역할 | 리소스 | 책임 범위 | RBAC 예시 |
|---|---|---|---|
| Infrastructure Provider | GatewayClass | 데이터 플레인 구현체 등록, 파라미터 정의 | ClusterRole: gatewayclass-admin |
| Cluster Operator | Gateway, ReferenceGrant | 리스너 설정, TLS 인증서 관리, 네임스페이스 접근 제어 | Role: gateway-admin (infra-ns) |
| Application Developer | HTTPRoute, GRPCRoute | 라우팅 규칙 정의, 백엔드 서비스 매핑, 트래픽 분배 | Role: route-editor (app-ns) |
4.3 실전 RBAC 구성 예시
1단계: Infrastructure Provider -- GatewayClass 정의
# 인프라 제공자가 정의하는 GatewayClass
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx-gateway-fabric
spec:
controllerName: gateway.nginx.org/nginx-gateway-controller
parametersRef:
group: gateway.nginx.org
kind: NginxProxy
name: production-proxy-config
2단계: Cluster Operator -- Gateway 설정
# 클러스터 운영자가 관리하는 Gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: production-gateway
namespace: gateway-infra # 인프라 전용 네임스페이스
spec:
gatewayClassName: nginx-gateway-fabric
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls-cert
kind: Secret
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: 'true' # 허용된 네임스페이스만
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same
---
# 교차 네임스페이스 참조 허용
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-gateway-to-app-secrets
namespace: app-team-a
spec:
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: gateway-infra
to:
- group: ''
kind: Service
3단계: Application Developer -- HTTPRoute 정의
# 개발자가 자신의 네임스페이스에서 관리하는 HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-routes
namespace: app-team-a # 애플리케이션 네임스페이스
spec:
parentRefs:
- name: production-gateway
namespace: gateway-infra # 인프라 네임스페이스의 Gateway 참조
sectionName: https
hostnames:
- api.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /v1
backendRefs:
- name: api-v1
port: 8080
weight: 80
- name: api-v2
port: 8080
weight: 20 # 카나리 배포: 20% 트래픽을 v2로
RBAC 정책 예시:
# 개발자용 Role: HTTPRoute만 생성/수정 가능
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: route-editor
namespace: app-team-a
rules:
- apiGroups: ['gateway.networking.k8s.io']
resources: ['httproutes', 'grpcroutes']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['gateway.networking.k8s.io']
resources: ['gateways']
verbs: ['get', 'list'] # Gateway는 조회만 가능
---
# 인프라 운영자용 Role: Gateway 관리 가능, Route 생성 불가
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: gateway-admin
namespace: gateway-infra
rules:
- apiGroups: ['gateway.networking.k8s.io']
resources: ['gateways', 'referencegrants']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['']
resources: ['secrets']
verbs: ['get', 'list', 'watch', 'create', 'update']
이 구조가 제공하는 실질적 가치는 다음과 같습니다:
- 개발자 자율성: 개발자는 인프라팀의 승인 없이도 자신의 네임스페이스에서 라우팅 규칙을 자유롭게 변경할 수 있습니다
- 인프라 안전성: 개발자가 TLS 인증서, 리스너 포트, 허용 네임스페이스 등 인프라 설정을 실수로 변경할 위험이 원천적으로 차단됩니다
- 교차 네임스페이스 보안:
ReferenceGrant를 통해 다른 네임스페이스의 리소스 참조를 명시적으로 허용해야 하므로, 무단 접근이 방지됩니다 - 셀프서비스 거버넌스: 플랫폼 팀은
allowedRoutes를 통해 어떤 네임스페이스가 Gateway를 사용할 수 있는지 제어하고, 개발팀은 그 범위 안에서 자유롭게 운영합니다
5. [Takeaway 4] 벤더 종속성을 깨는 이식성(Portability)의 실현
5.1 이식성 문제의 본질
Ingress API가 벤더 이식성을 제공하지 못하는 이유는 단순합니다: 표준 스펙이 너무 빈약하기 때문입니다. Ingress API의 spec은 호스트 매칭, 경로 매칭, TLS 종단이라는 최소한의 기능만 정의합니다. 실무에서 필요한 모든 고급 기능(카나리 배포, 속도 제한, 헤더 조작, 타임아웃, 재시도 등)은 어노테이션을 통해 각 벤더가 독자적으로 구현합니다.
결과적으로, Ingress 리소스를 작성하는 순간 특정 컨트롤러에 종속됩니다. 이는 "Write once, run anywhere"라는 쿠버네티스의 이상과 정면으로 충돌합니다.
┌─────────────────────────────────────────────────────────────┐
│ Ingress API의 이식성 한계 │
│ │
│ Ingress spec (표준) 어노테이션 (비표준) │
│ ┌───────────────────┐ ┌──────────────────────────────┐ │
│ │ host: app.com │ │ nginx.ingress.k8s.io/... │ │
│ │ path: /api │ │ traefik.ingress.k8s.io/... │ │
│ │ tls: cert │ │ alb.ingress.k8s.io/... │ │
│ │ │ │ haproxy.org/... │ │
│ │ (이식 가능) │ │ (이식 불가 - 벤더 종속) │ │
│ └───────────────────┘ └──────────────────────────────┘ │
│ 20% 80% │
│ 실제 설정의 20%만이 나머지 80%는 벤더 고유 │
│ 이식 가능 어노테이션에 의존 │
└─────────────────────────────────────────────────────────────┘
5.2 Gateway API의 이식성 전략
Gateway API는 기능을 **3가지 지원 수준(Support Level)**으로 계층화하여 이식성과 확장성을 동시에 확보합니다:
| 지원 수준 | 설명 | 이식성 | 적합성 테스트 |
|---|---|---|---|
| Core | 모든 구현체가 반드시 지원해야 하는 핵심 기능 | 완전 이식 가능 | 필수 통과 |
| Extended | 이식 가능하지만 모든 구현체가 지원하지 않을 수 있는 기능 | 조건부 이식 가능 | 선택적 통과 |
| Implementation-specific | 벤더 고유의 확장 기능 | 이식 불가 | 대상 아님 |
Core 기능 (완전 이식 가능):
# 이 HTTPRoute는 어떤 Gateway API 구현체에서든 동일하게 동작합니다
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: portable-route
spec:
parentRefs:
- name: my-gateway
hostnames:
- app.example.com
rules:
- matches:
- path:
type: PathPrefix # Core: 경로 매칭
value: /api
- headers: # Core: 헤더 매칭
- name: X-Version
value: v2
filters:
- type: RequestHeaderModifier # Core: 헤더 조작
requestHeaderModifier:
add:
- name: X-Gateway
value: production
backendRefs:
- name: api-service
port: 8080
Extended 기능 (이식 가능하나 구현체 확인 필요):
# Extended 기능: 대부분의 구현체가 지원하지만 확인 필요
rules:
- filters:
- type: RequestRedirect # Extended: HTTP 리다이렉트
requestRedirect:
scheme: https
statusCode: 301
- type: URLRewrite # Extended: URL 재작성
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /v2
backendRefs:
- name: api-v1
port: 8080
weight: 90 # Extended: 트래픽 가중치 (카나리)
- name: api-v2
port: 8080
weight: 10
5.3 Conformance Test: 이식성의 보증 수표
Gateway API의 이식성은 단순한 약속이 아니라 **Conformance Test(적합성 테스트)**라는 구체적인 검증 메커니즘으로 뒷받침됩니다.
각 구현체는 Gateway API 프로젝트가 제공하는 표준화된 테스트 스위트를 통과해야 합니다. 이 테스트는 실제로 Gateway와 Route를 생성하고, 트래픽을 보내서, API 사양과 동일하게 동작하는지 검증합니다.
┌─────────────────────────────────────────────────────────────┐
│ Conformance Test 프로세스 │
│ │
│ 1. Gateway API 테스트 스위트 실행 │
│ └─> 표준 Gateway/HTTPRoute 리소스 배포 │
│ │
│ 2. 실제 트래픽 전송 및 동작 검증 │
│ └─> 경로 매칭, 헤더 필터링, 리다이렉트 등 │
│ │
│ 3. 결과 리포트 생성 │
│ └─> Core 100%, Extended features 목록 │
│ │
│ 4. 공식 인증 (Conformance Profile) │
│ └─> Gateway API 공식 구현체 목록 등재 │
└─────────────────────────────────────────────────────────────┘
주요 구현체별 Conformance 현황:
| 구현체 | Core 적합성 | Extended 기능 | 비고 |
|---|---|---|---|
| NGINX Gateway Fabric | 통과 | HTTP 라우팅, TLS, URL 재작성, 가중치 기반 분배 | NGINX 데이터 플레인 |
| Envoy Gateway | 통과 | 전체 Extended 기능 지원 | Envoy Proxy 데이터 플레인 |
| GKE Gateway Controller | 통과 | GCP 네이티브 통합 | Google Cloud 전용 |
| Istio | 통과 | 서비스 메쉬 통합 | Istio 데이터 플레인 |
| Contour | 통과 | Envoy 기반 | VMware 지원 |
| Traefik | 통과 | 미들웨어 통합 | v3+ 지원 |
5.4 실질적 이식성 시나리오: 멀티 클라우드 마이그레이션
Conformance Test가 보장하는 이식성은 멀티 클라우드 운영에서 실질적 가치를 발휘합니다:
┌──────────────────┐ ┌──────────────────┐
│ AWS EKS │ │ Azure AKS │
│ │ │ │
│ GatewayClass: │ │ GatewayClass: │
│ aws-gateway │ │ azure-gateway │
│ (구현체 변경) │ │ (구현체 변경) │
│ │ │ │
│ Gateway: ───────┼─────┼─ Gateway: ──────┐│
│ (최소 수정) │ │ (최소 수정) ││
│ │ │ ││
│ HTTPRoute: ─────┼─────┼─ HTTPRoute: ────┘│
│ (동일 재사용) │ │ (동일 재사용) │
└──────────────────┘ └──────────────────┘
│ │
└───────┬────────────────┘
│
동일한 HTTPRoute 매니페스트를
GatewayClass만 변경하여 재사용
기존 Ingress 방식에서는 AWS ALB Ingress Controller에서 GKE Ingress Controller로 이동할 때 모든 어노테이션을 다시 작성해야 했습니다. Gateway API에서는 GatewayClass만 변경하면 나머지 리소스(Gateway, HTTPRoute)는 Core/Extended 기능 범위 내에서 그대로 재사용할 수 있습니다.
6. [Takeaway 5] 성능의 도약: HTTP/3와 QUIC의 본격 도입
6.1 왜 HTTP/3인가: TCP의 구조적 한계
HTTP/2는 멀티플렉싱을 통해 동일 TCP 연결에서 여러 스트림을 동시에 처리할 수 있게 했습니다. 그러나 TCP 프로토콜 자체의 Head-of-Line(HOL) Blocking 문제를 해결하지 못했습니다.
HTTP/2 over TCP의 Head-of-Line Blocking 문제:
TCP 연결
┌─────────────────────────────────────────────────┐
│ Stream 1: [패킷1][패킷2][ 손실 ][패킷4] │
│ Stream 2: [패킷A][패킷B] ← 대기 [패킷D] │ ← 블로킹!
│ Stream 3: [패킷X][패킷Y] ← 대기 [패킷Z] │ ← 블로킹!
└─────────────────────────────────────────────────┘
패킷3 손실 시 → 모든 스트림이 대기
HTTP/3 over QUIC의 독립 스트림:
QUIC 연결
┌─────────────────────────────────────────────────┐
│ Stream 1: [패킷1][패킷2][ 손실 ][패킷4] │ ← 이 스트림만 영향
│ Stream 2: [패킷A][패킷B][패킷C] [패킷D] │ ← 정상 진행!
│ Stream 3: [패킷X][패킷Y][패킷Z] │ ← 정상 진행!
└─────────────────────────────────────────────────┘
패킷3 손실 시 → Stream 1만 영향
HTTP/3는 TCP 대신 QUIC(Quick UDP Internet Connections) 프로토콜을 사용합니다. QUIC은 UDP 위에 구축되며, 각 스트림이 독립적으로 전달됩니다. 하나의 스트림에서 패킷 손실이 발생해도 다른 스트림에 영향을 주지 않습니다.
6.2 HTTP/3의 핵심 성능 이점
| 특성 | HTTP/2 (TCP) | HTTP/3 (QUIC) | 개선 효과 |
|---|---|---|---|
| 전송 계층 | TCP | UDP + QUIC | 커널 의존성 감소 |
| 연결 수립 | TCP 3-way handshake + TLS handshake (2~3 RTT) | QUIC 0-RTT / 1-RTT | 최대 67% 지연 감소 |
| HOL Blocking | TCP 수준에서 발생 | 스트림 수준으로 격리 | 병렬 처리 효율 향상 |
| 연결 마이그레이션 | IP/포트 변경 시 재연결 필요 | Connection ID 기반 유지 | 모바일 환경 안정성 |
| 암호화 | TLS 선택적 | TLS 1.3 필수 (내장) | 기본 암호화 보장 |
| 패킷 손실 복구 | 전체 연결 영향 | 개별 스트림 독립 복구 | 손실 허용 네트워크 성능 향상 |
6.3 NGINX Gateway Fabric에서의 HTTP/3 지원
NGINX는 v1.25.0부터 QUIC과 HTTP/3를 공식 지원하며, NGINX Gateway Fabric을 통해 쿠버네티스 환경에서 HTTP/3를 활용할 수 있습니다.
HTTP/3 활성화를 위한 NginxProxy 설정:
apiVersion: gateway.nginx.org/v1alpha1
kind: NginxProxy
metadata:
name: http3-enabled-proxy
spec:
config:
http:
http3: true
http3MaxConcurrentStreams: 128
altSvcHeader: true # Alt-Svc 헤더 자동 추가
Gateway에서 HTTP/3 리스너 구성:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: http3-gateway
namespace: gateway-infra
spec:
gatewayClassName: nginx-gateway-fabric
listeners:
# HTTPS (TCP) + HTTP/3 (UDP) 동시 리스닝
- name: https-tcp
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls-cert
- name: https-udp
protocol: HTTPS # HTTP/3는 HTTPS 프로토콜로 선언
port: 443 # 동일 포트, UDP로 QUIC 처리
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls-cert
Service에서 UDP 포트 노출:
apiVersion: v1
kind: Service
metadata:
name: nginx-gateway-fabric
namespace: gateway-infra
spec:
type: LoadBalancer
ports:
- name: https-tcp
port: 443
targetPort: 443
protocol: TCP
- name: https-udp
port: 443
targetPort: 443
protocol: UDP # QUIC을 위한 UDP 포트 필수
6.4 HTTP/3 도입 시 주의사항
HTTP/3 도입 시 반드시 확인해야 할 기술적 요구사항과 주의사항이 있습니다:
1) SSL 라이브러리 요구사항
QUIC 프로토콜 지원을 위해서는 QUIC 호환 SSL 라이브러리가 필요합니다. 표준 OpenSSL은 QUIC API를 지원하지 않으므로(OpenSSL 3.x 기준), 다음 대안 중 하나를 사용해야 합니다:
| SSL 라이브러리 | QUIC 지원 | 비고 |
|---|---|---|
| BoringSSL | 네이티브 지원 | Google 개발, NGINX Gateway Fabric 기본 사용 |
| LibreSSL | 3.6.0+ 지원 | OpenBSD 프로젝트 |
| QuicTLS | OpenSSL + QUIC 패치 | OpenSSL 포크, QUIC API 추가 |
| OpenSSL | 미지원 (3.x 기준) | 향후 지원 예정 |
NGINX Gateway Fabric은 기본적으로 BoringSSL을 사용하여 빌드되므로, 별도의 SSL 라이브러리 교체 없이 HTTP/3를 사용할 수 있습니다.
2) 방화벽 및 네트워크 설정
┌─────────────────────────────────────────────────────────┐
│ HTTP/3 네트워크 요구사항 │
│ │
│ 인바운드 규칙에 UDP 443 추가 필수: │
│ │
│ 기존 (HTTP/2만): │
│ ┌──────────────────────────────────────┐ │
│ │ TCP 80 ← HTTP │ │
│ │ TCP 443 ← HTTPS (TLS over TCP) │ │
│ └──────────────────────────────────────┘ │
│ │
│ HTTP/3 추가 후: │
│ ┌──────────────────────────────────────┐ │
│ │ TCP 80 ← HTTP │ │
│ │ TCP 443 ← HTTPS (TLS over TCP) │ │
│ │ UDP 443 ← QUIC (HTTP/3 over UDP) │ ← 추가 필수 │
│ └──────────────────────────────────────┘ │
│ │
│ 주의: 많은 기업 방화벽과 클라우드 보안 그룹이 │
│ UDP 443을 기본적으로 차단합니다. │
└─────────────────────────────────────────────────────────┘
- 클라우드 보안 그룹: AWS Security Group, Azure NSG, GCP Firewall Rules에서 UDP 443 인바운드를 명시적으로 허용해야 합니다
- CDN/WAF 호환성: 일부 CDN이나 WAF가 QUIC 트래픽을 차단하거나 제대로 처리하지 못할 수 있습니다
- 로드밸런서 지원: 클라우드 로드밸런서가 UDP 트래픽을 올바르게 라우팅하는지 확인해야 합니다. AWS NLB, Azure Load Balancer, GCP Network Load Balancer는 UDP를 지원합니다
3) Alt-Svc 헤더를 통한 점진적 전환
HTTP/3 도입은 점진적으로 진행할 수 있습니다. 서버는 HTTP/2 응답에 Alt-Svc 헤더를 포함시켜 클라이언트에게 HTTP/3 사용 가능을 알립니다:
Alt-Svc: h3=":443"; ma=86400
클라이언트(브라우저)는 이 헤더를 받은 후 다음 요청부터 HTTP/3를 시도합니다. 실패 시 자동으로 HTTP/2로 폴백됩니다. 2025년 기준 Chrome 87+, Firefox 88+, Safari 14+ 등 전체 브라우저의 95% 이상이 HTTP/3를 지원합니다.
4) eBPF를 활용한 QUIC 연결 마이그레이션
Linux 5.7+ 커널에서는 eBPF를 활용한 QUIC 패킷 라우팅을 지원합니다. 이를 통해 QUIC의 Connection Migration 기능을 활용할 수 있어, 클라이언트의 네트워크가 변경되더라도(Wi-Fi에서 LTE로 전환 등) 연결이 유지됩니다.
# nginx.conf에서 eBPF 기반 QUIC 라우팅 활성화
quic_bpf on; # Linux 5.7+ 필수
7. 실전 마이그레이션 가이드
7.1 마이그레이션 전략 개요
Ingress NGINX에서 Gateway API로의 마이그레이션은 한 번에 완료하는 Big Bang 방식이 아니라, **단계적 전환(Progressive Migration)**이 권장됩니다.
┌──────────────────────────────────────────────────────────────┐
│ 단계적 마이그레이션 전략 │
│ │
│ Phase 1: 인벤토리 및 평가 (1~2주) │
│ ├─ 전체 Ingress 리소스 목록화 │
│ ├─ 사용 중인 어노테이션 분류 │
│ ├─ snippets 사용 여부 파악 (보안 위험 우선 제거) │
│ └─ 의존성 매핑 (cert-manager, external-dns 등) │
│ │
│ Phase 2: Gateway API 인프라 구축 (1~2주) │
│ ├─ Gateway API CRD 설치 │
│ ├─ NGINX Gateway Fabric 또는 대안 컨트롤러 배포 │
│ ├─ GatewayClass, Gateway 리소스 생성 │
│ └─ 비프로덕션 환경에서 검증 │
│ │
│ Phase 3: 점진적 라우팅 전환 (2~4주) │
│ ├─ ingress2gateway 도구로 초기 변환 │
│ ├─ 수동 검토 및 어노테이션 → 필터/정책 변환 │
│ ├─ 서비스별 순차 전환 (비핵심 → 핵심 서비스) │
│ └─ 병렬 운영(Ingress + Gateway API) 기간 │
│ │
│ Phase 4: 완전 전환 및 정리 (1~2주) │
│ ├─ 모든 트래픽이 Gateway API 경유 확인 │
│ ├─ Ingress 리소스 제거 │
│ ├─ ingress-nginx 컨트롤러 제거 │
│ └─ 모니터링 및 알림 재설정 │
└──────────────────────────────────────────────────────────────┘
7.2 Phase 1: 인벤토리 수집
전체 Ingress 리소스 조회:
# 모든 네임스페이스의 Ingress 리소스 목록
kubectl get ingress -A -o wide
# 사용 중인 어노테이션 전체 추출
kubectl get ingress -A -o json | \
jq -r '.items[].metadata.annotations // {} | keys[]' | \
sort | uniq -c | sort -rn
# snippets 어노테이션 사용 여부 긴급 확인 (보안 위험)
kubectl get ingress -A -o json | \
jq -r '.items[] | select(.metadata.annotations["nginx.ingress.kubernetes.io/configuration-snippet"] != null or .metadata.annotations["nginx.ingress.kubernetes.io/server-snippet"] != null) | .metadata.namespace + "/" + .metadata.name'
# IngressClass 확인
kubectl get ingressclass
어노테이션 분류 체크리스트:
| 분류 | 어노테이션 예시 | Gateway API 대체 | 긴급도 |
|---|---|---|---|
| 보안 위험 | configuration-snippet, server-snippet | 제거 또는 Custom Filter | 즉시 |
| 표준 대체 가능 | ssl-redirect, rewrite-target | RequestRedirect, URLRewrite 필터 | 높음 |
| Policy 대체 가능 | proxy-read-timeout, proxy-body-size | Policy Attachment | 중간 |
| 기능별 대체 | canary, canary-weight | backendRefs.weight | 중간 |
| 구현체 의존 | upstream-hash-by, affinity | 구현체별 CRD 확인 | 낮음 |
7.3 Phase 2: ingress2gateway 도구 활용
ingress2gateway는 Kubernetes SIG-Network에서 공식 제공하는 마이그레이션 도구입니다.
설치:
# Go 환경이 있는 경우
go install github.com/kubernetes-sigs/ingress2gateway@latest
# 또는 GitHub Releases에서 바이너리 다운로드
# https://github.com/kubernetes-sigs/ingress2gateway/releases
기본 사용법:
# 클러스터의 Ingress 리소스를 자동 변환
ingress2gateway print --all-namespaces
# 특정 네임스페이스만 변환
ingress2gateway print --namespace production
# 파일 기반 변환
ingress2gateway print --input-file ingress-resources.yaml
# ingress-nginx 프로바이더 지정 (어노테이션 변환 지원)
ingress2gateway print --providers ingress-nginx --all-namespaces
# 결과를 파일로 저장
ingress2gateway print --providers ingress-nginx --all-namespaces > gateway-resources.yaml
변환 예시:
입력 (Ingress):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-app
namespace: production
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 80
출력 (Gateway API):
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: nginx
namespace: production
spec:
gatewayClassName: nginx
listeners:
- name: app-example-com-https
hostname: app.example.com
port: 443
protocol: HTTPS
tls:
certificateRefs:
- name: app-tls
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-app
namespace: production
spec:
parentRefs:
- name: nginx
hostnames:
- app.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: api-service
port: 80
중요 주의사항: ingress2gateway는 시작점일 뿐, 모든 어노테이션을 완벽하게 변환하지는 않습니다. 특히 구현체 고유 기능(snippets, 커스텀 Lua 스크립트 등)은 수동으로 재설계해야 합니다. 변환 결과를 반드시 검토하고, 비프로덕션 환경에서 충분히 테스트한 후 적용하세요.
7.4 Phase 3: NGINX Gateway Fabric 배포
Helm을 이용한 설치:
# Gateway API CRD 설치
kubectl kustomize \
"https://github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.1" \
| kubectl apply -f -
# NGINX Gateway Fabric 설치
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
--create-namespace \
--namespace nginx-gateway \
--set service.type=LoadBalancer
GatewayClass 확인:
# 설치 후 GatewayClass 확인
kubectl get gatewayclass
# NAME CONTROLLER ACCEPTED
# nginx gateway.nginx.org/nginx-gateway-controller True
Gateway 생성 및 검증:
# Gateway 리소스 적용
kubectl apply -f gateway.yaml
# Gateway 상태 확인
kubectl get gateway -n gateway-infra
# NAME CLASS ADDRESS PROGRAMMED AGE
# production-gateway nginx 203.0.113.10 True 5m
# HTTPRoute 적용
kubectl apply -f httproute.yaml
# HTTPRoute 상태 확인
kubectl get httproute -n app-team-a
# NAME HOSTNAMES AGE
# api-routes ["api.example.com"] 2m
# 실제 트래픽 테스트
curl -H "Host: api.example.com" https://203.0.113.10/v1/health
7.5 Ingress vs Gateway API 기능 비교 종합표
| 기능 | Ingress API | Gateway API | 비고 |
|---|---|---|---|
| 호스트 기반 라우팅 | spec.rules[].host | spec.hostnames | 동등 |
| 경로 기반 라우팅 | spec.rules[].http.paths | spec.rules[].matches[].path | Gateway API가 더 유연 |
| TLS 종단 | spec.tls | Gateway.listeners[].tls | 역할 분리 (Gateway에서 관리) |
| HTTPS 리다이렉트 | 어노테이션 (벤더 종속) | RequestRedirect 필터 (표준) | Gateway API 우위 |
| URL 재작성 | 어노테이션 (벤더 종속) | URLRewrite 필터 (표준) | Gateway API 우위 |
| 카나리 배포 | 어노테이션 (벤더 종속) | backendRefs.weight (표준) | Gateway API 우위 |
| 헤더 매칭 | 미지원 (어노테이션 한정) | spec.rules[].matches[].headers | Gateway API 우위 |
| 헤더 조작 | 어노테이션 (벤더 종속) | RequestHeaderModifier 필터 | Gateway API 우위 |
| 트래픽 미러링 | 어노테이션 (벤더 종속) | RequestMirror 필터 (Extended) | Gateway API 우위 |
| 타임아웃 | 어노테이션 (벤더 종속) | HTTPRoute timeouts (v1.2+) | Gateway API 우위 |
| 재시도 | 어노테이션 (벤더 종속) | HTTPRoute retry (v1.2+) | Gateway API 우위 |
| gRPC 라우팅 | 미지원 (어노테이션 한정) | GRPCRoute (GA) | Gateway API 우위 |
| TCP/UDP 라우팅 | 미지원 | TCPRoute, UDPRoute (Experimental) | Gateway API 우위 |
| 역할 기반 분리 | 미지원 | GatewayClass/Gateway/Route 분리 | Gateway API 우위 |
| 교차 네임스페이스 | 미지원 | ReferenceGrant | Gateway API 우위 |
| 벤더 이식성 | 낮음 (어노테이션 종속) | 높음 (Conformance Test) | Gateway API 우위 |
| 백엔드 TLS | 어노테이션 (벤더 종속) | BackendTLSPolicy (v1.4 GA) | Gateway API 우위 |
| WebSocket | 어노테이션 (벤더 종속) | 표준 지원 (v1.2+) | Gateway API 우위 |
8. 종합 마이그레이션 체크리스트
아래는 Ingress NGINX에서 Gateway API로의 전환을 위한 포괄적인 체크리스트입니다. 조직의 상황에 맞게 활용하시기 바랍니다.
8.1 평가 단계
- 전체 클러스터의 Ingress 리소스 수와 네임스페이스 매핑 완료
- 사용 중인 Ingress NGINX 어노테이션 전수 조사 완료
-
configuration-snippet/server-snippet사용 여부 확인 및 보안 위험 평가 - ingress-nginx 컨트롤러 버전 확인 (CVE-2025-1974 패치 적용 여부)
- cert-manager, external-dns 등 연동 시스템 의존성 파악
- 현재 트래픽 패턴 및 라우팅 규칙 문서화
8.2 계획 단계
- 대상 Gateway API 구현체 선정 (NGINX Gateway Fabric, Envoy Gateway 등)
- GatewayClass/Gateway/Route 역할 분리 정책 수립
- 네임스페이스 전략 설계 (인프라용, 애플리케이션용)
- RBAC 정책 설계 (인프라팀 vs 개발팀 권한 분리)
- 마이그레이션 순서 결정 (비핵심 서비스 우선)
- 롤백 계획 수립
- HTTP/3 도입 여부 결정
8.3 실행 단계
- Gateway API CRD 설치 (
gateway.networking.k8s.io) - Gateway API 구현체 컨트롤러 배포
- GatewayClass 리소스 생성 및 상태 확인 (
ACCEPTED: True) - Gateway 리소스 생성 및 IP 주소 할당 확인 (
PROGRAMMED: True) -
ingress2gateway도구로 초기 변환 실행 - 변환 결과 수동 검토 및 누락된 기능 보완
- 비프로덕션 환경에서 변환된 HTTPRoute 테스트
- DNS 가중치 기반으로 트래픽 점진적 전환
- 프로덕션 환경 전환 및 모니터링
8.4 검증 단계
- 모든 라우팅 경로의 정상 응답 확인
- TLS 인증서 종단 및 갱신 정상 동작 확인
- 카나리/가중치 기반 배포 동작 확인
- 헤더 기반 라우팅 동작 확인
- 에러 페이지 및 기본 백엔드 동작 확인
- 모니터링 및 알림 정상 동작 확인
- 부하 테스트 수행 및 성능 기준선 비교
8.5 정리 단계
- 기존 Ingress 리소스 제거
- ingress-nginx 컨트롤러 Deployment/DaemonSet 제거
- ingress-nginx 관련 ConfigMap, ServiceAccount, RBAC 리소스 정리
- ingress-nginx Service(LoadBalancer) 제거 및 IP 주소 회수
- Helm 릴리스 정리 (해당 시)
- CI/CD 파이프라인에서 Ingress 관련 매니페스트 제거 또는 Gateway API로 교체
- IaC(Terraform, Pulumi 등)에서 ingress-nginx 모듈 제거
- 팀 교육 및 운영 문서 업데이트
9. 결론: 이제 행동해야 할 때입니다
Ingress NGINX의 은퇴는 단순히 하나의 컨트롤러가 사라지는 사건이 아닙니다. 이것은 쿠버네티스 네트워킹 패러다임 전체의 전환점입니다.
요약: 5가지 핵심 변화와 대응 방향
| # | 변화 | 핵심 메시지 | 즉시 행동 |
|---|---|---|---|
| 1 | Ingress NGINX EOL | 2026년 3월 이후 보안 패치 없음 | 마이그레이션 계획 수립 착수 |
| 2 | 어노테이션 탈출 | 구조적 결함이 보안 취약점으로 직결 | snippets 사용 즉시 제거 |
| 3 | 역할 분리 | GatewayClass/Gateway/Route 3계층 모델 | RBAC 정책 재설계 |
| 4 | 벤더 이식성 | Conformance Test 기반 표준화 | 멀티 클라우드 전략 재검토 |
| 5 | HTTP/3 & QUIC | UDP 기반 차세대 프로토콜 | 방화벽 UDP 443 개방 검토 |
지금 바로 실행해야 할 3가지 행동:
1. 인벤토리 수집 (오늘)
# 지금 바로 실행하세요
kubectl get ingress -A -o json | \
jq -r '[.items[] | {
namespace: .metadata.namespace,
name: .metadata.name,
annotations: (.metadata.annotations // {} | keys | length),
has_snippets: ((.metadata.annotations // {}) |
has("nginx.ingress.kubernetes.io/configuration-snippet") or
has("nginx.ingress.kubernetes.io/server-snippet"))
}]'
2. ingress2gateway 도구 실행 (이번 주)
go install github.com/kubernetes-sigs/ingress2gateway@latest
ingress2gateway print --providers ingress-nginx -A > gateway-migration.yaml
3. NGINX Gateway Fabric 테스트 환경 구축 (이번 달)
# 비프로덕션 클러스터에서 테스트
kubectl kustomize \
"https://github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.1" \
| kubectl apply -f -
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
--create-namespace --namespace nginx-gateway
쿠버네티스 커뮤니티가 10년간 쌓아온 경험과 교훈이 Gateway API라는 새로운 표준에 녹아 있습니다. 어노테이션의 늪에서 벗어나 타입 안전한 API로, 단일 리소스의 혼재에서 역할 기반 분리로, 벤더 종속에서 이식성의 자유로 나아갈 때입니다.
2026년 3월이라는 데드라인은 위협이 아니라 기회입니다. 이 전환을 통해 더 안전하고, 더 유연하며, 더 표준화된 네트워킹 인프라를 구축할 수 있습니다. 지금 시작하세요.
10. 참고 자료
공식 문서 및 발표
- Ingress NGINX Retirement: What You Need to Know | Kubernetes Blog
- Gateway API v1.2: WebSockets, Timeouts, Retries, and More | Kubernetes Blog
- Gateway API v1.4: New Features | Kubernetes Blog
- Gateway API Official Documentation
- Gateway API Conformance
- Ingress-nginx CVE-2025-1974: What You Need to Know | Kubernetes Blog
NGINX Gateway Fabric
- F5 NGINX Gateway Fabric Documentation
- NGINX Gateway Fabric GitHub
- What's New in F5 NGINX Gateway Fabric 2.3.0
- Gateway Architecture | NGINX Documentation
- Gateway API Compatibility | NGINX Documentation
보안 및 CVE
- IngressNightmare: CVE-2025-1974 | Wiz Blog
- Detecting and Mitigating IngressNightmare | Sysdig
- IngressNightmare CVE-2025-1974 | FortiGuard Labs
마이그레이션 가이드
- Migrating from Ingress | Gateway API Documentation
- Migrating from Ingress-NGINX | Gateway API Documentation
- ingress2gateway GitHub
- Introducing ingress2gateway | Kubernetes Blog
클라우드 벤더
- AKS Application Routing Add-on Ingress-NGINX Update | AKS Engineering Blog
- The End of an Era: Transitioning Away from Ingress NGINX | Google Open Source Blog
HTTP/3 및 QUIC
The Death and Resurrection of Kubernetes Networking: 5 Changes You Must Know Before March 2026
- 1. Introduction: Your Cluster Is in Danger
- 2. [Takeaway 1] The Countdown of a Time Bomb: The Official Retirement of Ingress NGINX
- 3. [Takeaway 2] Escaping the Annotation Swamp
- 4. [Takeaway 3] Separation of Roles: Peaceful Coexistence of Infrastructure Administrators and Developers
- 5. [Takeaway 4] Breaking Vendor Lock-in: Achieving Portability
- 6. [Takeaway 5] The Performance Leap: Full-Scale Adoption of HTTP/3 and QUIC
- 7. Practical Migration Guide
- 8. Comprehensive Migration Checklist
- 9. Conclusion: It Is Time to Act
- 10. References
- Quiz
1. Introduction: Your Cluster Is in Danger
In March 2026, one of the most widely used infrastructure components in the Kubernetes ecosystem officially reaches the end of its life. This is the EOL (End of Life) of the Ingress NGINX Controller (kubernetes/ingress-nginx).
This is not a simple version upgrade or minor change. Approximately 41-50% of internet-connected Kubernetes clusters use Ingress NGINX, and it ships as the default ingress controller on major platforms including RKE2, IBM Cloud, and Alibaba ACK. The fact that this controller will no longer receive security patches, bug fixes, or any releases means that hundreds of thousands of production clusters will be left unprotected.
"In March 2026, Kubernetes will retire Ingress NGINX, a piece of critical infrastructure for about half of cloud native environments... Half of you will be affected. You have two months left to prepare... We cannot overstate the severity of this situation or the importance of beginning migration..."
-- Kat Cosgrove, CNCF Ambassador & DevRel Engineer
This article analyzes the essence of this transition from 5 key perspectives:
- The Countdown of a Time Bomb -- The official retirement of Ingress NGINX and its aftermath
- Escaping the Annotation Swamp -- Structural flaws and Gateway API's solution
- Separation of Roles -- Peaceful coexistence of infrastructure administrators and developers
- Breaking Vendor Lock-in -- Achieving portability
- The Performance Leap -- Full-scale adoption of HTTP/3 and QUIC
┌─────────────────────────────────────────────────────────────────┐
│ 2026 Kubernetes Networking Transition Roadmap │
├──────────┬──────────┬──────────┬──────────┬──────────┬──────────┤
│ 2025.03 │ 2025.11 │ 2026.03 │ 2026.06 │ 2026.11 │ 2027+ │
│ │ │ │ │ │ │
│ Ingress │ Official │ ■ EOL ■ │ Gateway │ AKS/GKE │ Ingress │
│ Nightmare│ Retire │ Security │ API v1.5 │ Extended │ API │
│ CVE │ Announce │ Patches │ (Est.) │ Support │ Residual│
│ │ │ End │ │ Ends │ Low │
│ GW API │ GW API │ │ │ │ │
│ v1.2 │ v1.4 GA │ │ │ │ │
└──────────┴──────────┴──────────┴──────────┴──────────┴──────────┘
▲ ▲ ▲
│ │ │
CVE-2025-1974 Community Support Cloud Vendor
CVSS 9.8 Fully Ends Extended Support Ends
2. [Takeaway 1] The Countdown of a Time Bomb: The Official Retirement of Ingress NGINX
2.1 What Is Being Retired: Precise Scope Definition
To prevent confusion, let's clarify something. What is being retired is the kubernetes/ingress-nginx controller project. The GA (General Availability) Ingress API itself (networking.k8s.io/v1) is still supported in Kubernetes. However, since the most popular implementation that actually runs the Ingress API is disappearing, the practical impact is enormous.
┌─────────────────────────────────────────────────────────┐
│ Retirement Scope Clarification │
│ │
│ ✗ Retiring: kubernetes/ingress-nginx controller │
│ (Community-maintained project) │
│ │
│ ✓ Continuing: Ingress API (networking.k8s.io/v1) │
│ F5 NGINX Ingress Controller (Commercial) │
│ Other third-party Ingress implementations │
│ │
│ ★ New Standard: Gateway API (gateway.networking.k8s.io)│
└─────────────────────────────────────────────────────────┘
2.2 Why Now: Accumulation of Structural Problems
The retirement of the Ingress NGINX project is not a sudden decision. It is the result of structural problems that have accumulated over years reaching a critical point:
1) Maintainer Exhaustion
The project has long relied on just one or two volunteers. Having critical infrastructure that affects half of internet-connected clusters depend on individuals' spare time is not a sustainable model.
"For a long time, we've considered big companies or end user companies that rely on open source not contributing back to be a moral issue. But now, I think it's very easy to make the argument that not contributing back to open source is, in fact, a security issue. You have to start considering open source contributions as part of your security plan."
-- Kat Cosgrove
2) Unmanageable Technical Debt
Features once praised for their flexibility, particularly the ability to inject arbitrary NGINX configuration through snippets annotations, are now recognized as unmanageable security vulnerabilities. This issue will be discussed in more detail later.
3) IngressNightmare: The Impact of CVE-2025-1974
CVE-2025-1974, discovered in March 2025, dramatically exposed the structural vulnerability of Ingress NGINX.
2.3 IngressNightmare: The Worst Kubernetes Vulnerability Ever
CVE-2025-1974 is not a single vulnerability but an attack chain composed of 5 chained vulnerabilities (CVE-2025-1097, CVE-2025-1098, CVE-2025-24513, CVE-2025-24514, CVE-2025-1974).
| CVE ID | CVSS | Description |
|---|---|---|
| CVE-2025-24514 | 8.8 | Configuration injection via auth-url annotation |
| CVE-2025-1097 | 8.8 | Configuration injection via auth-tls-match-cn annotation |
| CVE-2025-1098 | 8.8 | Configuration injection via mirror-target/mirror-host annotations |
| CVE-2025-24513 | 4.8 | Lack of auth-url file path validation |
| CVE-2025-1974 | 9.8 | Unauthenticated Remote Code Execution (Unauthenticated RCE) |
Attack Scenario:
Attacker (with Pod network access)
│
▼
┌──────────────────────────┐
│ Admission Webhook │ ← Accessible without authentication
│ (port 8443) │
└──────────┬───────────────┘
│ Send malicious Ingress object
▼
┌──────────────────────────┐
│ NGINX Config Injection │ ← Inject arbitrary NGINX directives
│ (Leveraging CVE-2025- │
│ 1097/1098/24514) │
└──────────┬───────────────┘
│ Achieve RCE via crafted config
▼
┌──────────────────────────┐
│ Controller Pod Takeover │ ← CVE-2025-1974
│ (CVSS 9.8) │
└──────────┬───────────────┘
│ Steal ServiceAccount token
▼
┌──────────────────────────┐
│ Access All Cluster │ ← Can view Secrets from
│ Secrets & Cluster │ all namespaces
│ Takeover │
└──────────────────────────┘
According to Wiz Research, approximately 43% of cloud environments were exposed to this vulnerability, and more than 6,500 clusters, including Fortune 500 companies, had vulnerable Admission Controllers exposed to the public internet.
The key lesson from this incident is clear: the architecture of annotation-based configuration injection itself is a fundamental security threat.
2.4 EOL Timeline and Platform-Specific Impact
| Timeframe | Event | Impact |
|---|---|---|
| March 2025 | IngressNightmare (CVE-2025-1974) disclosed | Emergency patches released (v1.12.1, v1.11.5) |
| November 2025 | Official Ingress NGINX retirement announced | Community migration advisory begins |
| March 2026 | Community support fully ends | All security patches, bug fixes, releases cease |
| November 2026 | AKS Application Routing extended support ends | Azure managed environments also lose support |
| After November 2026 | All official/extended support ends | Fully self-managed responsibility |
"Best-effort maintenance will continue until March 2026. Afterward, there will be no further releases, no bugfixes, and no updates to resolve any security vulnerabilities that may be discovered."
-- Tabitha Sable, Kubernetes Security Response Committee
Cloud Vendor Response Status:
| Cloud Vendor | Response Strategy | Extended Support | Recommended Alternative |
|---|---|---|---|
| Azure (AKS) | ingress-nginx support within Application Routing Add-on | Until November 2026 (security patches only) | Gateway API + NGINX Gateway Fabric |
| GCP (GKE) | GKE Gateway Controller provided | Recommends transition to vendor's own implementation | GKE Gateway Controller |
| AWS (EKS) | AWS Load Balancer Controller | Already separated to own implementation | AWS Gateway API Controller |
| Self-Hosted | Direct migration required | None (ends March 2026) | NGINX Gateway Fabric, Envoy Gateway, etc. |
For organizations running self-hosted environments, the situation is most urgent. No official patches will be provided for any security vulnerabilities discovered after March 2026.
3. [Takeaway 2] Escaping the Annotation Swamp
3.1 Structural Flaws of Annotation-Based Configuration
The most fundamental limitation of the Ingress API is lack of expressiveness. The Ingress resource spec only supports the most basic features: host-based routing and path-based routing. As a result, virtually all advanced features needed in practice rely on annotations -- an unstructured mechanism.
Analyzing the fundamental problems of annotations reveals the following:
1) Absence of Type Safety
Annotations are simple key: value string pairs. Without schema validation, typos, incorrect value formats, and wrong key names are not discovered until deployment time.
# Can you spot the typos?
metadata:
annotations:
# Typo: "rewrite-target" → "rewrite-traget"
nginx.ingress.kubernetes.io/rewrite-traget: /$2
# Type error: should be a number but string passed
nginx.ingress.kubernetes.io/proxy-read-timeout: 'sixhundred'
# Wrong prefix: "nginx.ingress.kubernetes.io" → "nginx.kubernetes.io"
nginx.kubernetes.io/ssl-redirect: 'true'
All three of the above are applied without any errors during kubectl apply. Problems only manifest as unexpected behavior at runtime, and debugging can take hours.
2) Vendor Lock-in Amplification
Each Ingress Controller uses its own annotation namespace:
# ingress-nginx specific
nginx.ingress.kubernetes.io/canary: 'true'
nginx.ingress.kubernetes.io/canary-weight: '20'
# Traefik specific
traefik.ingress.kubernetes.io/router.middlewares: default-rate-limit@kubernetescrd
# HAProxy specific
haproxy.org/rate-limit-requests: '100'
# AWS ALB specific
alb.ingress.kubernetes.io/target-type: ip
While implementing the same functionality (canary deployments, rate limiting, etc.), completely different annotation syntax is used. When migrating from one controller to another, all annotations must be manually converted.
3) Impossibility of Audit and Governance
Annotations are listed flat in the Ingress resource metadata. Identifying security-sensitive settings in an Ingress object with dozens of annotations is virtually impossible. Restricting specific annotations via RBAC is also impossible -- if you can write annotations, you can write all annotations.
3.2 The snippets Annotation: A Vulnerability by Design
The extreme case of the annotation problem is nginx.ingress.kubernetes.io/configuration-snippet and nginx.ingress.kubernetes.io/server-snippet. These annotations allow direct injection of arbitrary NGINX configuration directives.
# Dangerous: Allows injection of arbitrary NGINX configuration
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
# Intended normal use: add custom headers
more_set_headers "X-Custom-Header: value";
# Malicious use: exfiltrate server information
# proxy_pass http://internal-service.kube-system.svc.cluster.local;
# Malicious use: bypass authentication
# satisfy any;
# allow all;
This feature was the direct cause of multiple security vulnerabilities including CVE-2023-5043. With only the permission to create Ingress objects, it was effectively possible to manipulate the entire NGINX process configuration. This is because the configuration-snippet annotation is inserted directly into the location block of the NGINX configuration file, and server-snippet into the server block.
3.3 Gateway API's Annotation-less Model
Gateway API solves this problem with structured API types. Instead of relying on annotations, it expresses configuration through typed CRD fields.
Comparison Example: HTTPS Redirect and Path Rewriting
Legacy Ingress + Annotations approach:
# Ingress approach: relies on annotations
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/proxy-read-timeout: '600'
nginx.ingress.kubernetes.io/proxy-send-timeout: '600'
nginx.ingress.kubernetes.io/proxy-body-size: '100m'
nginx.ingress.kubernetes.io/cors-allow-origin: 'https://example.com'
nginx.ingress.kubernetes.io/cors-allow-methods: 'GET, POST, PUT'
nginx.ingress.kubernetes.io/cors-allow-headers: 'Content-Type, Authorization'
nginx.ingress.kubernetes.io/enable-cors: 'true'
nginx.ingress.kubernetes.io/limit-rps: '100'
nginx.ingress.kubernetes.io/canary: 'true'
nginx.ingress.kubernetes.io/canary-weight: '20'
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 80
Gateway API approach:
# Gateway API approach: structured spec
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app
spec:
parentRefs:
- name: production-gateway
hostnames:
- app.example.com
rules:
# Rule 1: HTTPS redirect (expressed via spec, not annotations)
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
matches:
- headers:
- name: X-Forwarded-Proto
value: http
# Rule 2: API routing
- matches:
- path:
type: PathPrefix
value: /api
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: api-service
port: 80
weight: 80
- name: api-service-canary
port: 80
weight: 20
Key Differences Analysis:
| Aspect | Ingress + Annotations | Gateway API |
|---|---|---|
| Type Safety | None (string key-value) | Yes (CRD schema validation) |
| IDE Support | None | Autocompletion, real-time validation |
| Deploy-time Validation | None (runtime errors) | Admission Webhook validation |
| Canary Deployment | Annotation (vendor-specific) | backendRefs.weight (standard) |
| HTTPS Redirect | Annotation (vendor-specific) | RequestRedirect filter (standard) |
| Path Rewriting | Annotation + regex | URLRewrite filter (standard) |
| RBAC Control | Cannot control per annotation | Resource-level RBAC possible |
| Audit Trail | Difficult | Possible at CRD level |
3.4 Policy Attachment: The True Alternative to Annotations
Gateway API's Policy Attachment model separates cross-cutting concerns that annotations used to handle into independent resources.
# Timeout policy: managed as a separate resource
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: BackendLBPolicy
metadata:
name: api-timeout-policy
spec:
targetRefs:
- group: ''
kind: Service
name: api-service
sessionPersistence:
sessionName: my-session
type: Cookie
---
# TLS policy: backend TLS config separated into its own resource
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
name: api-backend-tls
spec:
targetRefs:
- group: ''
kind: Service
name: api-service
validation:
caCertificateRefs:
- name: backend-ca-cert
group: ''
kind: ConfigMap
hostname: api-internal.example.com
The advantages of this model are clear:
- Separation of Concerns: Routing rules (HTTPRoute) and operational policies (Policy) are managed independently
- Reusability: A single policy can be attached to multiple services
- RBAC Application: Separate RBAC rules can be applied to policy resources
- Audit Ease: Which policies are applied to which targets can be clearly tracked
4. [Takeaway 3] Separation of Roles: Peaceful Coexistence of Infrastructure Administrators and Developers
4.1 Governance Problems with Ingress
One of the fundamental design limitations of the existing Ingress API is the absence of role separation. Infrastructure settings (TLS certificates, listener ports) and application routing rules (path matching, backend services) are mixed within a single Ingress resource.
# Ingress: infrastructure and application settings mixed
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
# Who manages these annotations? Infra team? Dev team?
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: 'true' # Infrastructure concern
nginx.ingress.kubernetes.io/proxy-body-size: '50m' # Infrastructure concern
nginx.ingress.kubernetes.io/rewrite-target: /$1 # Application concern
nginx.ingress.kubernetes.io/canary-weight: '10' # Application concern
spec:
ingressClassName: nginx # Infrastructure concern
tls:
- hosts:
- app.example.com
secretName: production-tls-cert # Infrastructure concern (secret management)
rules:
- host: app.example.com # Mixed concern
http:
paths:
- path: /api/(.*) # Application concern
pathType: ImplementationSpecific
backend:
service:
name: api-service # Application concern
port:
number: 80
In this structure, developers must modify the same resource that contains infrastructure settings to change their routing rules. Conversely, infrastructure administrators must access resources containing application routing rules to replace TLS certificates.
4.2 Gateway API's Role-Based Resource Hierarchy
Gateway API solves this problem with a 3-layer resource model:
┌─────────────────────────────────────────────────────────────┐
│ Layer 1: GatewayClass │
│ ───────────────────── │
│ Owner: Infrastructure Provider (Cloud vendor, Platform team)│
│ Role: Define data plane implementation │
│ Example: "nginx", "envoy", "gke-l7-global" │
│ RBAC: cluster-admin level │
├─────────────────────────────────────────────────────────────┤
│ Layer 2: Gateway │
│ ───────────────── │
│ Owner: Cluster Operator (Platform/Infra Engineer) │
│ Role: Listeners, TLS, IP addresses, ports, allowed NS │
│ Example: Port 443 HTTPS listener, wildcard certificate │
│ RBAC: namespace-admin level (infra namespace) │
├─────────────────────────────────────────────────────────────┤
│ Layer 3: HTTPRoute / GRPCRoute / TCPRoute │
│ ─────────────────────────────────────────── │
│ Owner: Application Developer (Service developer) │
│ Role: Routing rules, backend service mapping, traffic weight│
│ Example: /api → api-service, canary 20% │
│ RBAC: namespace-editor level (application namespace) │
└─────────────────────────────────────────────────────────────┘
Role Responsibility Matrix:
| Role | Resource | Scope of Responsibility | RBAC Example |
|---|---|---|---|
| Infrastructure Provider | GatewayClass | Register data plane implementation, define parameters | ClusterRole: gatewayclass-admin |
| Cluster Operator | Gateway, ReferenceGrant | Listener settings, TLS cert management, NS access control | Role: gateway-admin (infra-ns) |
| Application Developer | HTTPRoute, GRPCRoute | Routing rules, backend service mapping, traffic distribution | Role: route-editor (app-ns) |
4.3 Production RBAC Configuration Example
Step 1: Infrastructure Provider -- GatewayClass Definition
# GatewayClass defined by the infrastructure provider
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx-gateway-fabric
spec:
controllerName: gateway.nginx.org/nginx-gateway-controller
parametersRef:
group: gateway.nginx.org
kind: NginxProxy
name: production-proxy-config
Step 2: Cluster Operator -- Gateway Configuration
# Gateway managed by the cluster operator
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: production-gateway
namespace: gateway-infra # Infrastructure-only namespace
spec:
gatewayClassName: nginx-gateway-fabric
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls-cert
kind: Secret
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: 'true' # Only allowed namespaces
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same
---
# Cross-namespace reference grant
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-gateway-to-app-secrets
namespace: app-team-a
spec:
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: gateway-infra
to:
- group: ''
kind: Service
Step 3: Application Developer -- HTTPRoute Definition
# HTTPRoute managed by developers in their namespace
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-routes
namespace: app-team-a # Application namespace
spec:
parentRefs:
- name: production-gateway
namespace: gateway-infra # Reference Gateway in infra namespace
sectionName: https
hostnames:
- api.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /v1
backendRefs:
- name: api-v1
port: 8080
weight: 80
- name: api-v2
port: 8080
weight: 20 # Canary deployment: 20% traffic to v2
RBAC Policy Example:
# Developer Role: Can only create/modify HTTPRoutes
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: route-editor
namespace: app-team-a
rules:
- apiGroups: ['gateway.networking.k8s.io']
resources: ['httproutes', 'grpcroutes']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['gateway.networking.k8s.io']
resources: ['gateways']
verbs: ['get', 'list'] # Gateway is read-only
---
# Infrastructure operator Role: Can manage Gateway, cannot create Routes
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: gateway-admin
namespace: gateway-infra
rules:
- apiGroups: ['gateway.networking.k8s.io']
resources: ['gateways', 'referencegrants']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['']
resources: ['secrets']
verbs: ['get', 'list', 'watch', 'create', 'update']
The practical value this structure provides is as follows:
- Developer Autonomy: Developers can freely change routing rules in their namespace without approval from the infrastructure team
- Infrastructure Safety: The risk of developers accidentally modifying infrastructure settings such as TLS certificates, listener ports, or allowed namespaces is fundamentally eliminated
- Cross-Namespace Security: Through
ReferenceGrant, referencing resources from other namespaces must be explicitly allowed, preventing unauthorized access - Self-Service Governance: The platform team controls which namespaces can use the Gateway via
allowedRoutes, and development teams operate freely within that scope
5. [Takeaway 4] Breaking Vendor Lock-in: Achieving Portability
5.1 The Essence of the Portability Problem
The reason the Ingress API fails to provide vendor portability is simple: the standard spec is too minimal. The Ingress API spec defines only the bare minimum: host matching, path matching, and TLS termination. All advanced features needed in practice (canary deployments, rate limiting, header manipulation, timeouts, retries, etc.) are independently implemented by each vendor through annotations.
As a result, the moment you write an Ingress resource, you are locked into a specific controller. This directly conflicts with Kubernetes' ideal of "Write once, run anywhere."
┌─────────────────────────────────────────────────────────────┐
│ Ingress API Portability Limitations │
│ │
│ Ingress spec (Standard) Annotations (Non-standard) │
│ ┌───────────────────┐ ┌──────────────────────────────┐ │
│ │ host: app.com │ │ nginx.ingress.k8s.io/... │ │
│ │ path: /api │ │ traefik.ingress.k8s.io/... │ │
│ │ tls: cert │ │ alb.ingress.k8s.io/... │ │
│ │ │ │ haproxy.org/... │ │
│ │ (Portable) │ │ (Non-portable - Vendor-locked)│ │
│ └───────────────────┘ └──────────────────────────────┘ │
│ 20% 80% │
│ Only 20% of actual The remaining 80% depends │
│ config is portable on vendor-specific annotations│
└─────────────────────────────────────────────────────────────┘
5.2 Gateway API's Portability Strategy
Gateway API achieves both portability and extensibility by layering features into 3 support levels:
| Support Level | Description | Portability | Conformance Test |
|---|---|---|---|
| Core | Essential features that all implementations must support | Fully portable | Mandatory pass |
| Extended | Portable features that not all implementations may support | Conditionally portable | Optional pass |
| Implementation-specific | Vendor-specific extension features | Not portable | Not applicable |
Core Features (Fully Portable):
# This HTTPRoute works identically on any Gateway API implementation
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: portable-route
spec:
parentRefs:
- name: my-gateway
hostnames:
- app.example.com
rules:
- matches:
- path:
type: PathPrefix # Core: path matching
value: /api
- headers: # Core: header matching
- name: X-Version
value: v2
filters:
- type: RequestHeaderModifier # Core: header manipulation
requestHeaderModifier:
add:
- name: X-Gateway
value: production
backendRefs:
- name: api-service
port: 8080
Extended Features (Portable but verify implementation support):
# Extended features: supported by most implementations but verify
rules:
- filters:
- type: RequestRedirect # Extended: HTTP redirect
requestRedirect:
scheme: https
statusCode: 301
- type: URLRewrite # Extended: URL rewriting
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /v2
backendRefs:
- name: api-v1
port: 8080
weight: 90 # Extended: traffic weighting (canary)
- name: api-v2
port: 8080
weight: 10
5.3 Conformance Test: The Guarantee of Portability
Gateway API's portability is backed not by mere promises but by a concrete verification mechanism called Conformance Tests.
Each implementation must pass a standardized test suite provided by the Gateway API project. These tests actually create Gateways and Routes, send traffic, and verify that they behave identically to the API specification.
┌─────────────────────────────────────────────────────────────┐
│ Conformance Test Process │
│ │
│ 1. Run Gateway API test suite │
│ └─> Deploy standard Gateway/HTTPRoute resources │
│ │
│ 2. Send actual traffic and verify behavior │
│ └─> Path matching, header filtering, redirects, etc. │
│ │
│ 3. Generate results report │
│ └─> Core 100%, Extended features list │
│ │
│ 4. Official certification (Conformance Profile) │
│ └─> Listed in official Gateway API implementations │
└─────────────────────────────────────────────────────────────┘
Conformance Status by Major Implementation:
| Implementation | Core Conformance | Extended Features | Notes |
|---|---|---|---|
| NGINX Gateway Fabric | Pass | HTTP routing, TLS, URL rewriting, weight-based distribution | NGINX data plane |
| Envoy Gateway | Pass | All Extended features supported | Envoy Proxy data plane |
| GKE Gateway Controller | Pass | GCP native integration | Google Cloud only |
| Istio | Pass | Service mesh integration | Istio data plane |
| Contour | Pass | Envoy-based | VMware supported |
| Traefik | Pass | Middleware integration | v3+ support |
5.4 Practical Portability Scenario: Multi-Cloud Migration
The portability guaranteed by Conformance Tests delivers real value in multi-cloud operations:
┌──────────────────┐ ┌──────────────────┐
│ AWS EKS │ │ Azure AKS │
│ │ │ │
│ GatewayClass: │ │ GatewayClass: │
│ aws-gateway │ │ azure-gateway │
│ (change impl) │ │ (change impl) │
│ │ │ │
│ Gateway: ───────┼─────┼─ Gateway: ──────┐│
│ (minimal edits) │ │ (minimal edits) ││
│ │ │ ││
│ HTTPRoute: ─────┼─────┼─ HTTPRoute: ────┘│
│ (reuse as-is) │ │ (reuse as-is) │
└──────────────────┘ └──────────────────┘
│ │
└───────┬────────────────┘
│
Same HTTPRoute manifests reused
by only changing GatewayClass
With the legacy Ingress approach, moving from AWS ALB Ingress Controller to GKE Ingress Controller required rewriting all annotations. With Gateway API, by only changing the GatewayClass, the remaining resources (Gateway, HTTPRoute) can be reused as-is within the scope of Core/Extended features.
6. [Takeaway 5] The Performance Leap: Full-Scale Adoption of HTTP/3 and QUIC
6.1 Why HTTP/3: The Structural Limitations of TCP
HTTP/2 enabled processing multiple streams simultaneously on the same TCP connection through multiplexing. However, it failed to solve the Head-of-Line (HOL) Blocking problem inherent in the TCP protocol itself.
HTTP/2 over TCP Head-of-Line Blocking:
TCP Connection
┌─────────────────────────────────────────────────┐
│ Stream 1: [Pkt1][Pkt2][ Lost ][Pkt4] │
│ Stream 2: [PktA][PktB] ← Wait [PktD] │ ← Blocked!
│ Stream 3: [PktX][PktY] ← Wait [PktZ] │ ← Blocked!
└─────────────────────────────────────────────────┘
Pkt3 lost → All streams wait
HTTP/3 over QUIC Independent Streams:
QUIC Connection
┌─────────────────────────────────────────────────┐
│ Stream 1: [Pkt1][Pkt2][ Lost ][Pkt4] │ ← Only this stream affected
│ Stream 2: [PktA][PktB][PktC] [PktD] │ ← Proceeds normally!
│ Stream 3: [PktX][PktY][PktZ] │ ← Proceeds normally!
└─────────────────────────────────────────────────┘
Pkt3 lost → Only Stream 1 affected
HTTP/3 uses the QUIC (Quick UDP Internet Connections) protocol instead of TCP. QUIC is built on top of UDP, and each stream is delivered independently. Packet loss in one stream does not affect other streams.
6.2 Key Performance Benefits of HTTP/3
| Feature | HTTP/2 (TCP) | HTTP/3 (QUIC) | Improvement |
|---|---|---|---|
| Transport Layer | TCP | UDP + QUIC | Reduced kernel dependency |
| Connection Establishment | TCP 3-way handshake + TLS handshake (2-3 RTT) | QUIC 0-RTT / 1-RTT | Up to 67% latency reduction |
| HOL Blocking | Occurs at TCP level | Isolated to stream level | Improved parallel processing |
| Connection Migration | Reconnection needed on IP/port change | Maintained via Connection ID | Mobile environment stability |
| Encryption | TLS optional | TLS 1.3 mandatory (built-in) | Default encryption guaranteed |
| Packet Loss Recovery | Affects entire connection | Independent per-stream recovery | Better lossy network performance |
6.3 HTTP/3 Support in NGINX Gateway Fabric
NGINX officially supports QUIC and HTTP/3 since v1.25.0, and HTTP/3 can be leveraged in Kubernetes environments through NGINX Gateway Fabric.
NginxProxy Configuration for HTTP/3 Activation:
apiVersion: gateway.nginx.org/v1alpha1
kind: NginxProxy
metadata:
name: http3-enabled-proxy
spec:
config:
http:
http3: true
http3MaxConcurrentStreams: 128
altSvcHeader: true # Automatically add Alt-Svc header
Gateway HTTP/3 Listener Configuration:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: http3-gateway
namespace: gateway-infra
spec:
gatewayClassName: nginx-gateway-fabric
listeners:
# HTTPS (TCP) + HTTP/3 (UDP) simultaneous listening
- name: https-tcp
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls-cert
- name: https-udp
protocol: HTTPS # HTTP/3 declared as HTTPS protocol
port: 443 # Same port, QUIC handled over UDP
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls-cert
Exposing UDP Port in Service:
apiVersion: v1
kind: Service
metadata:
name: nginx-gateway-fabric
namespace: gateway-infra
spec:
type: LoadBalancer
ports:
- name: https-tcp
port: 443
targetPort: 443
protocol: TCP
- name: https-udp
port: 443
targetPort: 443
protocol: UDP # UDP port required for QUIC
6.4 HTTP/3 Adoption Considerations
There are technical requirements and considerations that must be verified when adopting HTTP/3:
1) SSL Library Requirements
QUIC protocol support requires a QUIC-compatible SSL library. Standard OpenSSL does not support the QUIC API (as of OpenSSL 3.x), so one of the following alternatives must be used:
| SSL Library | QUIC Support | Notes |
|---|---|---|
| BoringSSL | Native support | Developed by Google, default in NGINX Gateway Fabric |
| LibreSSL | 3.6.0+ support | OpenBSD project |
| QuicTLS | OpenSSL + QUIC patch | OpenSSL fork with QUIC API added |
| OpenSSL | Not supported (3.x) | Future support planned |
NGINX Gateway Fabric is built with BoringSSL by default, so HTTP/3 can be used without any SSL library replacement.
2) Firewall and Network Configuration
┌─────────────────────────────────────────────────────────┐
│ HTTP/3 Network Requirements │
│ │
│ UDP 443 must be added to inbound rules: │
│ │
│ Before (HTTP/2 only): │
│ ┌──────────────────────────────────────┐ │
│ │ TCP 80 ← HTTP │ │
│ │ TCP 443 ← HTTPS (TLS over TCP) │ │
│ └──────────────────────────────────────┘ │
│ │
│ After adding HTTP/3: │
│ ┌──────────────────────────────────────┐ │
│ │ TCP 80 ← HTTP │ │
│ │ TCP 443 ← HTTPS (TLS over TCP) │ │
│ │ UDP 443 ← QUIC (HTTP/3 over UDP) │ ← Must add │
│ └──────────────────────────────────────┘ │
│ │
│ Note: Many enterprise firewalls and cloud security │
│ groups block UDP 443 by default. │
└─────────────────────────────────────────────────────────┘
- Cloud Security Groups: UDP 443 inbound must be explicitly allowed in AWS Security Groups, Azure NSGs, GCP Firewall Rules
- CDN/WAF Compatibility: Some CDNs or WAFs may block or improperly handle QUIC traffic
- Load Balancer Support: Verify that cloud load balancers correctly route UDP traffic. AWS NLB, Azure Load Balancer, and GCP Network Load Balancer support UDP
3) Gradual Transition via Alt-Svc Header
HTTP/3 adoption can proceed gradually. The server includes an Alt-Svc header in HTTP/2 responses to inform clients that HTTP/3 is available:
Alt-Svc: h3=":443"; ma=86400
After receiving this header, the client attempts HTTP/3 on subsequent requests. If it fails, it automatically falls back to HTTP/2. As of 2025, Chrome 87+, Firefox 88+, Safari 14+, and more than 95% of all browsers support HTTP/3.
4) QUIC Connection Migration with eBPF
Linux 5.7+ kernels support QUIC packet routing using eBPF. This enables QUIC's Connection Migration feature, allowing connections to persist even when the client's network changes (e.g., switching from Wi-Fi to LTE).
# Enable eBPF-based QUIC routing in nginx.conf
quic_bpf on; # Requires Linux 5.7+
7. Practical Migration Guide
7.1 Migration Strategy Overview
Migration from Ingress NGINX to Gateway API should follow a Progressive Migration approach rather than a Big Bang approach.
┌──────────────────────────────────────────────────────────────┐
│ Progressive Migration Strategy │
│ │
│ Phase 1: Inventory and Assessment (1-2 weeks) │
│ ├─ Catalog all Ingress resources │
│ ├─ Classify annotations in use │
│ ├─ Identify snippets usage (priority: security risk removal)│
│ └─ Map dependencies (cert-manager, external-dns, etc.) │
│ │
│ Phase 2: Build Gateway API Infrastructure (1-2 weeks) │
│ ├─ Install Gateway API CRDs │
│ ├─ Deploy NGINX Gateway Fabric or alternative controller │
│ ├─ Create GatewayClass, Gateway resources │
│ └─ Validate in non-production environment │
│ │
│ Phase 3: Progressive Routing Transition (2-4 weeks) │
│ ├─ Initial conversion with ingress2gateway tool │
│ ├─ Manual review & annotation → filter/policy conversion │
│ ├─ Sequential per-service transition (non-critical → critical)│
│ └─ Parallel operation period (Ingress + Gateway API) │
│ │
│ Phase 4: Full Transition and Cleanup (1-2 weeks) │
│ ├─ Confirm all traffic routes through Gateway API │
│ ├─ Remove Ingress resources │
│ ├─ Remove ingress-nginx controller │
│ └─ Reconfigure monitoring and alerts │
└──────────────────────────────────────────────────────────────┘
7.2 Phase 1: Inventory Collection
Query all Ingress resources:
# List all Ingress resources across all namespaces
kubectl get ingress -A -o wide
# Extract all annotations in use
kubectl get ingress -A -o json | \
jq -r '.items[].metadata.annotations // {} | keys[]' | \
sort | uniq -c | sort -rn
# Urgent check for snippets annotations (security risk)
kubectl get ingress -A -o json | \
jq -r '.items[] | select(.metadata.annotations["nginx.ingress.kubernetes.io/configuration-snippet"] != null or .metadata.annotations["nginx.ingress.kubernetes.io/server-snippet"] != null) | .metadata.namespace + "/" + .metadata.name'
# Check IngressClass
kubectl get ingressclass
Annotation Classification Checklist:
| Classification | Annotation Examples | Gateway API Replacement | Urgency |
|---|---|---|---|
| Security Risk | configuration-snippet, server-snippet | Remove or Custom Filter | Immediate |
| Standard Replaceable | ssl-redirect, rewrite-target | RequestRedirect, URLRewrite filter | High |
| Policy Replaceable | proxy-read-timeout, proxy-body-size | Policy Attachment | Medium |
| Feature Replaceable | canary, canary-weight | backendRefs.weight | Medium |
| Implementation Dependent | upstream-hash-by, affinity | Check implementation-specific CRDs | Low |
7.3 Phase 2: Using the ingress2gateway Tool
ingress2gateway is an official migration tool provided by Kubernetes SIG-Network.
Installation:
# With Go environment
go install github.com/kubernetes-sigs/ingress2gateway@latest
# Or download binary from GitHub Releases
# https://github.com/kubernetes-sigs/ingress2gateway/releases
Basic Usage:
# Auto-convert Ingress resources from the cluster
ingress2gateway print --all-namespaces
# Convert specific namespace only
ingress2gateway print --namespace production
# File-based conversion
ingress2gateway print --input-file ingress-resources.yaml
# Specify ingress-nginx provider (annotation conversion support)
ingress2gateway print --providers ingress-nginx --all-namespaces
# Save results to file
ingress2gateway print --providers ingress-nginx --all-namespaces > gateway-resources.yaml
Important Note: ingress2gateway is only a starting point and does not perfectly convert all annotations. Implementation-specific features (snippets, custom Lua scripts, etc.) must be manually redesigned. Always review conversion results and thoroughly test in a non-production environment before applying.
7.4 Phase 3: Deploying NGINX Gateway Fabric
Installation via Helm:
# Install Gateway API CRDs
kubectl kustomize \
"https://github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.1" \
| kubectl apply -f -
# Install NGINX Gateway Fabric
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
--create-namespace \
--namespace nginx-gateway \
--set service.type=LoadBalancer
Verify GatewayClass:
# Check GatewayClass after installation
kubectl get gatewayclass
# NAME CONTROLLER ACCEPTED
# nginx gateway.nginx.org/nginx-gateway-controller True
Create and Validate Gateway:
# Apply Gateway resource
kubectl apply -f gateway.yaml
# Check Gateway status
kubectl get gateway -n gateway-infra
# NAME CLASS ADDRESS PROGRAMMED AGE
# production-gateway nginx 203.0.113.10 True 5m
# Apply HTTPRoute
kubectl apply -f httproute.yaml
# Check HTTPRoute status
kubectl get httproute -n app-team-a
# NAME HOSTNAMES AGE
# api-routes ["api.example.com"] 2m
# Test with actual traffic
curl -H "Host: api.example.com" https://203.0.113.10/v1/health
7.5 Ingress vs Gateway API Feature Comparison Summary
| Feature | Ingress API | Gateway API | Notes |
|---|---|---|---|
| Host-based Routing | spec.rules[].host | spec.hostnames | Equivalent |
| Path-based Routing | spec.rules[].http.paths | spec.rules[].matches[].path | Gateway API more flexible |
| TLS Termination | spec.tls | Gateway.listeners[].tls | Role separation (managed at Gateway) |
| HTTPS Redirect | Annotation (vendor-specific) | RequestRedirect filter (standard) | Gateway API advantage |
| URL Rewriting | Annotation (vendor-specific) | URLRewrite filter (standard) | Gateway API advantage |
| Canary Deployment | Annotation (vendor-specific) | backendRefs.weight (standard) | Gateway API advantage |
| Header Matching | Not supported (annotation only) | spec.rules[].matches[].headers | Gateway API advantage |
| Header Manipulation | Annotation (vendor-specific) | RequestHeaderModifier filter | Gateway API advantage |
| Traffic Mirroring | Annotation (vendor-specific) | RequestMirror filter (Extended) | Gateway API advantage |
| Timeouts | Annotation (vendor-specific) | HTTPRoute timeouts (v1.2+) | Gateway API advantage |
| Retries | Annotation (vendor-specific) | HTTPRoute retry (v1.2+) | Gateway API advantage |
| gRPC Routing | Not supported (annotation only) | GRPCRoute (GA) | Gateway API advantage |
| TCP/UDP Routing | Not supported | TCPRoute, UDPRoute (Experimental) | Gateway API advantage |
| Role-based Separation | Not supported | GatewayClass/Gateway/Route separation | Gateway API advantage |
| Cross-Namespace | Not supported | ReferenceGrant | Gateway API advantage |
| Vendor Portability | Low (annotation-dependent) | High (Conformance Test) | Gateway API advantage |
| Backend TLS | Annotation (vendor-specific) | BackendTLSPolicy (v1.4 GA) | Gateway API advantage |
| WebSocket | Annotation (vendor-specific) | Standard support (v1.2+) | Gateway API advantage |
8. Comprehensive Migration Checklist
Below is a comprehensive checklist for transitioning from Ingress NGINX to Gateway API. Adapt it to your organization's situation.
8.1 Assessment Phase
- Complete inventory of all Ingress resources and namespace mapping across all clusters
- Complete audit of all Ingress NGINX annotations in use
- Confirm
configuration-snippet/server-snippetusage and assess security risk - Verify ingress-nginx controller version (CVE-2025-1974 patch status)
- Identify dependencies on integrated systems (cert-manager, external-dns, etc.)
- Document current traffic patterns and routing rules
8.2 Planning Phase
- Select target Gateway API implementation (NGINX Gateway Fabric, Envoy Gateway, etc.)
- Establish GatewayClass/Gateway/Route role separation policy
- Design namespace strategy (infrastructure vs. application)
- Design RBAC policy (infrastructure team vs. development team privilege separation)
- Determine migration order (non-critical services first)
- Establish rollback plan
- Decide on HTTP/3 adoption
8.3 Execution Phase
- Install Gateway API CRDs (
gateway.networking.k8s.io) - Deploy Gateway API implementation controller
- Create GatewayClass resource and verify status (
ACCEPTED: True) - Create Gateway resource and confirm IP address allocation (
PROGRAMMED: True) - Run initial conversion with
ingress2gatewaytool - Manually review conversion results and supplement missing features
- Test converted HTTPRoutes in non-production environment
- Gradually shift traffic using DNS weight-based routing
- Production environment transition and monitoring
8.4 Validation Phase
- Confirm normal responses for all routing paths
- Verify TLS certificate termination and renewal work correctly
- Confirm canary/weight-based deployment behavior
- Verify header-based routing behavior
- Confirm error pages and default backend behavior
- Verify monitoring and alerting work correctly
- Perform load testing and compare against performance baseline
8.5 Cleanup Phase
- Remove legacy Ingress resources
- Remove ingress-nginx controller Deployment/DaemonSet
- Clean up ingress-nginx related ConfigMaps, ServiceAccounts, RBAC resources
- Remove ingress-nginx Service (LoadBalancer) and reclaim IP addresses
- Clean up Helm releases (if applicable)
- Remove or replace Ingress-related manifests in CI/CD pipelines with Gateway API
- Remove ingress-nginx modules from IaC (Terraform, Pulumi, etc.)
- Team training and operational documentation update
9. Conclusion: It Is Time to Act
The retirement of Ingress NGINX is not simply an event where one controller disappears. It is a turning point for the entire Kubernetes networking paradigm.
Summary: 5 Key Changes and Response Directions
| # | Change | Key Message | Immediate Action |
|---|---|---|---|
| 1 | Ingress NGINX EOL | No security patches after March 2026 | Begin migration planning |
| 2 | Escape Annotations | Structural flaws directly lead to vulnerabilities | Remove snippets usage immediately |
| 3 | Role Separation | GatewayClass/Gateway/Route 3-layer model | Redesign RBAC policies |
| 4 | Vendor Portability | Conformance Test-based standardization | Revisit multi-cloud strategy |
| 5 | HTTP/3 & QUIC | Next-gen protocol based on UDP | Review firewall UDP 443 opening |
3 Actions to Execute Right Now:
1. Collect Inventory (Today)
# Execute this right now
kubectl get ingress -A -o json | \
jq -r '[.items[] | {
namespace: .metadata.namespace,
name: .metadata.name,
annotations: (.metadata.annotations // {} | keys | length),
has_snippets: ((.metadata.annotations // {}) |
has("nginx.ingress.kubernetes.io/configuration-snippet") or
has("nginx.ingress.kubernetes.io/server-snippet"))
}]'
2. Run ingress2gateway Tool (This Week)
go install github.com/kubernetes-sigs/ingress2gateway@latest
ingress2gateway print --providers ingress-nginx -A > gateway-migration.yaml
3. Build NGINX Gateway Fabric Test Environment (This Month)
# Test on a non-production cluster
kubectl kustomize \
"https://github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.1" \
| kubectl apply -f -
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
--create-namespace --namespace nginx-gateway
The experience and lessons the Kubernetes community has built over a decade are distilled into Gateway API as the new standard. It is time to move from the annotation swamp to type-safe APIs, from mixed single resources to role-based separation, and from vendor lock-in to the freedom of portability.
The March 2026 deadline is not a threat but an opportunity. Through this transition, you can build more secure, more flexible, and more standardized networking infrastructure. Start now.
10. References
Official Documentation and Announcements
- Ingress NGINX Retirement: What You Need to Know | Kubernetes Blog
- Gateway API v1.2: WebSockets, Timeouts, Retries, and More | Kubernetes Blog
- Gateway API v1.4: New Features | Kubernetes Blog
- Gateway API Official Documentation
- Gateway API Conformance
- Ingress-nginx CVE-2025-1974: What You Need to Know | Kubernetes Blog
NGINX Gateway Fabric
- F5 NGINX Gateway Fabric Documentation
- NGINX Gateway Fabric GitHub
- What's New in F5 NGINX Gateway Fabric 2.3.0
- Gateway Architecture | NGINX Documentation
- Gateway API Compatibility | NGINX Documentation
Security and CVE
- IngressNightmare: CVE-2025-1974 | Wiz Blog
- Detecting and Mitigating IngressNightmare | Sysdig
- IngressNightmare CVE-2025-1974 | FortiGuard Labs
Migration Guides
- Migrating from Ingress | Gateway API Documentation
- Migrating from Ingress-NGINX | Gateway API Documentation
- ingress2gateway GitHub
- Introducing ingress2gateway | Kubernetes Blog
Cloud Vendors
- AKS Application Routing Add-on Ingress-NGINX Update | AKS Engineering Blog
- The End of an Era: Transitioning Away from Ingress NGINX | Google Open Source Blog
HTTP/3 and QUIC
- Support for QUIC and HTTP/3 | NGINX Documentation
- Module ngx_http_v3_module | NGINX Documentation
- 5 Reasons to Try the Kubernetes Gateway API | NGINX Blog
Quiz
Q1: What is the main topic covered in "The Death and Resurrection of Kubernetes Networking: 5
Changes You Must Know Before March 2026"?
From the March 2026 EOL of Ingress NGINX, the transition to Gateway API, eliminating annotation technical debt, role-based resource separation, vendor portability, to the adoption of HTTP/3 and QUIC -- an in-depth analysis of 5 critical changes in Kubernetes networking and a prac...
Q2: What is [Takeaway 1] The Countdown of a Time Bomb: The Official Retirement of Ingress NGINX?
2.1 What Is Being Retired: Precise Scope Definition To prevent confusion, let's clarify something. What is being retired is the kubernetes/ingress-nginx controller project. The GA (General Availability) Ingress API itself (networking.k8s.io/v1) is still supported in Kubernetes.
Q3: Explain the core concept of [Takeaway 2] Escaping the Annotation Swamp.
3.1 Structural Flaws of Annotation-Based Configuration The most fundamental limitation of the
Ingress API is lack of expressiveness. The Ingress resource spec only supports the most basic
features: host-based routing and path-based routing.
Q4: What are the key aspects of [Takeaway 3] Separation of Roles: Peaceful Coexistence of
Infrastructure Administrators and Developers?
4.1 Governance Problems with Ingress One of the fundamental design limitations of the existing Ingress API is the absence of role separation.
Q5: How does [Takeaway 4] Breaking Vendor Lock-in: Achieving Portability work?
5.1 The Essence of the Portability Problem The reason the Ingress API fails to provide vendor
portability is simple: the standard spec is too minimal. The Ingress API spec defines only the
bare minimum: host matching, path matching, and TLS termination.