Gateway 구성
네임스페이스에 제공된 Gateway에 API 키 인증, 모델 라우팅, 트래픽 정책과 Rate Limit을 구성합니다. 각 구성은 필요한 항목만 독립적으로 적용할 수 있습니다.
- Gateway는 네임스페이스와 같은 이름으로 미리 생성되어 있습니다.
targetRefs와parentRefs의 Gateway 이름에는 사용자 네임스페이스를 지정합니다.- 예시의
<...>값은 실제 환경에 맞게 변경합니다.
구성 요소
| 구성 | 리소스 | 기능 |
|---|---|---|
| 인증 | Secret, SecurityPolicy | API 키 인증 |
| AI Gateway | Backend, AIServiceBackend, AIGatewayRoute | 서빙 Service를 호스트명과 모델 이름으로 라우팅 |
| 트래픽 | ClientTrafficPolicy, BackendTrafficPolicy | 요청 버퍼, 타임아웃, 로드밸런싱, 서킷브레이커, 재시도 |
| Rate Limit | AIGatewayRoute, BackendTrafficPolicy | 요청 수 또는 토큰 사용량 기반 제한 |
API 키 인증 구성
Gateway로 들어오는 요청의 API 키를 검증합니다. API 키는 Secret에 저장하고 SecurityPolicy가 Secret을 참조합니다.
- Secret의 key는 클라이언트 식별자이고 value는 API 키입니다.
- 클라이언트마다
stringData항목을 추가합니다. - API 키 값에는
Bearer접두어를 포함하지 않습니다. sanitize: true이면 인증에 사용한 헤더를 백엔드로 전달하지 않습니다.
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: <Secret 이름>
namespace: <사용자 namespace>
stringData:
<클라이언트 식별자>: <API 키>
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: <SecurityPolicy 이름>
namespace: <사용자 namespace>
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: <사용자 namespace>
apiKeyAuth:
credentialRefs:
- group: ""
kind: Secret
name: <Secret 이름>
extractFrom:
- headers:
- authorization
forwardClientIDHeader: x-client-id
sanitize: true
API 키가 없거나 Secret의 값과 일치하지 않으면 Gateway가 401 Unauthorized로 요청을 거부합니다.
curl -s https://<호스트명>/v1/chat/completions \
-H "authorization: Bearer <API 키>" \
-H "content-type: application/json" \
-d '{"model":"<모델 이름>","messages":[{"role":"user","content":"안녕"}],"max_tokens":16}'
Secret이 포함된 YAML을 소스 저장소에 커밋하지 마세요. API 키는 사용자별로 구분하고 정기적으로 교체하는 것을 권장합니다.
AI Gateway 구성
서빙 Service를 외부 호스트명으로 노출하고 요청 본문의 model 값에 따라 라우팅합니다. Backend, AIServiceBackend, AIGatewayRoute를 함께 생성합니다.
Backend 생성
Backend는 요청을 전달할 서빙 Service의 클러스터 내부 주소와 포트를 정의합니다.
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
metadata:
name: <Backend 이름>
namespace: <사용자 namespace>
spec:
endpoints:
- fqdn:
hostname: <서빙 Service 이름>.<사용자 namespace>.svc.cluster.local
port: <서빙 Service 포트>
AIServiceBackend 생성
OpenAI 호환 API를 제공하는 Backend의 API 스키마를 정의합니다.
apiVersion: aigateway.envoyproxy.io/v1beta1
kind: AIServiceBackend
metadata:
name: <AIServiceBackend 이름>
namespace: <사용자 namespace>
spec:
schema:
name: OpenAI
backendRef:
group: gateway.envoyproxy.io
kind: Backend
name: <Backend 이름>
AIGatewayRoute 생성
AIGatewayRoute는 호스트명과 모델 이름을 기준으로 요청을 AIServiceBackend에 전달합니다. 요청 본문의 model 값은 x-ai-eg-model 헤더로 추출되며 라우팅 조건에 사용됩니다.
apiVersion: aigateway.envoyproxy.io/v1beta1
kind: AIGatewayRoute
metadata:
name: <AIGatewayRoute 이름>
namespace: <사용자 namespace>
spec:
hostnames:
- <호스트명>
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: <사용자 namespace>
namespace: <사용자 namespace>
rules:
- matches:
- headers:
- type: Exact
name: x-ai-eg-model
value: <모델 이름>
backendRefs:
- name: <AIServiceBackend 이름>
timeouts:
request: 1800s
AIGatewayRoute를 생성하면 같은 이름의 HTTPRoute가 자동으로 생성됩니다. hostnames는 Gateway 리스너의 호스트명 패턴에 포함되어야 합니다.
트래픽 구성
LLM 요청은 본문이 크고 응답 생성 시간이 길기 때문에 요청 버퍼와 백엔드 타임아웃을 워크로드 특성에 맞게 설정합니다.
클라이언트 연결 버퍼 설정
ClientTrafficPolicy로 클라이언트 연결당 버퍼 크기를 설정합니다. 기본 버퍼 크기는 32,768바이트입니다.
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
name: <ClientTrafficPolicy 이름>
namespace: <사용자 namespace>
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: <사용자 namespace>
connection:
bufferLimit: 50Mi
백엔드 트래픽 정책 설정
BackendTrafficPolicy는 AIGatewayRoute가 자동으로 생성한 HTTPRoute를 대상으로 합니다.
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: <BackendTrafficPolicy 이름>
namespace: <사용자 namespace>
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <AIGatewayRoute 이름>
timeout:
http:
requestTimeout: 1800s
streamIdleTimeout: 1800s
maxStreamDuration: 3600s
tcp:
connectTimeout: 30s
loadBalancer:
type: LeastRequest
circuitBreaker:
maxConnections: 4096
maxPendingRequests: 4096
maxParallelRequests: 4096
maxParallelRetries: 16
retry:
numRetries: 1
perRetry:
timeout: 1800s
backOff:
baseInterval: 500ms
maxInterval: 5s
retryOn:
triggers:
- connect-failure
- reset
- unavailable
Rate Limit 구성
BackendTrafficPolicy의 rateLimit.global로 클라이언트별 요청 수 또는 토큰 사용량을 제한합니다. 제한을 초과한 요청은 429 Too Many Requests와 x-envoy-ratelimited: true 헤더로 거부됩니다.
요청 수 기반 제한
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: <BackendTrafficPolicy 이름>
namespace: <사용자 namespace>
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <AIGatewayRoute 이름>
rateLimit:
type: Global
global:
rules:
- clientSelectors:
- headers:
- name: <클라이언트 식별 헤더>
type: Distinct
limit:
requests: <허용 요청 수>
unit: <단위 시간>
토큰 사용량 기반 제한
AIGatewayRoute의 llmRequestCosts로 토큰 사용량을 메타데이터에 기록합니다.
spec:
llmRequestCosts:
- metadataKey: llm_input_token
type: InputToken
- metadataKey: llm_output_token
type: OutputToken
- metadataKey: llm_total_token
type: TotalToken
BackendTrafficPolicy에서 같은 메타데이터 키를 참조하여 토큰 예산을 차감합니다.
spec:
rateLimit:
type: Global
global:
rules:
- clientSelectors:
- headers:
- name: <클라이언트 식별 헤더>
type: Distinct
limit:
requests: <허용 토큰 수>
unit: <단위 시간>
cost:
request:
from: Number
number: 0
response:
from: Metadata
metadata:
namespace: io.envoy.ai_gateway
key: llm_total_token
토큰 사용량은 응답이 완료된 후 차감됩니다. 스트리밍 요청은 스트림이 끝난 후 차감되며, 진행 중인 스트림을 중간에 종료하지 않습니다.
상태 확인
kubectl get gateway,httproute -n <사용자 namespace>
kubectl get backend,aiservicebackend,aigatewayroute -n <사용자 namespace>
kubectl get securitypolicy,clienttrafficpolicy,backendtrafficpolicy -n <사용자 namespace>
HTTPRoute의 Accepted와 ResolvedRefs 조건이 True인지 확인합니다.
kubectl describe httproute <AIGatewayRoute 이름> -n <사용자 namespace>