개요
쿠버네티스 환경에서 동작하는 서비스를 외부에 노출하고 싶다. 보통 서비스를 외부에 노출할 때는 Nginx Ingress Controller를 배포한 뒤 kubernetes Ingress 리소스를 생성해 왔는데, 현재 구성 중인 환경에서는 Istio를 사용 중이다. 그리고 Istio와 Nginx Ingress Controller는 포트 충돌 등의 이유로 함께 사용하지 않는 것 같다. Istio를 사용할 때는 Nginx Ingress Controller 대신 Istio Ingress Gateway를 사용하여 Ingress를 구성하거나 Gateway와 VirtualService를 이용해 서비스를 외부에 노출하는 것으로 보인다.
그림으로 표현하면 아래와 같은 구조가 되는 것 같다.
이 글에서는 https://killercoda.com/lorenzo-g의 Ingress - Gateways를 따라해보면서 Ingress Gateway, Gateway와 VirtualService를 구성해 서비스를 외부에 노출하는 방법을 적어둔다. 애플리케이션 자체는 이미 동작 중인 환경이다.
Ingress Gateway
Istio의 Igress Gateway는 외부 트래픽을 클러스터 내부로 들어오게 하는 관문에 해당한다. 내부로 들어온 트래픽은 실제 서비스 Pod로 라우팅 하는 기능을 수행한다.
Istioctl를 이용해 설치하는 경우, 설치 시 지정한 profiledl default, demo라면 자동으로 함께 설치된다.
2024.02.09-[Istio] 다운로드 및 설치에서 demo profile을 사용해 설치해봤을 때 실제로 함께 설치된 모습을 확인할 수 있다.
Istio ingress Gateway는 기본적으로 LoadBalancer 유형의 서비스와 연결된다. 아래 사진은 EXTERNAL-IP가 pending 상태인데 이는 배포 환경이 killercoda의 플레이그라운드라 실제 로드 밸런서와 연결되지 못했기 때문이다.
만약 사용 중인 쿠버네티스 환경에서 로드 밸런서를 사용하지 않으면 MetalLB 등을 구성해야 한다.
또는 NodePort를 이용해 Istio Ingress Gateway에 접근할 수도 있다. (https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/#using-node-ports-of-the-ingress-gateway-service)
export INGRESS_NAME=istio-ingressgateway
export INGRESS_NS=istio-system
export INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
export TCP_INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="tcp")].nodePort}')
만약 사용 중인 쿠버네티스 환경에 Istio Ingress Gateway가 배포되어 있지 않다면 공식 문서를 참조하여 배포해야 한다.
참고 : https://istio.io/latest/docs/setup/additional-setup/gateway/
Istio Gateway
Istio의 Gateway은 쿠버네티스 내부로 들어오거나 나가는 HTTP/TCP 트래픽을 관리하는 서비스 메시 관문이다. 일종의 로드 밸런서에 해당된다. Istio Gateway를 생성할 때는 노출되는 포트와 프로토콜, 호스트 정보 등이 필요하다.
아래 예시는 HTTP를 통해 booking.example.com이라는 도메인을 노출한 것이다.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: booking-gateway
spec:
# The selector matches the ingress gateway pod labels.
selector:
istio: ingressgateway
servers:
- name: booking
port:
number: 80
name: http
protocol: HTTP
hosts:
- "booking.example.com"
VirtualService
Istio VirtualService는 Istio Gateway를 통해 들어온 트래픽에 대한 경로를 구성한다. 도메인과 Gateway, 그리고 라우팅 정보 등을 지정해야 한다.
아래 예시는 booking.example.com 도메인으로 booking-gateway를 통해 들어온 트래픽을 booking-service의 80 포트로 라우팅 하는 VirtualService 예시이다.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: booking
spec:
hosts:
- "booking.example.com"
gateways:
- booking-gateway
http:
- route:
- destination:
port:
number: 80
host: booking-service
접속 테스트
이제 구성한 도메인을 사용해 서비스에 접근할 수 있다.
이 테스트 환경에서는 Istio Igress Gateway가 NodePort로 구성되어 있기 때문에
도메인 뒤에 HTTP에 접근할 때 사용하는 노드 포트인 30000을 명시해야 한다.
curl http://booking.example.com:30000/bookings; \
echo;
참고 문서
https://findstar.pe.kr/2021/04/14/istio-traffic-management/
https://ibm.github.io/istio101/exercise-5/
https://netpple.github.io/docs/istio-in-action/Istio-ch3-envoy