K8s Gateway API란?
Kubernetes Gateway API는 기존 Ingress 리소스의 한계를 극복하기 위해 SIG-Network에서 설계한 차세대 트래픽 라우팅 표준이다. Ingress가 단일 리소스에 모든 설정을 몰아넣는 반면, Gateway API는 역할 기반 분리(Role-Oriented Design)를 핵심 원칙으로 삼아 인프라 관리자와 애플리케이션 개발자의 관심사를 명확히 나눈다.
2023년 v1.0 GA를 달성했고, 2025년 현재 v1.2까지 발전하며 gRPC, TLS Passthrough, Backend TLS Policy 등이 표준 채널에 포함되었다. NGINX, Istio, Cilium, Envoy Gateway, Traefik 등 주요 구현체가 모두 지원하고 있어 프로덕션 도입 시점이다.
핵심 리소스 3계층 구조
Gateway API의 가장 큰 특징은 3계층 리소스 모델이다. 각 계층이 서로 다른 역할(Persona)에 매핑된다.
1. GatewayClass — 인프라 제공자
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: production-gateway
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: custom-proxy-config
namespace: envoy-gateway-system
GatewayClass는 클러스터 범위 리소스로, 어떤 컨트롤러가 Gateway를 관리할지 정의한다. Kubernetes의 StorageClass와 동일한 패턴이다. 인프라 팀이 관리하며, 개발자는 이미 정의된 GatewayClass를 참조만 한다.
2. Gateway — 클러스터 운영자
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: api-gateway
namespace: infra
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
gatewayClassName: production-gateway
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: api-tls-cert
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: "true"
- name: grpc
protocol: HTTPS
port: 8443
hostname: "grpc.example.com"
tls:
mode: Terminate
certificateRefs:
- name: grpc-tls-cert
allowedRoutes:
kinds:
- kind: GRPCRoute
Gateway는 실제 로드밸런서/프록시 인스턴스를 나타낸다. 리스너별로 프로토콜, 포트, TLS 설정, 허용 네임스페이스를 세밀하게 제어할 수 있다. 핵심은 allowedRoutes로, 어떤 네임스페이스의 어떤 종류의 Route만 이 Gateway에 붙을 수 있는지 제한한다.
3. HTTPRoute — 애플리케이션 개발자
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: order-service
namespace: shop
spec:
parentRefs:
- name: api-gateway
namespace: infra
sectionName: https
hostnames:
- "api.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api/v2/orders
headers:
- name: X-Api-Version
value: "2"
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: X-Route-Version
value: "v2"
backendRefs:
- name: order-service-v2
port: 8080
weight: 90
- name: order-service-v3
port: 8080
weight: 10
개발자는 자신의 네임스페이스에서 HTTPRoute만 생성하면 된다. parentRefs로 어떤 Gateway에 연결할지 지정하고, 나머지는 표준화된 매칭·필터·백엔드 설정을 사용한다. Ingress와 달리 어노테이션 없이 모든 기능을 선언적으로 표현할 수 있다.
Ingress 대비 핵심 개선점
| 비교 항목 | Ingress | Gateway API |
|---|---|---|
| 역할 분리 | ❌ 단일 리소스에 모든 설정 | ✅ GatewayClass → Gateway → Route 3계층 |
| 크로스 네임스페이스 | ❌ 불가능 | ✅ ReferenceGrant로 안전하게 허용 |
| 헤더 매칭 | ❌ 비표준 어노테이션 | ✅ 표준 spec으로 지원 |
| 트래픽 분할 | ❌ 컨트롤러마다 다름 | ✅ weight 기반 표준 지원 |
| gRPC 라우팅 | ❌ 미지원 | ✅ GRPCRoute 표준 리소스 |
| 확장성 | ⚠️ 어노테이션 남발 | ✅ Policy Attachment 패턴 |
ReferenceGrant: 크로스 네임스페이스 보안
Gateway API에서 가장 혁신적인 보안 메커니즘이 ReferenceGrant다. 다른 네임스페이스의 리소스를 참조하려면 대상 네임스페이스에서 명시적으로 허용해야 한다.
# backend 네임스페이스의 서비스를 shop 네임스페이스의 HTTPRoute가 참조하도록 허용
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-shop-routes
namespace: backend # 참조 "대상"이 있는 네임스페이스
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: shop # 참조를 "하는" 네임스페이스
to:
- group: ""
kind: Service
이 패턴 덕분에 멀티테넌트 클러스터에서 안전하게 공유 Gateway를 운영할 수 있다. 인프라 팀이 Gateway를 infra 네임스페이스에 두고, 각 팀은 자기 네임스페이스에서 Route만 생성하는 구조다.
카나리 배포: weight 기반 트래픽 분할
Ingress에서 카나리 배포는 nginx.ingress.kubernetes.io/canary-weight 같은 비표준 어노테이션에 의존했다. Gateway API는 backendRefs의 weight를 표준으로 지원한다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-deploy
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /api/products
backendRefs:
- name: product-stable
port: 8080
weight: 95
- name: product-canary
port: 8080
weight: 5
weight를 점진적으로 조정하면서 5% → 25% → 50% → 100%로 트래픽을 이동시킨다. ArgoCD Rollout이나 Flagger와 연동하면 자동 카나리 분석도 가능하다.
헤더 기반 A/B 테스트 라우팅
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ab-test-route
spec:
parentRefs:
- name: api-gateway
rules:
# A/B 테스트 그룹 B → 신규 서비스로 라우팅
- matches:
- headers:
- name: X-Experiment-Group
value: "group-b"
path:
type: PathPrefix
value: /api/checkout
backendRefs:
- name: checkout-experiment
port: 8080
# 기본 트래픽 → 기존 서비스
- matches:
- path:
type: PathPrefix
value: /api/checkout
backendRefs:
- name: checkout-stable
port: 8080
규칙은 위에서 아래로 순서대로 평가된다. 더 구체적인 매칭(헤더 포함)을 위에 배치하면 자연스럽게 폴백 구조가 만들어진다.
GRPCRoute: gRPC 네이티브 라우팅
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: grpc-order-service
spec:
parentRefs:
- name: api-gateway
sectionName: grpc
hostnames:
- "grpc.example.com"
rules:
- matches:
- method:
service: order.v1.OrderService
method: CreateOrder
backendRefs:
- name: order-grpc-v2
port: 50051
- matches:
- method:
service: order.v1.OrderService
backendRefs:
- name: order-grpc-v1
port: 50051
GRPCRoute는 gRPC 서비스명과 메서드명으로 직접 매칭할 수 있다. 특정 RPC 메서드만 새 버전으로 라우팅하는 세밀한 트래픽 제어가 가능하다.
Policy Attachment: 확장 기능 표준화
Ingress의 가장 큰 문제는 어노테이션 남발이었다. Gateway API는 Policy Attachment 패턴으로 이를 해결한다. Rate limiting, timeout, retry 같은 정책을 별도 리소스로 분리해서 Gateway나 Route에 붙이는 방식이다.
# Envoy Gateway의 BackendTrafficPolicy 예시
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: order-timeout-policy
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: order-service
rateLimit:
type: Global
global:
rules:
- clientSelectors:
- headers:
- name: X-User-Tier
value: free
limit:
requests: 100
unit: Minute
timeout:
http:
connectionIdleTimeout: 60s
requestTimeout: 30s
retry:
numRetries: 3
retryOn:
- "5xx"
- "reset"
perRetry:
timeout: 5s
이 패턴의 장점은 정책을 라우팅과 분리할 수 있다는 것이다. SRE 팀이 정책을, 개발팀이 라우팅을 각각 관리할 수 있다.
TLS Passthrough: TCP/TLS 터널링
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tls-passthrough-gw
spec:
gatewayClassName: production-gateway
listeners:
- name: tls-pass
protocol: TLS
port: 443
hostname: "secure.example.com"
tls:
mode: Passthrough
allowedRoutes:
kinds:
- kind: TLSRoute
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: secure-backend
spec:
parentRefs:
- name: tls-passthrough-gw
sectionName: tls-pass
rules:
- backendRefs:
- name: secure-app
port: 8443
TLS Passthrough 모드에서는 Gateway가 TLS를 종료하지 않고 SNI 기반으로 백엔드에 그대로 전달한다. 금융, 의료 등 end-to-end 암호화가 필수인 환경에서 사용한다.
실전 마이그레이션: Ingress → Gateway API
기존 Ingress에서 Gateway API로의 마이그레이션은 점진적으로 진행해야 한다.
Step 1: CRD 설치
# Gateway API 표준 CRD 설치 (v1.2.0)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
# 실험적 채널 (TLSRoute, TCPRoute 등 포함)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml
Step 2: 구현체 설치 (Envoy Gateway 예시)
helm install envoy-gateway oci://docker.io/envoyproxy/gateway-helm
--version v1.2.0
-n envoy-gateway-system --create-namespace
Step 3: 기존 Ingress를 HTTPRoute로 변환
# 기존 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
tls:
- hosts: ["api.example.com"]
secretName: api-tls
rules:
- host: api.example.com
http:
paths:
- path: /v1(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-v1
port:
number: 8080
# ↓ 변환된 Gateway API
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-route
spec:
parentRefs:
- name: api-gateway
hostnames:
- "api.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /v1
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: api-v1
port: 8080
Step 4: 병행 운영 후 Ingress 제거
두 시스템을 동시에 운영하며 트래픽을 점진 이동한 후, 모든 Route가 정상 동작하면 Ingress를 제거한다. ingress2gateway CLI 도구를 활용하면 자동 변환도 가능하다.
# ingress2gateway로 자동 변환
go install github.com/kubernetes-sigs/ingress2gateway@latest
ingress2gateway print --input-file ingress.yaml
운영 트러블슈팅 체크리스트
Route가 Gateway에 붙지 않을 때
# Route 상태 확인
kubectl get httproute order-service -o jsonpath='{.status.parents}' | jq .
# 확인할 것:
# 1. parentRefs의 Gateway 이름/네임스페이스가 정확한가?
# 2. Gateway의 allowedRoutes.namespaces 설정이 Route의 네임스페이스를 허용하는가?
# 3. ReferenceGrant가 필요한 경우 생성했는가?
# 4. Gateway의 listeners[].allowedRoutes.kinds에 해당 Route 종류가 포함되는가?
status.conditions 해석
# Gateway 상태 확인
kubectl get gateway api-gateway -o yaml
# 주요 Condition:
# - Accepted: GatewayClass 컨트롤러가 이 Gateway를 인식했는가
# - Programmed: 실제 데이터 플레인에 설정이 반영되었는가
# - ResolvedRefs: 참조하는 Secret/Service가 모두 존재하는가
Ingress와 공존: 마이그레이션 전략
대부분의 Gateway API 구현체는 Ingress와 동시에 운영 가능하다. 권장 전략은 다음과 같다.
- 신규 서비스는 처음부터 HTTPRoute로 생성
- 기존 서비스는 Ingress를 유지하면서 HTTPRoute를 병행 생성
- DNS를 Gateway의 외부 IP로 점진 전환 (weighted DNS)
- 모니터링으로 안정성 확인 후 Ingress 제거
Gateway API는 단순한 Ingress 대체가 아니라 Kubernetes 네트워킹의 패러다임 전환이다. 역할 기반 설계, 크로스 네임스페이스 보안, 표준화된 트래픽 관리를 통해 멀티팀 환경에서의 운영 복잡도를 근본적으로 줄여준다. 아직 Ingress를 쓰고 있다면, 지금이 전환을 시작할 적기다.