- Published on
Kubernetes Gateway API 실전 마이그레이션 — Ingress에서 Gateway로
- Authors
- Name

들어가며
Kubernetes의 네트워킹 스택이 진화하고 있습니다. 오랫동안 표준이었던 Ingress API는 이제 Gateway API로 대체되는 흐름입니다. Gateway API는 2023년 GA(General Availability)를 달성했고, 2025년부터는 대부분의 Ingress Controller가 Gateway API를 지원하기 시작했습니다.
이 글에서는 기존 Ingress 리소스를 Gateway API로 마이그레이션하는 실전 과정을 단계별로 살펴봅니다.
Ingress vs Gateway API: 왜 전환해야 하나?
Ingress의 한계
Ingress API는 단순한 HTTP 라우팅에는 충분하지만, 다음과 같은 한계가 있습니다:
- 역할 분리 불가: 인프라 관리자와 애플리케이션 개발자의 관심사가 하나의 리소스에 섞임
- 제한된 프로토콜: HTTP/HTTPS만 지원, TCP/UDP/gRPC는 비표준 어노테이션 필요
- 벤더 종속: nginx, traefik 등 구현체마다 다른 어노테이션
- 헤더 기반 라우팅 미지원: 가중치 기반 트래픽 분할 불가
Gateway API의 장점
┌─────────────────────────────────────┐
│ GatewayClass │ ← 인프라 제공자 (플랫폼 팀)
├─────────────────────────────────────┤
│ Gateway │ ← 클러스터 운영자
├─────────────────────────────────────┤
│ HTTPRoute / TCPRoute / GRPCRoute │ ← 애플리케이션 개발자
└─────────────────────────────────────┘
- 역할 기반 설계: GatewayClass → Gateway → Route 3계층으로 관심사 분리
- 풍부한 라우팅: 헤더, 쿼리 파라미터, 메서드 기반 매칭
- 멀티 프로토콜: HTTP, gRPC, TCP, UDP, TLS 네이티브 지원
- 이식성: 표준 API로 벤더 종속 최소화
핵심 리소스 이해하기
GatewayClass
인프라 제공자가 정의하는 최상위 리소스입니다. 어떤 컨트롤러가 Gateway를 관리할지 지정합니다.
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx
spec:
controllerName: gateway.nginx.org/nginx-gateway-controller
Gateway
실제 리스너(포트, 프로토콜)를 정의합니다. 클러스터 운영자가 관리합니다.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: main-gateway
namespace: infra
spec:
gatewayClassName: nginx
listeners:
- name: http
protocol: HTTP
port: 80
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: wildcard-cert
kind: Secret
allowedRoutes:
namespaces:
from: All
HTTPRoute
애플리케이션 개발자가 라우팅 규칙을 정의합니다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app-route
namespace: app-ns
spec:
parentRefs:
- name: main-gateway
namespace: infra
hostnames:
- "app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-service
port: 8080
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend-service
port: 3000
실전 마이그레이션 단계
Step 1: Gateway API CRD 설치
# Gateway API v1.2 CRD 설치
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
# 실험적 기능 포함 (TCPRoute, TLSRoute 등)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml
# 설치 확인
kubectl get crd | grep gateway
Step 2: 기존 Ingress 분석
마이그레이션 전에 기존 Ingress를 파악합니다:
# 모든 Ingress 리소스 조회
kubectl get ingress -A -o wide
# 특정 Ingress 상세 확인 (어노테이션 포함)
kubectl get ingress my-ingress -o yaml
기존 Ingress 예시:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: web-svc
port:
number: 3000
Step 3: ingress2gateway 도구 활용
Kubernetes SIG에서 제공하는 공식 변환 도구를 활용합니다:
# ingress2gateway 설치
go install github.com/kubernetes-sigs/ingress2gateway@latest
# 현재 클러스터의 Ingress를 Gateway API로 변환
ingress2gateway print --all-namespaces
# 특정 네임스페이스만 변환
ingress2gateway print --namespace production
# 파일로 출력
ingress2gateway print --namespace production > gateway-resources.yaml
Step 4: 변환된 리소스 검증 및 적용
# dry-run으로 검증
kubectl apply -f gateway-resources.yaml --dry-run=server
# 적용
kubectl apply -f gateway-resources.yaml
# 상태 확인
kubectl get gateway -A
kubectl get httproute -A
kubectl describe gateway main-gateway -n infra
Step 5: 트래픽 분할 (카나리 배포)
Gateway API만의 강력한 기능인 가중치 기반 트래픽 분할:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-route
spec:
parentRefs:
- name: main-gateway
hostnames:
- "app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: app-v1
port: 8080
weight: 90
- name: app-v2
port: 8080
weight: 10
Step 6: 헤더 기반 라우팅
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-route
spec:
parentRefs:
- name: main-gateway
rules:
- matches:
- headers:
- name: X-Version
value: beta
backendRefs:
- name: app-beta
port: 8080
- backendRefs:
- name: app-stable
port: 8080
점진적 전환 전략
Ingress와 Gateway API는 동일 클러스터에서 공존할 수 있습니다:
- Phase 1: Gateway API CRD 설치 + GatewayClass/Gateway 생성
- Phase 2: 신규 서비스부터 HTTPRoute 사용
- Phase 3: 기존 Ingress를 하나씩 HTTPRoute로 전환
- Phase 4: 모든 Ingress 제거 후 Ingress Controller 정리
# 전환 진행률 모니터링
echo "Ingress: $(kubectl get ingress -A --no-headers | wc -l)"
echo "HTTPRoute: $(kubectl get httproute -A --no-headers | wc -l)"
주의사항 및 트러블슈팅
어노테이션 매핑
Ingress 어노테이션은 Gateway API에서 Policy 리소스나 Filter로 대체됩니다:
| Ingress 어노테이션 | Gateway API 대응 |
|---|---|
rewrite-target | URLRewriteFilter |
ssl-redirect | Gateway listener에서 HTTP→HTTPS 리다이렉트 |
rate-limit | BackendPolicy 또는 구현체별 Policy |
cors | HTTPRoute 필터 또는 Policy |
# URL Rewrite 예시
rules:
- matches:
- path:
type: PathPrefix
value: /old-api
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /new-api
backendRefs:
- name: api-svc
port: 8080
흔한 실수
- parentRefs 네임스페이스 누락: Gateway와 HTTPRoute가 다른 네임스페이스에 있으면 반드시 namespace 지정
- allowedRoutes 미설정: Gateway에서 다른 네임스페이스의 Route를 허용하려면
from: All설정 필요 - ReferenceGrant 누락: 크로스 네임스페이스 백엔드 참조 시 ReferenceGrant 필요
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-route-from-app
namespace: backend-ns
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: app-ns
to:
- group: ""
kind: Service
마무리
Gateway API는 단순한 Ingress의 대체가 아니라, Kubernetes 네트워킹의 패러다임 전환입니다. 역할 기반 설계, 풍부한 라우팅 기능, 멀티 프로토콜 지원으로 더 안전하고 유연한 트래픽 관리가 가능합니다. 기존 Ingress와 공존할 수 있으므로, 지금부터 점진적으로 전환을 시작하는 것을 추천합니다.
퀴즈
Q1: Gateway API의 3계층 리소스 모델에서 각 계층의 이름과 담당자는?
GatewayClass (인프라 제공자/플랫폼 팀), Gateway (클러스터 운영자), HTTPRoute/TCPRoute 등 (애플리케이션 개발자)
Q2: Ingress에서 벤더 종속적인 설정을 위해 사용하던 방식은?
어노테이션(annotations). nginx, traefik 등 구현체마다 다른 비표준 어노테이션을 사용했으며, 이는 이식성을 떨어뜨리는 주요 원인이었습니다.
Q3: Gateway API CRD를 설치하는 kubectl 명령어는?
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
Q4: 기존 Ingress를 Gateway API 리소스로 자동 변환해주는 공식 도구는?
ingress2gateway. Kubernetes SIG에서 제공하며, ingress2gateway print 명령으로 변환 결과를 확인할 수 있습니다.
Q5: Gateway API에서 가중치 기반 카나리 배포를 구현하려면 어떤 필드를 사용하나?
backendRefs의 weight 필드. 예: v1에 weight: 90, v2에 weight: 10으로 설정하면 90:10 비율로 트래픽 분할.
Q6: HTTPRoute와 Gateway가 다른 네임스페이스에 있을 때 주의할 점 두 가지는?
- parentRefs에 Gateway의 namespace를 명시해야 함. 2) Gateway의 listeners에서 allowedRoutes.namespaces.from을 "All"로 설정해야 함.
Q7: 크로스 네임스페이스에서 백엔드 서비스를 참조할 때 필요한 리소스는?
ReferenceGrant. 대상 네임스페이스에 생성하여, 어떤 네임스페이스의 어떤 리소스가 자신의 Service를 참조할 수 있는지 명시합니다.
Q8: Ingress의 rewrite-target 어노테이션은 Gateway API에서 어떻게 대체되나?
HTTPRoute의 filters에서 URLRewriteFilter를 사용합니다. type: URLRewrite와 urlRewrite.path 설정으로 경로를 재작성합니다.