Skip to content
Published on

Kubernetes Gateway API 실전 마이그레이션 — Ingress에서 Gateway로

Authors
  • Name
    Twitter
Kubernetes Gateway API Migration

들어가며

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는 동일 클러스터에서 공존할 수 있습니다:

  1. Phase 1: Gateway API CRD 설치 + GatewayClass/Gateway 생성
  2. Phase 2: 신규 서비스부터 HTTPRoute 사용
  3. Phase 3: 기존 Ingress를 하나씩 HTTPRoute로 전환
  4. 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-targetURLRewriteFilter
ssl-redirectGateway listener에서 HTTP→HTTPS 리다이렉트
rate-limitBackendPolicy 또는 구현체별 Policy
corsHTTPRoute 필터 또는 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

흔한 실수

  1. parentRefs 네임스페이스 누락: Gateway와 HTTPRoute가 다른 네임스페이스에 있으면 반드시 namespace 지정
  2. allowedRoutes 미설정: Gateway에서 다른 네임스페이스의 Route를 허용하려면 from: All 설정 필요
  3. 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에서 가중치 기반 카나리 배포를 구현하려면 어떤 필드를 사용하나? backendRefsweight 필드. 예: v1에 weight: 90, v2에 weight: 10으로 설정하면 90:10 비율로 트래픽 분할.

Q6: HTTPRoute와 Gateway가 다른 네임스페이스에 있을 때 주의할 점 두 가지는?
  1. parentRefs에 Gateway의 namespace를 명시해야 함. 2) Gateway의 listeners에서 allowedRoutes.namespaces.from을 "All"로 설정해야 함.

Q7: 크로스 네임스페이스에서 백엔드 서비스를 참조할 때 필요한 리소스는? ReferenceGrant. 대상 네임스페이스에 생성하여, 어떤 네임스페이스의 어떤 리소스가 자신의 Service를 참조할 수 있는지 명시합니다.

Q8: Ingress의 rewrite-target 어노테이션은 Gateway API에서 어떻게 대체되나? HTTPRoute의 filters에서 URLRewriteFilter를 사용합니다. type: URLRewriteurlRewrite.path 설정으로 경로를 재작성합니다.