K8s Gateway API 라우팅 심화

K8s Gateway API란?

Kubernetes Gateway API는 기존 Ingress 리소스의 한계를 극복하기 위해 SIG-Network에서 설계한 차세대 트래픽 라우팅 표준이다. Ingress가 단일 리소스에 모든 설정을 몰아넣는 반면, Gateway API는 역할 기반 분리(Role-Oriented Design)를 통해 인프라 관리자와 애플리케이션 개발자의 관심사를 명확히 나눈다.

구분 Ingress Gateway API
리소스 구조 단일 Ingress 리소스 GatewayClass → Gateway → HTTPRoute 계층
역할 분리 없음 인프라 제공자 / 클러스터 운영자 / 앱 개발자
프로토콜 HTTP/HTTPS 중심 HTTP, TCP, UDP, gRPC, TLS 모두 지원
헤더 기반 라우팅 어노테이션 의존 네이티브 지원
트래픽 분할 미지원 weight 기반 카나리 네이티브 지원

핵심 리소스 3계층 구조

Gateway API의 가장 큰 특징은 3계층 리소스 모델이다. 각 계층은 서로 다른 역할의 담당자가 관리하며, 이를 통해 대규모 멀티 팀 환경에서도 안전한 트래픽 관리가 가능하다.

1. GatewayClass — 인프라 제공자 영역

GatewayClass는 어떤 컨트롤러(예: Envoy, Istio, Cilium)가 Gateway를 구현하는지 정의한다. 클라우드 프로바이더나 인프라 팀이 한 번 설정하면 클러스터 전체에서 재사용된다.

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: envoy-gateway
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
  description: "Envoy 기반 프로덕션 게이트웨이"

2. Gateway — 클러스터 운영자 영역

Gateway는 실제 로드밸런서 인스턴스를 나타낸다. 리스너(listener)를 통해 어떤 포트와 프로토콜로 트래픽을 수신할지 정의하며, allowedRoutes로 어떤 네임스페이스의 Route가 이 Gateway에 바인딩할 수 있는지 제어한다.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: prod-gateway
  namespace: infra
spec:
  gatewayClassName: envoy-gateway
  listeners:
  - name: https
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: wildcard-tls
        namespace: cert-store
    allowedRoutes:
      namespaces:
        from: Selector
        selector:
          matchLabels:
            gateway-access: "true"
  - name: http-redirect
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same

3. HTTPRoute — 애플리케이션 개발자 영역

HTTPRoute는 실제 라우팅 규칙을 정의한다. 개발자가 자신의 네임스페이스에서 독립적으로 생성하며, parentRefs로 Gateway에 바인딩한다. 이것이 역할 분리의 핵심이다.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-route
  namespace: app-team-a
spec:
  parentRefs:
  - name: prod-gateway
    namespace: infra
  hostnames:
  - "api.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /users
      headers:
      - name: X-Api-Version
        value: "v2"
    backendRefs:
    - name: user-service-v2
      port: 8080
      weight: 90
    - name: user-service-v3
      port: 8080
      weight: 10
  - matches:
    - path:
        type: PathPrefix
        value: /users
    backendRefs:
    - name: user-service-v2
      port: 8080

카나리 배포: weight 기반 트래픽 분할

Gateway API의 킬러 피처 중 하나는 네이티브 트래픽 분할이다. Ingress에서는 어노테이션 해킹이 필요했던 카나리 배포를 선언적으로 구현할 수 있다. 위 HTTPRoute 예시에서 weight: 90weight: 10으로 v2에 90%, v3에 10%의 트래픽을 보낸다.

점진적 롤아웃 시나리오를 단계별로 구성하면:

# 1단계: 5% 카나리
backendRefs:
- name: api-stable
  weight: 95
- name: api-canary
  weight: 5

# 2단계: 메트릭 정상 확인 후 50%
backendRefs:
- name: api-stable
  weight: 50
- name: api-canary
  weight: 50

# 3단계: 완전 전환
backendRefs:
- name: api-canary
  weight: 100

요청 필터링과 변환

HTTPRoute의 filters는 요청/응답을 인라인으로 변환한다. 어노테이션 없이 표준 스펙만으로 헤더 조작, URL 리라이트, 리다이렉트가 가능하다.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: transform-route
spec:
  parentRefs:
  - name: prod-gateway
    namespace: infra
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /old-api
    filters:
    - type: URLRewrite
      urlRewrite:
        path:
          type: ReplacePrefixMatch
          replacePrefixMatch: /v2/api
    - type: RequestHeaderModifier
      requestHeaderModifier:
        add:
        - name: X-Forwarded-Prefix
          value: /old-api
        set:
        - name: X-Request-Source
          value: gateway
        remove:
        - X-Internal-Debug
    backendRefs:
    - name: api-service
      port: 8080
  - matches:
    - path:
        type: Exact
        value: /legacy
    filters:
    - type: RequestRedirect
      requestRedirect:
        scheme: https
        hostname: new.example.com
        statusCode: 301

크로스 네임스페이스 참조와 ReferenceGrant

멀티 팀 환경에서 네임스페이스 간 리소스 참조는 보안상 민감하다. Gateway API는 ReferenceGrant로 이를 명시적으로 허용한다. 기본적으로 크로스 네임스페이스 참조는 차단되며, 리소스 소유자가 ReferenceGrant를 생성해야만 접근이 열린다.

# cert-store 네임스페이스의 Secret을
# infra 네임스페이스의 Gateway가 참조하도록 허용
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-gateway-tls
  namespace: cert-store
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: Gateway
    namespace: infra
  to:
  - group: ""
    kind: Secret

이 설계 덕분에 인증서는 보안 팀이 관리하고, Gateway 설정은 인프라 팀이, 라우팅은 각 앱 팀이 독립적으로 운영할 수 있다. K8s cert-manager TLS 자동화 글에서 다룬 인증서 관리와 함께 사용하면 완전한 TLS 파이프라인이 완성된다.

GRPCRoute: gRPC 전용 라우팅

마이크로서비스에서 gRPC를 쓴다면 GRPCRoute가 핵심이다. HTTP/2 기반 gRPC 트래픽을 서비스/메서드 단위로 라우팅할 수 있다.

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: grpc-route
spec:
  parentRefs:
  - name: prod-gateway
    namespace: infra
  hostnames:
  - "grpc.example.com"
  rules:
  - matches:
    - method:
        service: user.UserService
        method: GetUser
    backendRefs:
    - name: user-grpc-service
      port: 50051
  - matches:
    - method:
        service: order.OrderService
    backendRefs:
    - name: order-grpc-service
      port: 50051

실전 운영: Envoy Gateway 설치와 구성

Gateway API는 스펙이므로 실제 구현체가 필요하다. Envoy Gateway는 가장 활발하게 개발되는 구현체 중 하나다.

# Gateway API CRD 설치
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml

# Envoy Gateway 설치
helm install eg oci://docker.io/envoyproxy/gateway-helm 
  --version v1.2.0 
  -n envoy-gateway-system 
  --create-namespace

# GatewayClass 확인
kubectl get gatewayclass
# NAME             CONTROLLER                                      ACCEPTED
# eg               gateway.envoyproxy.io/gatewayclass-controller    True

모니터링과 디버깅

Gateway API 리소스의 상태는 conditions로 추적한다. 문제 발생 시 각 리소스의 status를 확인하면 원인을 빠르게 파악할 수 있다.

# Gateway 상태 확인
kubectl describe gateway prod-gateway -n infra

# HTTPRoute 바인딩 상태
kubectl get httproute -A -o wide

# 주요 condition 타입:
# - Accepted: Route가 Gateway에 수락되었는지
# - ResolvedRefs: 백엔드 참조가 유효한지
# - Programmed: 데이터 플레인에 설정이 반영되었는지

K8s Pod Probe 헬스체크 전략과 결합하면 Gateway부터 Pod까지 전 구간의 상태를 관측할 수 있는 체계가 만들어진다.

Ingress에서 Gateway API 마이그레이션

기존 Ingress를 Gateway API로 전환하는 것은 점진적으로 가능하다. 두 리소스는 동시에 공존할 수 있으므로, 서비스 단위로 하나씩 마이그레이션하면 된다.

# 기존 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: legacy-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: api-svc
            port:
              number: 80

# Gateway API 변환 결과
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-route
spec:
  parentRefs:
  - name: prod-gateway
  hostnames:
  - "api.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    filters:
    - type: URLRewrite
      urlRewrite:
        path:
          type: ReplacePrefixMatch
          replacePrefixMatch: /
    backendRefs:
    - name: api-svc
      port: 80

마이그레이션의 핵심은 어노테이션 기반의 암묵적 설정을 Gateway API의 명시적 필터로 변환하는 것이다. 복잡한 nginx 어노테이션일수록 Gateway API로의 전환 이점이 크다.

마무리

Gateway API는 Kubernetes 네트워킹의 미래 표준이다. GA(v1.0)가 2023년에 발표된 이후 Envoy Gateway, Istio, Cilium, Traefik 등 주요 구현체가 빠르게 지원을 확대하고 있다. 새 프로젝트라면 처음부터 Gateway API를 채택하고, 기존 프로젝트는 점진적 마이그레이션을 계획하는 것이 현명한 선택이다.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux