티스토리 뷰
작성일: 2025년 12월 18일
카테고리: Kubernetes, Networking, Architecture
키워드: Gateway API, Ingress, Cross-Namespace Reference, ReferenceGrant, Kubernetes
요약
Kubernetes Gateway API는 Ingress의 한계를 해결하기 위해 처음부터 다시 설계된 API다. Role-Oriented Design을 통해 Infrastructure Provider, Cluster Operator, Application Developer 역할을 명확히 분리하고, Cross-Namespace Reference와 ReferenceGrant를 통해 멀티테넌시 환경에서 안전한 리소스 공유를 지원한다. 이 글에서는 Ingress의 문제점, Gateway API의 설계 원칙, 그리고 실제 적용 방법을 다룬다.
들어가며
Kubernetes에서 API를 외부에 노출하는 것은 생각보다 복잡하다. 단순히 Service를 LoadBalancer 타입으로 변경하는 것을 넘어, L7 라우팅, TLS 종료, 인증 등 다양한 요구사항을 처리해야 한다.
Kubernetes에서 외부 트래픽을 처리하는 방법은 크게 발전해왔다:
| 년도 | 기술 | 특징 |
|---|---|---|
| 2015 | Service (NodePort, LoadBalancer) | 기본적인 L4 로드밸런싱 |
| 2016 | Ingress (v1beta1) | L7 라우팅 표준화 시도 |
| 2020 | Ingress GA (v1) | 안정화, 하지만 한계 명확 |
| 2021 | Gateway API (v1alpha1) | 완전히 새로운 설계 |
| 2023 | Gateway API GA (v1) | 프로덕션 준비 완료 |
Gateway API는 Ingress의 "개선판"이 아니라, 처음부터 다시 설계된 완전히 새로운 API다.
Ingress의 한계
문제 1: 단일 네임스페이스 제약
# Ingress - 같은 네임스페이스의 Service만 참조 가능
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: team-a # 이 네임스페이스에 있는 Service만
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
backend:
service:
name: my-service # team-a 네임스페이스의 서비스만 가능
port:
number: 80
결과: 중앙 집중식 Gateway 관리가 어려움
문제 2: Annotation 지옥
# 실제 프로덕션 Ingress 예시 (NGINX)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
# NGINX 전용
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/rate-limit: "100"
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
# ... 더 많은 annotation들
문제점:
| 문제 | 설명 |
|---|---|
| 구현체마다 다른 annotation | NGINX, Traefik, Kong 모두 다름 |
| 타입 안정성 없음 | 모든 값이 문자열 |
| 문서 찾기 어려움 | 각 구현체 문서를 따로 확인 |
| 이식성 제로 | 구현체 변경 시 annotation 전체 수정 |
문제 3: 역할 분리 불가
flowchart TB
subgraph Problem["Ingress의 권한 문제"]
I[Ingress 리소스]
I --> Q1["누가 TLS 인증서를 관리?"]
I --> Q2["누가 포트를 열 수 있나?"]
I --> Q3["누가 라우팅 규칙을 정의?"]
Q1 & Q2 & Q3 --> A["모두 같은 리소스에서<br/>같은 권한으로 관리"]
end
style Problem stroke:#dc2626,stroke-width:2px
인프라 팀 vs 개발 팀의 책임 분리가 불가능
문제 요약
| 문제 | 영향 |
|---|---|
| 단일 네임스페이스 | 중앙 Gateway 관리 불가 |
| Annotation 기반 | 이식성 없음, 타입 안정성 없음 |
| 역할 분리 불가 | 보안 및 운영 복잡성 증가 |
| 제한된 기능 | 고급 라우팅, 트래픽 분할 어려움 |
Gateway API의 탄생
SIG-Network의 새로운 접근
Kubernetes SIG-Network는 Ingress를 패치하는 대신 완전히 새로운 API를 설계하기로 결정했다.
설계 원칙 (공식):
| 원칙 | 설명 |
|---|---|
| Role-oriented | 역할별 리소스 분리 |
| Portable | 구현체 간 이식성 보장 |
| Expressive | 복잡한 라우팅 표현 가능 |
| Extensible | 확장 가능한 구조 |
리소스 분리
flowchart LR
subgraph Ingress["Ingress (단일 리소스)"]
I["Ingress<br/>- TLS 설정<br/>- 호스트/포트<br/>- 라우팅 규칙<br/>- 백엔드 참조<br/>모두 한 곳에!"]
end
subgraph GatewayAPI["Gateway API (분리된 리소스)"]
GC["GatewayClass<br/>구현체 정의"]
GW["Gateway<br/>포트/호스트/TLS"]
HR["HTTPRoute<br/>라우팅 규칙"]
BE["Backend/Service<br/>백엔드 정의"]
GC --> GW --> HR --> BE
end
Ingress -->|진화| GatewayAPI
style Ingress stroke:#dc2626,stroke-width:2px
style GatewayAPI stroke:#16a34a,stroke-width:2px
Role-Oriented Design
Gateway API의 핵심 혁신은 역할 기반 리소스 분리다.
세 가지 역할
flowchart TB
subgraph Role1["Infrastructure Provider"]
GC[GatewayClass]
GC_DESC["Gateway 구현체 제공<br/>Envoy, Kong, Istio, Traefik 등<br/>클러스터 스코프 (전역)"]
end
subgraph Role2["Cluster Operator"]
GW[Gateway]
RG[ReferenceGrant]
GW_DESC["어떤 포트/호스트를 열지 결정<br/>TLS 인증서 관리<br/>네임스페이스: gateway-system"]
end
subgraph Role3["Application Developer"]
HR[HTTPRoute / GRPCRoute]
BE[Backend / Service]
HR_DESC["앱별 라우팅 규칙 정의<br/>자신의 네임스페이스에서 관리"]
end
GC --> GW
GW --> HR
HR --> BE
style Role1 stroke:#2563eb,stroke-width:2px
style Role2 stroke:#7c3aed,stroke-width:2px
style Role3 stroke:#16a34a,stroke-width:2px
역할별 책임
| 역할 | 리소스 | 책임 | RBAC 범위 |
|---|---|---|---|
| Infrastructure Provider | GatewayClass | Gateway 구현체 배포 | 클러스터 관리자 |
| Cluster Operator | Gateway, ReferenceGrant | 진입점 설정, 보안 정책 | 인프라 네임스페이스 |
| Application Developer | HTTPRoute, Backend | 앱 라우팅 규칙 | 앱 네임스페이스 |
실제 예시: 권한 분리
# 인프라 팀만 Gateway 생성 가능
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: gateway-admin
namespace: gateway-system
rules:
- apiGroups: ["gateway.networking.k8s.io"]
resources: ["gateways"]
verbs: ["*"]
---
# 개발 팀은 HTTPRoute만 생성 가능
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: route-admin
namespace: team-a
rules:
- apiGroups: ["gateway.networking.k8s.io"]
resources: ["httproutes"]
verbs: ["*"]
# gateways 권한 없음!
Cross-Namespace Reference
핵심 혁신
Gateway API는 다른 네임스페이스의 리소스를 참조할 수 있다:
# team-a 네임스페이스의 HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-route
namespace: team-a # 개발팀 네임스페이스
spec:
parentRefs:
- name: shared-gateway
namespace: gateway-system # 인프라 네임스페이스 참조
hostnames:
- app-a.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: my-service
port: 8080
이것이 가능하게 하는 아키텍처
flowchart TB
subgraph Cluster["Kubernetes Cluster"]
subgraph NS_Infra["gateway-system (인프라)"]
GW["Gateway<br/>shared-gateway<br/>*.example.com:443"]
RG["ReferenceGrant<br/>(Cross-NS 허용)"]
end
subgraph NS_A["team-a (팀 A)"]
HR_A["HTTPRoute<br/>app-a.example.com"]
SVC_A["Service<br/>my-service"]
end
subgraph NS_B["team-b (팀 B)"]
HR_B["HTTPRoute<br/>app-b.example.com"]
SVC_B["Service<br/>other-service"]
end
subgraph NS_C["team-c (팀 C)"]
HR_C["HTTPRoute<br/>app-c.example.com"]
SVC_C["Service<br/>another-service"]
end
end
HR_A & HR_B & HR_C -.parentRef.-> GW
RG -.허용.-> HR_A & HR_B & HR_C
style NS_Infra stroke:#6366f1,stroke-width:2px
style NS_A stroke:#16a34a,stroke-width:2px
style NS_B stroke:#f59e0b,stroke-width:2px
style NS_C stroke:#dc2626,stroke-width:2px
공식 문서의 설명
"Gateway API is designed with multi-tenancy in mind."
Routes can attach to Gateways across namespace boundaries. This allows the infrastructure team to manage Gateways centrally while application teams define their routing rules in their own namespaces.
ReferenceGrant: 보안 메커니즘
Cross-Namespace Reference는 강력하지만, 보안이 필요하다. ReferenceGrant가 이를 제어한다.
ReferenceGrant 개념
sequenceDiagram
participant HR as HTTPRoute<br/>(team-a)
participant RG as ReferenceGrant<br/>(gateway-system)
participant GW as Gateway<br/>(gateway-system)
participant Controller as Gateway Controller
HR->>Controller: parentRef: gateway-system/shared-gateway
Controller->>RG: ReferenceGrant 확인
alt ReferenceGrant 존재
RG-->>Controller: 허용됨
Controller->>GW: Route 연결
Controller-->>HR: Status: Accepted
else ReferenceGrant 없음
RG-->>Controller: 거부됨
Controller-->>HR: Status: RefNotPermitted
end
ReferenceGrant 예시
# gateway-system 네임스페이스에서 정의
# "다른 네임스페이스의 HTTPRoute가 내 Gateway를 참조해도 됨"
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-routes-from-all
namespace: gateway-system
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: team-a # 특정 네임스페이스만 허용
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: team-b
to:
- group: gateway.networking.k8s.io
kind: Gateway
name: shared-gateway # 특정 Gateway만 허용 (선택)
보안 원칙
| 원칙 | 설명 |
|---|---|
| 명시적 허용 | 기본은 거부, ReferenceGrant로 허용 |
| 대상 네임스페이스에서 정의 | 참조 "받는" 쪽에서 허용 결정 |
| 세분화된 제어 | 네임스페이스, 리소스 종류, 이름까지 제한 가능 |
Gateway API 실전 적용
기본 구조
# 1. GatewayClass (Envoy Gateway 설치 시 자동)
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy-gateway
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
# 2. Gateway (인프라 레이어)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: shared-gateway
namespace: gateway-system
spec:
gatewayClassName: envoy-gateway
listeners:
- name: https
hostname: "*.api.example.com"
port: 443
protocol: HTTPS
tls:
certificateRefs:
- name: wildcard-api-tls
---
# 3. ReferenceGrant (Cross-NS 허용)
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-tenant-routes
namespace: gateway-system
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: "*" # 모든 테넌트 네임스페이스 허용
to:
- group: gateway.networking.k8s.io
kind: Gateway
---
# 4. HTTPRoute (테넌트 레이어)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-api-route
namespace: team-a
spec:
parentRefs:
- name: shared-gateway
namespace: gateway-system # Cross-NS Reference
hostnames:
- app-a.api.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: my-backend
port: 8080
표준 준수 체크리스트
| Gateway API 원칙 | 구현 방법 | 상태 |
|---|---|---|
| Role-Oriented | 인프라/테넌트 네임스페이스 분리 | 필수 |
| Cross-Namespace | HTTPRoute → Gateway 참조 | 필수 |
| ReferenceGrant | 테넌트 Route 허용 정책 | 필수 |
| Portable | 표준 CRD 사용 | 권장 |
| Expressive | 고급 라우팅, 필터, 정책 | 선택 |
결론
Gateway API vs Ingress
flowchart LR
subgraph Ingress["Ingress"]
I1["단일 리소스"]
I2["단일 네임스페이스"]
I3["Annotation 기반"]
I4["역할 분리 불가"]
end
subgraph GatewayAPI["Gateway API"]
G1["역할별 리소스 분리"]
G2["Cross-Namespace 지원"]
G3["타입 안정성 있는 스펙"]
G4["RBAC 친화적"]
end
Ingress -->|"재설계"| GatewayAPI
style Ingress stroke:#dc2626,stroke-width:2px
style GatewayAPI stroke:#16a34a,stroke-width:2px
핵심 포인트
Gateway API의 Cross-Namespace 설계는 "꼼수"가 아니라 표준이다:
- 의도적 설계: SIG-Network가 멀티테넌시를 위해 설계
- Role-Oriented: 인프라 팀과 개발 팀 책임 분리
- 보안 내장: ReferenceGrant로 명시적 허용 필요
- 업계 표준: Envoy, Kong, Istio, Traefik 모두 지원
요약 다이어그램
flowchart TB
subgraph Cluster["Kubernetes Cluster"]
subgraph GC["GatewayClass (클러스터 스코프)"]
GC_DESC["구현체 정의: envoy-gateway, kong, istio..."]
end
subgraph Infra["gateway-system namespace (인프라 팀)"]
GW["Gateway<br/>포트, 호스트, TLS"]
RG["ReferenceGrant<br/>Cross-NS 허용 정책"]
end
subgraph TeamA["team-a NS (개발팀 A)"]
HR_A["HTTPRoute"]
SVC_A["Service"]
end
subgraph TeamB["team-b NS (개발팀 B)"]
HR_B["HTTPRoute"]
SVC_B["Service"]
end
subgraph TeamC["team-c NS (개발팀 C)"]
HR_C["HTTPRoute"]
SVC_C["Service"]
end
end
GC --> Infra
HR_A & HR_B & HR_C -.->|Cross-Namespace<br/>Reference| GW
style GC stroke:#2563eb,stroke-width:2px
style Infra stroke:#7c3aed,stroke-width:2px
style TeamA stroke:#16a34a,stroke-width:2px
style TeamB stroke:#f59e0b,stroke-width:2px
style TeamC stroke:#dc2626,stroke-width:2px
참고 자료
공식 문서
- Gateway API Official Documentation
- KEP-1452: Gateway API
- Gateway API Cross-Namespace References
- ReferenceGrant Specification
구현체
'실제 경험과 인사이트를 AI와 함께 정리한 글' 카테고리의 다른 글
| Ory Kratos 로그인 플로우 Deep Dive (0) | 2025.12.18 |
|---|---|
| Ory 스택 완전 가이드: 오픈소스 인증/인가 시스템 (0) | 2025.12.18 |
| Kubernetes Operator 패턴과 Reconciliation: 선언적 인프라의 핵심 (0) | 2025.12.18 |
| gRPC 완전 가이드: REST와의 비교부터 실전 활용까지 (0) | 2025.12.18 |
| API Gateway 입문 가이드: 마이크로서비스의 관문 (0) | 2025.12.18 |
- Total
- Today
- Yesterday
- Go
- react
- Gemini 3.0
- Next.js
- Claude
- zustand
- architecture
- Kubernetes
- authentication
- imprun.dev
- feature-sliced design
- Developer Tools
- AI agent
- GPT-5.1
- ai coding
- backend
- authorization
- NestJS
- AI
- EnvironmentAgnostic
- Development Tools
- api gateway
- AGENTS.md
- troubleshooting
- Claude Opus 4.5
- security
- Tailwind CSS
- claude code
- frontend
- CLAUDE.md
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
