Gateway API
개요
Gateway API is a family of API kinds that provide dynamic infrastructure provisioning and advanced traffic routing.[1]
게이트웨이 api는 동적인 인프라 프로비저닝과 향상된 트래픽 라우팅 기능을 제공하는 api 종류의 집합이다.
그냥 게이트웨이면 게이트웨이라 하지 싶은데, 3가지의 오브젝트가 합쳐진 콤비네이션이라 굳이 이렇게 부르는 듯하다.
인그레스를 거의 상속하는 대체제로 최근 조금씩 사람들도 인식하고 있는 것 같다.
기본으로 쿠버네티스의 api로 제공되는 것은 아니고, CRD를 설치해주어야 한다.
한글로 부르기가 조금 애매한 친구.. 나는 그냥 게아라고 부른다.
Gateway API vs API Gateway
처음 이름을 접할 때 조금 헷갈리는 포인트.[2]
이름으로 말장난 하는 거 아니냐! 싶지만..
api 게이트웨이는 백엔드 서비스를 노출하는 일반적인 컨셉을 이야기한다.
물론 여기에 트래픽 라우팅, 밸런싱, 인증 인가 등의 다양한 기능을 가질 수 있다.
반면 게이트웨이 api는 쿠버네티스 네트워킹을 위해 제공되는 인터페이스이자 모델, 집합체이다.
그래서 api 게이트웨이라는 컨셉 아래 게이트웨이 api라는 프레임, 모델이 성립한다고 보면 되겠다.
이 모델을 구현하는 구현체에 따라 차이는 있겠으나 게이트웨이 api는 api 게이트웨이로서의 기능을 가진다.
기능 - 디자인 구조
게아 아키텍쳐는 아래의 디자인 원칙을 따르며 설계됐다.
- 역할 기반 - 조직적 역할을 기반으로 구성될 수 있도록 하여 운영 이슈를 줄인다.
- 인프라 제공자 - 클러스터 자원 제공자로, 여러 클러스터에 여러 테넌시를 관리한다.
- 클러스터 운영자 - 정책, 네트워크 접근, 앱 권한 등을 설정하는 관리자로, 한 클러스터의 전반을 책임진다.
- 앱 개발자 - 앱 레벨의 설정과 구성에 초점을 맞추는 개발자로, 클러스터 위에서 구동될 앱을 만든다.
- 휴대성 - 커스텀 리소스를 기반으로 정의되어 다양한 구현체를 가진다.
- 표현성 - 헤더 기반, 가중치 기반 라우팅 등 어노테이션으로만 제공한 인그레스의 기능들을 지원한다.
- 확장성 - api의 다양한 층과 결합하여 트래픽 아키텍쳐 상에 적절한 장소에 커스텀 리소스를 넣을 수 있게 한다.
나는 기능을 이렇게 두 가지 관점에서 정리하고자 한다.
- 클러스터 내의 조직 역할 기반으로 네트워크 관련 권한 및 설정 분리
- 인그레스보다 확장성 있고 유연한 트래픽 처리 기능(로드밸런싱, 헤더 조작, 인증 인가 등)
아무튼 세 그룹의 역할을 기반으로 개발이 됐기에 보다시피 3개의 오브젝트가 나오게 됐다.
서비스 메시 설정 리소스 - East-West 트래픽 관리
먼저 분명히 할 지점이 있는 게, 기본적으로 gateway api는 인그레스를 대체하기 위해 개발됐다.
그래서 클러스터 바깥에서 들어오는 트래픽을 관리하는데 특화돼있다는 것을 유의해야 한다.
게이트웨이라는 이름에 걸맞게 클러스터 내외부를 연결하는, North-South 트래픽을 관리하기 용이하도록 개발됐다는 것이다.
이걸 굳이 언급하는 것은 gateway api가 서비스 메시의 대체제로도 어느 정도 활용될 수 있기 때문이다.
구체적으로는 서비스 메시를 설정하는 리소스라고 하는 것이 맞겠다.
대표적으로 이스티오의 설정들을 여기의 리소스들을 이용해서 진행하는 것이 가능한데, 실제로 양식을 보면 거의 비슷하게 생긴 것을 볼 수 있다.
(이스티오 팀에서 게이트웨이 api를 주도적으로 개발하고 있어서 그런 것도 있다.)
이렇게 하기 위해서는 gateway api의 하위 프로젝트인 GAMMA Initiative 프로젝트에서 개발 중인 기능을 사용해야 한다.[3]
Gateway Api for Mesh Management and Administration은 2022년부터 생긴 서브 프로젝트로 gateway api를 클러스터 내부의 트래픽을 조절하는데 사용하기 위한 기능 개발 목적을 가지고 있는 작업을 진행하고 있다.
글을 계속 봤을 때는 기본적으로 다른 네임스페이스 간 라우트를 통제하는 것에 주안점을 두고 있는 것으로 보인다.
productor, consumer 라우트를 구분하는 기준이 네임스페이스던데, 아직 문서가 명쾌하게 정리가 이뤄지지 않은 듯한 느낌을 받았다.
종류
그래서 어떤 오브젝트들이 있는가?
게아에서는 조직에서 역할 기반 설정을 제공하고자 상호의존적인 관계를 맺는 오브젝트들을 만들었다.
이런 식으로 각 오브젝트에 권한을 부여하여 책임 영역을 확실하게 지정하는 방향으로 운영에 활용할 수 있다!
GatewayClass
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: example-class
spec:
controllerName: example.com/gateway-controller
클래스를 구현하는 컨트롤러와 설정을 통해 여러 게이트웨이를 정의하는 오브젝트.
인프라 제공자가 설정할 영역의 오브젝트라고 할 수 있다.
컨트롤러와는 1:1 관계를 맺는다.
이 친구는 클러스터 전역의 리소스로, 인그레스로 치자면 Ingress#인그레스 클래스라고 할 수 있다.
Gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-gateway
spec:
gatewayClassName: example-class
listeners:
- name: http
protocol: HTTP
port: 80
로드 밸런싱 등의 트래픽 처리 인프라 인스턴스를 정의하는 오브젝트.
클러스터 운영자가 설정할 영역의 오브젝트라고 할 수 있다.
여기에서 어떤 트래픽들을 어떻게 처리하고 싶은지 설정한다.
가령 80으로 들어오는 http 프로토콜만 처리하고 싶다던가, 하는 설정들이 있겠다.
자신의 리스너에 첨부될 수 있는 경로를 필터링함으로써 양방향 신뢰 관계를 형성할 수 있다.
개발자가 아무 경로나 열어버리지 않도록, 운영자가 제한할 수 있다는 말이다.
네트워크 흐름으로서는 말 그대로 게이트웨이 역할을 한다.
즉, 클러스터에 들어올 ip 경로가 곧 게이트웨이가 되는 것이다.
위의 GatewayClass와는 다:1 관계를 맺는다.
즉 하나의 GatewayClass는 여러 Gateway를 가질 수 있다.
(가진다는 표현은 조금 애매한데, 여러 Gateway가 하나의 GatewayClass를 참조할 수 있다 보는 게 좋겠다.)
예시로는 클러스터 외부를 들었지만, 그냥 트래픽이 서비스로 연결될 수 있는 길로서의 역할을 하기에 당연히 내부에서도 사용될 수 있다.
그런 식으로 설정하면 완벽히 API Gateway로서 설정하는 것이라 할 수 있겠다.
기본설정과 행동은 게웨클에 의해 지정된다.
이것은 게웨클을 관리하는 컨트롤러에 의해 만들어질 수도, 관리자가 직접 만들 수도 있다.
참고로 이 리소스를 지정하면 실제 트래픽을 담당하게 될 서비스와 워크로드가 알아서 배포된다.
이 부분은 이스티오의 gateway와 분명하게 대비되는 지점이며, 같이 생기게 될 리소스들에 대해 설정을 하는 필드도 존재한다.[4]
gateway 리소스의 listeners
필드는 어떤 트래픽을 받을지, 그리고 이렇게 열린 게이트웨이에 연결될 수 있는 route 리소스는 어떤 것이 가능한지 지정한다.
# 모든 네임스페이스의 라우트 허용
allowedRoutes:
namespaces:
from: ALL
---
# 셀렉팅된 네임스페이스만 허용
allowedRoutes:
namespaces:
from: Selector
selector:
kubernetes.io/name: test
allowedRoutes
필드의 경우 어떤 네임스페이스의 route 리소스를 허용할지 지정한다.
기본은 같은 네임스페이스의 리소스만 허용하는데, 위처럼 모든 네임스페이스나 특정 네임스페이스들만 허용하는 것도 가능하다.
Route
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-httproute
spec:
parentRefs:
- name: example-gateway
hostnames:
- "www.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /login
backendRefs:
- name: example-svc
port: 8080
게이트웨이 리스너로부터 백엔드포인트로 이어지는 구체적인 트래픽 규칙을 지정하는 오브젝트.
앱 개발자가 설정할 영역의 오브젝트라고 할 수 있다.
따지자면 이 놈이 라우팅 룰을 넣는 인그레스와 비교될 만하겠다.
여기에서의 엔드포인트는 서비스를 의미하며, 구체적으로 어떻게 연결할지에 대한 규칙을 지정한다.
위의 게이트웨이에 세부 규칙들을 지정하여 원하는 작업들을 수행한다.
프로토콜, 경로, 헤더 등 다양한 것들을 기반으로 연결할 백엔드를 지정할 수 있다.
게이트웨이와 다:다 관계를 맺는다.
즉 하나의 게이트웨이가 여러 라우트를 가질 수 있고, 하나의 라우트 역시 여러 게이트웨이에 붙여질 수 있다.
프로토콜 별로 세부적인 라우트 종류가 있다.
- HTTPRoute
- GRPCRoute
- TLSRoute
- TCPRoute
- UDPRoute
이름만 봐도 뭔지 알만 해서 추가적으로 설명은 않겠다만, 현재 stable 단계인 것은 아직 http, grpc 뿐이다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ratings
spec:
parentRefs:
- name: ratings
kind: Service
group: ""
port: 9080
rules:
- name: retry
matches:
- path:
type: PathPrefix
value: /ratings
retry:
attempts: 5
codes:
- 503
- 501
backendRefs:
- name: ratings
port: 9080
원래 Route 리소스는 parentRef
필드에 Gateway 리소스를 적어야 한다.
근데 서비스 메시로서 클러스터 내부 트래픽을 관리할 때를 위해, 위처럼 서비스를 대상으로 지정하는 것도 가능하다.
ReferenceGrant
이 친구는 다른 네임스페이스의 서비스에 연결하고 싶을 때 쓴다.[5]
재밌는 게, PV에서 네임스페이스를 넘나들 때도 사용된다!
동작 흐름
동작 흐름을 구체적으로 따라가보자.
클라이언트의 dns 쿼리 요청은 게이트웨이의 ip 주소를 알려준다.
해당 주소로 요청이 날아가면 이 게이트웨이에 붙은 httproute 중 조건에 매칭되는 놈이 작동할 것이다.
여기에서 헤더를 제거하던, 바꾸던 경로를 바꾸던 각종 다양한 작업을 할 수 있고 이것이 최종적으로 서비스로 전달된다.
이스티오와의 비교
이스티오와 설정이 상당히 비슷하니, 이스티오와 어떤 식으로 비교되는지 간단하게 정리해보자.[6]
- 이스티오의 gateway는 이미 배포된 게이트웨이 관련 워크로드를 기반(ingress gatewayr가 그 워크로드이다)으로 세팅만 하는 리소스이다.
- 반면 gateway api의 gateway는 설정과 배포를 동시에 진행하는 리소스이다.
- gatewayclass가 제대로 설정돼있다면, gateway 리소스를 만드는 것만으로 실제 트래픽을 담당하는 워크로드가 같이 배포된 것을 확인할 수 있었다.
- 그래서 ingress gateway를 따로 구축하지 않고도 편하게 설정이 가능하다!
- 이스티오의 virtualservice는 모든 프로토콜을 하나의 리소스에서 관리한다.
- gateway api는 각 프로토콜에 맞게 route 리소스(HTTPRoute, TLSRoute, TCPRoute 등등)를 따로 만든다.
- 아직 gateway api는 이스티오의 모든 기능을 커버하진 않는다!
- 일단 대표적으로 위에서도 보았듯이 gateway api는 서비스 메시로서 기능하기 위한 리소스가 아니라 인그레스를 대체하는 리소스의 집합이다.
- 그래서 서비스 메시를 기대하고 사용하려 하면.. 조금 아쉬운 경우를 왕왕 마주할 것으로 생각된다.
- 당장 재시도 설정을 하기 위해 stable이 아닌 상태의 api를 사용해야 했던 것만 봐도 그렇다.
사용성은 어떠한가?
사실 설정 방식 자체는 대체로 비슷해서 엄청난 차이가 느껴지진 않았다.
다만 이스티오의 리소스는 이스티오 컨트롤 플레인과 잘 결합되어 설정이 잘 되는 편이다.
그러나 게이트웨이 api는 통신 간 암호화를 위해서는 추가적인 설정을 필요로 한다던가 하는 별도의 설정들이 더 필요한 편이다.
게이트웨이 api는 쿠버의 공식 api로 결합되었기에, 서비스 메시를 사용하지 않는 조직에서 인그레스를 대체하기 위한 용도로 사용하기에는 꽤나 유용하다.
인그레스는 앞으로도 업데이트가 되지 않을 예정이기에 궁극적으로 게이트웨이 api를 사용하는 방향으로 가는 것은 기술 부채로부터 상대적으로 안전하다.
앞으로 기능 개발과 문서화가 더 이뤄져서 성숙도가 높아진다면 완전히 서비스 메시 설정 리소스로서 활용하기에도 좋을 것이라 생각한다.
설치
kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
{ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.1" | kubectl apply -f -; }
위에서 언급했듯이 기본적으로 CRD는 별도로 설치를 해줘야만 한다.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml
아직 완전히 stable로 넘어가지 않은 실험적 기능들을 사용하고 싶다면 이걸 적용하자.[7]
25년 4월을 기준으로 서비스 메시를 대체할 정도의 기능들은 아직 stable이 되지 않아서 이걸 이용해야 한다.
툴
- ingress2gateway
- 기존의 인그레스를 게아로 전환할 수 있도록 도와준다.
- gwctl
- 게아를 다룰 수 있도록 도와주는 cli다.
관련 문서
이름 | noteType | created |
---|
참고
https://kubernetes.io/docs/concepts/services-networking/gateway/ ↩︎
https://gateway-api.sigs.k8s.io/reference/spec/#gatewayinfrastructure ↩︎
https://gateway-api.sigs.k8s.io/api-types/referencegrant/ ↩︎
https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/ ↩︎
https://gateway-api.sigs.k8s.io/guides/#install-experimental-channel ↩︎