API Gateway, Kubernetes Gateway 및 Service Mesh의 종합 비교
June 9, 2023
API 게이트웨이, Kubernetes 게이트웨이, 서비스 메시에 대해 여전히 많은 혼란이 있습니다. 이는 다음과 같은 이유 때문입니다:
- 사람들은 종종 카나리 배포, 속도 제한, 서비스 디스커버리와 같은 동일한 키워드로 이러한 기술들을 언급합니다.
- 이 모든 기술들은 리버스 프록시를 사용합니다.
- 일부 API 게이트웨이는 자체 Kubernetes 게이트웨이와 서비스 메시를 가지고 있고, 그 반대도 마찬가지입니다.
- 이 세 가지 기술을 비교하고 하나가 다른 것보다 왜 더 나은지 결론짓는 많은 글/비디오가 있습니다.
이 글에서는 이러한 기술들을 설명하고, 근본적으로 어떻게 다르며 어떤 사용 사례에 적합한지 공유하려고 합니다.
API 게이트웨이
API 게이트웨이는 클라이언트 애플리케이션과 API 사이에 위치합니다. 모든 클라이언트 요청을 수락하고, 필요한 API로 전달한 후, 응답을 클라이언트에게 통합된 패키지로 반환합니다.
기본적으로 많은 기능을 가진 리버스 프록시입니다.
이 외에도 API 게이트웨이는 인증, 보안, 세밀한 트래픽 제어, 모니터링과 같은 기능을 제공하여 API 개발자가 비즈니스 요구에만 집중할 수 있도록 합니다.
많은 API 게이트웨이 솔루션이 있습니다. 일부 인기 있는 무료 및 오픈 소스 솔루션은 다음과 같습니다:
- Apache APISIX: Nginx 위에 구축된 고성능, 확장 가능한 클라우드 네이티브 API 게이트웨이.
- Gloo Edge: Envoy 프록시 위에 구축된 API 게이트웨이.
- Kong: Nginx 위에 구축된 플러그형 API 게이트웨이.
- Tyk: Go로 작성된 API 게이트웨이로 REST, GraphQL, TCP, gRPC 프로토콜을 지원합니다.
GCP, AWS, Azure와 같은 클라우드 플랫폼도 자체적인 API 게이트웨이를 제공합니다.
API 게이트웨이, Kubernetes 게이트웨이, 서비스 메시는 카나리 배포를 지원합니다. 이는 새로운 소프트웨어 버전을 소규모 사용자 집단에게 점진적으로 출시한 후 일반적으로 사용 가능하게 만드는 방식입니다.
아래 예제는 Apache APISIX에서 카나리 배포를 구성하는 방법을 보여줍니다.
다음 구성으로 APISIX Admin API에 요청을 보낼 수 있습니다:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri":"/*",
"plugins":{
"traffic-split":{
"rules":[
{
"weighted_upstreams":[
{
"upstream":{
"name":"api-v1",
"type":"roundrobin",
"nodes":{
"api-v1:8080":1
}
},
"weight":95
},
{
"weight":5
}
]
}
]
}
},
"upstream":{
"type":"roundrobin",
"nodes":{
"api-v2:8080":1
}
}
}'
APISIX는 이제 트래픽의 95%를 api-v1 서비스로, 5%를 api-v2 서비스로 라우팅합니다.
Kubernetes 게이트웨이
Kubernetes 게이트웨이는 Kubernetes 네이티브 API 게이트웨이입니다. 즉, Kubernetes API를 사용하여 이러한 API 게이트웨이를 관리할 수 있으며, Kubernetes 파드, 서비스, 배포와 유사합니다.
Kubernetes에서 API는 클러스터에 배포된 파드와 서비스입니다. 그런 다음 Kubernetes 게이트웨이를 사용하여 외부 트래픽을 클러스터로 전달합니다.
Kubernetes는 이를 위해 Ingress API와 Gateway API 두 가지 API를 제공합니다.
Kubernetes Ingress API
Ingress API는 기본 서비스 유형인 NodePort와 LoadBalancer의 한계를 극복하기 위해 라우팅 및 SSL 종료와 같은 기능을 도입했습니다. 또한 Kubernetes 서비스를 외부 트래픽에 노출하는 방법을 표준화했습니다.
Ingress API는 Ingress와 Ingress 컨트롤러 두 가지 구성 요소로 이루어져 있습니다.
Ingress Kubernetes 네이티브 객체는 외부 트래픽이 서비스에 접근할 수 있는 방법에 대한 규칙 집합을 정의합니다.
이 예제 구성은 Kubernetes Ingress 객체를 사용하여 URI 경로를 기반으로 트래픽을 라우팅하는 방법을 보여줍니다:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-routes
spec:
ingressClassName: apisix
rules:
- http:
paths:
- backend:
service:
name: api-v1
port:
number: 8080
path: /v1
pathType: Exact
- backend:
service:
name: api-v2
port:
number: 8080
path: /v2
pathType: Exact
Ingress 컨트롤러는 이러한 규칙을 구현하고 리버스 프록시를 사용하여 클러스터로 트래픽을 라우팅합니다.
20개 이상의 Ingress 컨트롤러 구현이 있습니다. APISIX는 APISIX API 게이트웨이를 Kubernetes Ingress로 작동하도록 감싸는 Ingress 컨트롤러를 가지고 있습니다.
APISIX Ingress 컨트롤러는 Kubernetes Ingress 객체를 APISIX 구성으로 변환합니다.
APISIX는 이 구성을 구현합니다.
Ingress API는 특정 구현에 종속되지 않으므로 APISIX를 다른 Ingress 컨트롤러로 교체할 수 있습니다.
이 벤더 중립성은 간단한 구성에는 잘 작동합니다. 하지만 카나리 배포와 같은 복잡한 라우팅을 하려면 벤더별 주석에 의존해야 합니다.
아래 예제는 Nginx Ingress를 사용하여 카나리 배포를 구성하는 방법을 보여줍니다. 여기서 사용된 사용자 정의 주석은 Nginx에 특화되어 있습니다:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "5"
name: api-canary
spec:
rules:
- http:
paths:
- backend:
serviceName: api-v2
servicePort: 8080
path: /
위 구성은 트래픽의 5%를 api-v2 서비스로 라우팅합니다.
주석 외에도 APISIX와 같은 Ingress 컨트롤러는 Ingress API의 한계를 극복하기 위해 사용자 정의 Kubernetes CRD를 가지고 있습니다.
아래 예제는 APISIX CRD인 ApisixRoute를 사용하여 카나리 배포를 구성합니다:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: api-canary
spec:
http:
- name: route
match:
paths:
- /*
backends:
- serviceName: api-v1
servicePort: 8080
weight: 95
- serviceName: api-v2
servicePort: 8080
weight: 5
이러한 사용자 정의 CRD는 Ingress를 구성하고 API 게이트웨이의 모든 기능을 활용하기 훨씬 쉽게 만들었지만, 이식성의 비용이 따릅니다.
Kubernetes Gateway API
Gateway API는 Ingress API를 "수정"하려는 새로운 Kubernetes 객체입니다.
이는 Ingress 컨트롤러가 개발한 사용자 정의 CRD에서 영감을 받아 HTTP 헤더 기반 매칭, 가중치 기반 트래픽 분할 및 Ingress API에서 사용자 정의 주석이 필요한 기타 기능을 추가했습니다.
아래 예제는 Kubernetes Gateway API를 사용하여 카나리 배포를 구성하는 방법을 보여줍니다:
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRoute
metadata:
name: api-canary
spec:
rules:
- backendRefs:
- name: api-v1
port: 8080
weight: 95
- name: api-v2
port: 8080
weight: 5
이제 (Gateway API를 구현하는) 모든 Ingress 컨트롤러가 이 구성을 구현할 수 있습니다.
Gateway API는 Ingress API에 비해 많은 개선 사항을 제공하지만, 아직 알파 단계이며 Gateway API 구현은 계속 변경되고 있습니다.
서비스 메시
API 게이트웨이와 Kubernetes 게이트웨이는 애플리케이션 경계를 넘어 API를 추상화하면서 엣지 문제를 해결합니다.
서비스 메시는 다른 문제를 해결합니다.
서비스 메시는 서비스-클라이언트 통신(북-남 트래픽)보다는 서비스 간 통신(동-서 트래픽)에 더 관심이 있습니다.
일반적으로 이는 API/서비스와 함께 사이드카 프록시를 배포하여 달성됩니다.
여기서 사이드카 프록시는 서비스 간 통신을 처리하며, 개발자가 서비스에 네트워킹 로직을 코딩할 필요가 없습니다.
많은 서비스 메시가 있습니다. 일부 인기 있는 서비스 메시는 다음과 같습니다:
- Istio: 지금까지 가장 인기 있는 서비스 메시입니다. 많은 서비스 메시가 사용하는 Envoy 프록시 위에 구축되었습니다.
- Linkerd: Linkerd를 위해 특별히 Rust로 작성된 linkerd2-proxy를 사용하는 경량 서비스 메시입니다.
- Consul Connect: 보안과 관찰 가능성을 강조하는 서비스 메시입니다. 내장 프록시 또는 Envoy와 함께 작동할 수 있습니다.
Cilium과 같은 새로운 서비스 메시 제품은 eBPF를 통해 커널에서 직접 네트워킹 기능을 사용하여 사이드카 기반 서비스 메시에 대한 대안을 제공합니다.
일반적인 서비스 메시는 8개의 서비스에 대해 8개의 프록시가 필요하지만, Cilium과 같은 eBPF 기반 서비스 메시는 그렇지 않습니다. Cilium Service Mesh – Everything You Need to Know에서 적응됨.
서비스 메시는 또한 서비스로 들어오고 나가는 북-남 트래픽을 처리하기 위한 기본적인 인그레스/이그레스 게이트웨이를 가지고 있습니다. 인그레스 게이트웨이는 서비스 메시로 들어오는 외부 트래픽의 진입점이며, 이그레스 게이트웨이는 메시 내부의 서비스가 외부 서비스에 접근할 수 있도록 합니다.
Apache APISIX는 또한 Amesh라는 서비스 메시 구현을 가지고 있습니다. 이는 Istio의 컨트롤 플레인과 xDS 프로토콜을 사용하여 사이드카의 기본 Envoy 프록시를 대체합니다.
서비스 메시는 카나리 배포를 구성할 수 있게 합니다. 예를 들어, 한 서비스의 요청을 다른 서비스의 두 버전으로 분할할 수 있습니다.
아래 예제는 Istio 서비스 메시를 사용하여 카나리 배포를 구성하는 방법을 보여줍니다:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: api-virtual-service
spec:
hosts:
- api
http:
- route:
- destination:
host: api
subset: v1
weight: 80
- destination:
host: api
subset: v2
weight: 20
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: api-destination-rule
spec:
host: api
subsets:
- name: v1
labels:
version: "1.0"
- name: v2
labels:
version: "2.0"
이러한 구성은 Istio에 특화되어 있습니다. 다른 서비스 메시로 전환하려면 비슷하지만 벤더에 종속된 구성을 만들어야 합니다.
Service Mesh Interface (SMI) 사양은 이 이식성 문제를 해결하기 위해 만들어졌습니다.
SMI 사양은 서비스 메시 사용자가 서비스 메시 구현에 구속되지 않고 애플리케이션을 정의할 수 있는 Kubernetes CRD 집합입니다.
표준화 시도는 모든 프로젝트가 참여할 때만 작동합니다. 하지만 SMI 사양에서는 몇몇 프로젝트만 적극적으로 참여했습니다.
최근에는 Kubernetes SIG Network가 서비스 메시를 지원하기 위해 Gateway API를 발전시키고 있습니다.
GAMMA (Gateway API for Mesh Management and Administration) 이니셔티브는 Gateway API 프로젝트 내의 전담 그룹으로, "서비스 메시 기술 및 사용 사례와 관련된 Gateway API 리소스, 의미론 및 기타 아티팩트를 조사, 설계 및 추적"하는 목표를 가지고 있습니다.
Gateway API는 Ingress API의 자연스러운 다음 단계이지만, 서비스 메시에 대해 어떻게 작동할지는 지켜봐야 합니다. Istio는 Gateway API를 모든 트래픽 관리의 기본 API로 사용할 의도를 발표했으며, 프로젝트를 계속 추진하고 있습니다.
아래 예제는 Istio에서 Gateway API를 사용하여 카나리 배포를 구성하는 방법을 보여줍니다. 기본 아이디어는 게이트웨이 대신 다른 서비스에 연결하기 위해 parentRefs를 사용하는 것입니다:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: api-canary
spec:
parentRefs:
- kind: Service
name: api-a
port: 8080
rules:
- backendRefs:
- name: api-b-v1
port: 8080
weight: 95
- name: api-b-v2
port: 8080
weight: 5
GAMMA 프로젝트가 특정 프로젝트의 요구를 충족하기 위해 편향될 수 있다는 일부 우려가 있으며, 이는 결국 다른 프로젝트가 자체 API를 사용하게 될 수 있습니다. 이는 Kubernetes Ingress API 이후의 사용자 정의 CRD 시나리오와 유사합니다.
하지만 Gateway API 프로젝트는 서비스 메시에서 트래픽 관리를 표준화하기 위한 최선의 시도였습니다. SMI 프로젝트도 GAMMA 이니셔티브에 참여하여 공유된 비전을 가지고 있으며, 서비스 메시 프로젝트가 Gateway API를 일관되게 구현하도록 옹호할 것입니다.
Flagger 및 Argo Rollouts와 같은 다른 프로젝트도 Gateway API와 통합되었습니다.
무엇을 사용해야 할까요?
이 질문에 대한 하나의 정답은 "상황에 따라 다르다"입니다.
API를 개발하고 인증, 보안, 라우팅 또는 메트릭이 필요하다면, API 게이트웨이를 사용하는 것이 API에 이를 직접 구축하는 것보다 낫습니다.
Kubernetes 환경에서 비슷한 작업을 하려면, API 게이트웨이를 Kubernetes에서 작동하도록 고생하는 대신 Kubernetes 게이트웨이를 사용해야 합니다. 다행히 많은 API 게이트웨이가 Kubernetes 네이티브 구성과 함께 작동합니다.
하지만 때로는 API 게이트웨이 + Ingress 컨트롤러가 제공하는 기능이 Kubernetes 환경에서는 과도할 수 있으며, 간단한 트래픽 관리로 돌아가고 싶을 수도 있습니다.
반면, 서비스 메시는 완전히 다른 문제를 해결합니다. 그들은 북-남 트래픽을 처리하기 위한 자체 게이트웨이를 가지고 있으며(보통 충분함), 더 많은 기능을 가진 자체 게이트웨이를 사용할 수도 있습니다.
Kubernetes Gateway API를 통해 API 게이트웨이와 서비스 메시의 수렴은 애플리케이션 개발자가 기본 구현에 대해 걱정하지 않고 문제를 해결하는 데 집중할 수 있도록 해야 합니다.
Apache APISIX와 같은 프로젝트는 동일한 기술을 사용하여 API 게이트웨이와 서비스 메시 제품을 구축하고 이러한 사양과 잘 통합되어 벤더 중립적인 선택을 장려합니다.
또한 이러한 것들이 필요하지 않을 수도 있습니다. 마이크로서비스가 필요하지 않을 수도 있고, 분산 아키텍처가 필요하지 않을 수도 있지만, 필요할 때 게이트웨이와 메시는 삶을 훨씬 쉽게 만들어 줄 수 있습니다.