- Published on
Kubernetes Gateway API와 GRPCRoute 완벽 가이드: 서비스 메시부터 트래픽 라우팅까지
- Authors
- Name
- Gateway API란?
- GRPCRoute 심층 분석
- 트래픽 스플리팅 (카나리 배포)
- GAMMA: 서비스 메시 통합
- 실전 핸즈온: gRPC 마이크로서비스 라우팅
- ReferenceGrant: 크로스 네임스페이스 접근 제어
- 모니터링과 디버깅
- 프로덕션 체크리스트
Gateway API란?
Kubernetes Gateway API는 기존 Ingress 리소스의 한계를 넘어선 차세대 네트워킹 API입니다. 역할 기반의 리소스 모델(GatewayClass, Gateway, Route)을 통해 인프라 운영자와 애플리케이션 개발자의 관심사를 명확히 분리합니다.
왜 Gateway API인가?
기존 Ingress의 문제점:
- 단일 리소스에 모든 설정이 집중
- 구현체마다 다른 어노테이션
- gRPC, TCP, UDP 등 HTTP 외 프로토콜 미지원
- 역할 분리 불가
Gateway API는 이를 해결합니다:
# 1. 인프라팀이 관리하는 GatewayClass
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
---
# 2. 플랫폼팀이 관리하는 Gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: production-gateway
namespace: infra
spec:
gatewayClassName: istio
listeners:
- name: grpc
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: wildcard-cert
- name: http
protocol: HTTP
port: 80
GRPCRoute 심층 분석
GRPCRoute는 Gateway API v1 (GA)에 포함된 gRPC 전용 라우팅 리소스입니다. HTTPRoute와 달리 gRPC의 서비스/메서드 기반 매칭을 네이티브로 지원합니다.
기본 구조
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: user-service-route
namespace: app
spec:
parentRefs:
- name: production-gateway
namespace: infra
sectionName: grpc
hostnames:
- 'api.example.com'
rules:
- matches:
- method:
service: 'user.v1.UserService'
method: 'GetUser'
backendRefs:
- name: user-service
port: 50051
- matches:
- method:
service: 'user.v1.UserService'
method: 'CreateUser'
backendRefs:
- name: user-write-service
port: 50051
헤더 기반 라우팅
특정 헤더 값에 따라 다른 백엔드로 라우팅할 수 있습니다:
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: ab-test-route
spec:
parentRefs:
- name: production-gateway
namespace: infra
rules:
- matches:
- method:
service: 'recommendation.v1.RecommendationService'
headers:
- name: x-experiment-group
value: 'treatment-a'
backendRefs:
- name: recommendation-v2
port: 50051
- matches:
- method:
service: 'recommendation.v1.RecommendationService'
backendRefs:
- name: recommendation-v1
port: 50051
트래픽 스플리팅 (카나리 배포)
GRPCRoute의 backendRefs에 weight를 지정하면 트래픽을 비율로 분배할 수 있습니다:
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: canary-route
spec:
parentRefs:
- name: production-gateway
namespace: infra
rules:
- matches:
- method:
service: 'order.v1.OrderService'
backendRefs:
- name: order-service-stable
port: 50051
weight: 90
- name: order-service-canary
port: 50051
weight: 10
GAMMA: 서비스 메시 통합
GAMMA(Gateway API for Mesh Management and Administration)는 Gateway API를 서비스 메시로 확장하는 이니셔티브입니다.
GAMMA의 핵심: Service를 parentRef로
기존 Gateway API에서 Route의 parentRefs는 Gateway를 가리킵니다. GAMMA에서는 Service 자체를 parentRef로 지정하여 서비스 간 통신(East-West)을 제어합니다:
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: payment-mesh-route
spec:
parentRefs:
- group: ''
kind: Service
name: payment-service
port: 50051
rules:
- matches:
- method:
service: 'payment.v1.PaymentService'
method: 'ProcessPayment'
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: x-request-priority
value: 'high'
backendRefs:
- name: payment-service
port: 50051
Istio에서 GAMMA 활성화
# Istio 1.22+ 에서 GAMMA 지원
istioctl install --set profile=ambient
# Gateway API CRD 설치
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml
실전 핸즈온: gRPC 마이크로서비스 라우팅
1단계: gRPC 서비스 배포
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service-v1
namespace: app
spec:
replicas: 3
selector:
matchLabels:
app: user-service
version: v1
template:
metadata:
labels:
app: user-service
version: v1
spec:
containers:
- name: user-service
image: myregistry/user-service:v1.0
ports:
- containerPort: 50051
name: grpc
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
livenessProbe:
grpc:
port: 50051
initialDelaySeconds: 10
readinessProbe:
grpc:
port: 50051
initialDelaySeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: user-service
namespace: app
spec:
selector:
app: user-service
ports:
- name: grpc
port: 50051
targetPort: 50051
appProtocol: kubernetes.io/grpc
2단계: Gateway 설정
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: grpc-gateway
namespace: infra
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
gatewayClassName: istio
listeners:
- name: grpc-tls
protocol: HTTPS
port: 443
hostname: '*.api.example.com'
tls:
mode: Terminate
certificateRefs:
- name: api-tls-cert
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: 'true'
kinds:
- kind: GRPCRoute
3단계: GRPCRoute로 라우팅 규칙 정의
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: user-grpc-route
namespace: app
spec:
parentRefs:
- name: grpc-gateway
namespace: infra
sectionName: grpc-tls
hostnames:
- 'user.api.example.com'
rules:
- matches:
- method:
service: 'user.v1.UserService'
method: 'GetUser'
- method:
service: 'user.v1.UserService'
method: 'ListUsers'
backendRefs:
- name: user-service-reader
port: 50051
- matches:
- method:
service: 'user.v1.UserService'
method: 'CreateUser'
- method:
service: 'user.v1.UserService'
method: 'UpdateUser'
- method:
service: 'user.v1.UserService'
method: 'DeleteUser'
backendRefs:
- name: user-service-writer
port: 50051
4단계: 테스트
# grpcurl로 테스트
grpcurl -d '{"user_id": "123"}' \
-H "x-request-id: test-001" \
user.api.example.com:443 \
user.v1.UserService/GetUser
# 카나리 배포 확인 (여러 번 호출하여 비율 확인)
for i in $(seq 1 100); do
grpcurl -d '{"user_id": "123"}' \
user.api.example.com:443 \
user.v1.UserService/GetUser 2>&1 | grep "server_version"
done | sort | uniq -c
ReferenceGrant: 크로스 네임스페이스 접근 제어
다른 네임스페이스의 백엔드를 참조하려면 ReferenceGrant가 필요합니다:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-app-to-backend
namespace: backend
spec:
from:
- group: gateway.networking.k8s.io
kind: GRPCRoute
namespace: app
to:
- group: ''
kind: Service
모니터링과 디버깅
Gateway API 상태 확인
# Gateway 상태 확인
kubectl get gateway -A
kubectl describe gateway grpc-gateway -n infra
# GRPCRoute 상태 확인
kubectl get grpcroute -A
kubectl describe grpcroute user-grpc-route -n app
# Istio 라우팅 규칙 확인
istioctl proxy-config route deploy/istio-ingressgateway -n istio-system -o json
Prometheus 메트릭
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: grpc-gateway-alerts
spec:
groups:
- name: grpc-gateway
rules:
- alert: GRPCHighErrorRate
expr: |
sum(rate(grpc_server_handled_total{grpc_code!="OK"}[5m])) by (grpc_service)
/
sum(rate(grpc_server_handled_total[5m])) by (grpc_service)
> 0.05
for: 5m
labels:
severity: warning
프로덕션 체크리스트
Gateway API를 프로덕션에 도입할 때 확인 사항:
- GatewayClass 구현체 선택 (Istio, Envoy Gateway, Cilium 등)
- TLS 인증서 자동화 (cert-manager 연동)
- ReferenceGrant 정책 수립
- 모니터링 (Gateway 상태, 라우팅 메트릭)
- 레이트 리미팅 설정 (BackendTrafficPolicy)
- 타임아웃 및 리트라이 정책
- gRPC 헬스체크 설정
- 점진적 마이그레이션 계획
📝 확인 퀴즈 (5문제)
Q1. Gateway API에서 역할 분리를 위한 세 가지 핵심 리소스는?
GatewayClass, Gateway, Route (HTTPRoute/GRPCRoute 등)
Q2. GAMMA 이니셔티브에서 GRPCRoute의 parentRefs가 가리키는 것은?
Gateway 대신 Service 자체를 parentRef로 지정하여 East-West(서비스 간) 트래픽을 제어합니다.
Q3. GRPCRoute에서 카나리 배포를 구현하려면 어떤 필드를 사용하나요?
backendRefs의 weight 필드를 사용하여 트래픽 비율을 분배합니다.
Q4. 다른 네임스페이스의 Service를 backendRef로 참조하려면 어떤 리소스가 필요한가요?
ReferenceGrant 리소스가 대상 네임스페이스에 생성되어야 합니다.
Q5. GRPCRoute에서 특정 gRPC 메서드를 매칭하려면 어떤 필드를 사용하나요?
rules.matches.method 필드에 service와 method를 지정합니다.