Gateway와 VirtualService
Gateway와 VirtualService는 Istio에서 트래픽을 관리하는 핵심 리소스입니다.
목차
이 장은 Kubernetes Gateway API와 구분되는 networking.istio.io/v1 Gateway를 사용합니다. 예제는 istio-system의 istio=ingressgateway 워크로드/Service, default의 앱 Service와 일치하는 서비스 포트를 전제로 합니다. Istio Gateway는 기존 프록시를 구성하며 프록시를 새로 생성하지 않습니다. TLS Secret은 게이트웨이 워크로드 네임스페이스에 생성하고 테스트할 Gateway에 VirtualService를 연결하세요. 같은 호스트 예제는 대안 구성이므로 동시에 적용하지 않습니다.
Gateway 개요
Gateway는 메시로 들어오는 외부 트래픽의 진입점을 정의합니다.
yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway # Ingress Gateway 파드 선택
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "myapp.example.com"
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: myapp-tls
hosts:
- "myapp.example.com"VirtualService 개요
VirtualService는 메시 Sidecar 및/또는 명시적으로 참조한 게이트웨이의 라우팅을 정의합니다.
yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: myapp
namespace: default
spec:
hosts:
- "myapp.example.com"
gateways:
- istio-system/my-gateway
http:
- match:
- uri:
prefix: "/api"
route:
- destination:
host: api-service
port:
number: 8080
- route:
- destination:
host: frontend-service
port:
number: 3000기본 설정
HTTP 트래픽
yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: http-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*" # 모든 호스트 허용
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: app-routes
spec:
hosts:
- "*"
gateways:
- istio-system/http-gateway
http:
- route:
- destination:
host: myapp
port:
number: 8080HTTPS 트래픽
bash
# TLS 인증서 Secret 생성
kubectl create secret tls myapp-tls \
--cert=myapp.crt \
--key=myapp.key \
-n istio-systemyaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: https-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: myapp-tls
hosts:
- "myapp.example.com"실전 예제
Path 기반 라우팅
yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: path-routing
spec:
hosts:
- "myapp.example.com"
gateways:
- istio-system/my-gateway
http:
# API 트래픽
- match:
- uri:
prefix: "/api/v1"
route:
- destination:
host: api-v1
port:
number: 8080
# Admin 트래픽
- match:
- uri:
prefix: "/admin"
route:
- destination:
host: admin-service
port:
number: 9000
# 기본 트래픽
- route:
- destination:
host: frontend
port:
number: 3000Header 기반 라우팅
yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: header-routing
spec:
hosts:
- reviews
http:
# Mobile 트래픽
- match:
- headers:
user-agent:
regex: ".*Mobile.*"
route:
- destination:
host: reviews
subset: mobile-v2
# 개발자 트래픽
- match:
- headers:
x-dev-user:
exact: "true"
route:
- destination:
host: reviews
subset: v3
# 기본 트래픽
- route:
- destination:
host: reviews
subset: v1헤더 예제의 mobile-v2, v3, v1 DestinationRule subset과 일치하는 파드 레이블을 먼저 준비하세요. 클라이언트 라우팅 헤더는 인가 수단이 아닙니다. 아래 정적 응답 헤더는 예시이며 측정한 지연 시간이 아닙니다.
다중 도메인 설정
yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: multi-domain-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https-api
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: api-tls
hosts:
- "api.example.com"
- port:
number: 443
name: https-admin
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: admin-tls
hosts:
- "admin.example.com"
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: api-routes
spec:
hosts:
- "api.example.com"
gateways:
- istio-system/multi-domain-gateway
http:
- route:
- destination:
host: api-service
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: admin-routes
spec:
hosts:
- "admin.example.com"
gateways:
- istio-system/multi-domain-gateway
http:
- route:
- destination:
host: admin-service고급 패턴
HTTP to HTTPS 리다이렉트
yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: secure-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
# HTTP (리다이렉트용)
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "myapp.example.com"
tls:
httpsRedirect: true # HTTPS로 리다이렉트
# HTTPS
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: myapp-tls
hosts:
- "myapp.example.com"URL Rewrite
yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: url-rewrite
spec:
hosts:
- "myapp.example.com"
gateways:
- istio-system/my-gateway
http:
- match:
- uri:
prefix: "/old-api"
rewrite:
uri: "/api/v2" # URL 재작성
route:
- destination:
host: api-serviceHeader 추가/수정
yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: header-manipulation
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
headers:
request:
add:
x-custom-header: "custom-value"
x-demo-stage: "gateway"
set:
x-api-version: "v2"
remove:
- x-internal-header
response:
add:
x-demo-response: "configured-value"Redirect
yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: redirect-example
spec:
hosts:
- "myapp.example.com"
gateways:
- istio-system/my-gateway
http:
- match:
- uri:
prefix: "/old-page"
redirect:
uri: "/new-page"
authority: "newapp.example.com"문제 해결
Gateway가 작동하지 않음
bash
# 1. Gateway 상태 확인
kubectl get gateways.networking.istio.io -n istio-system
# 2. Ingress Gateway 파드 확인
kubectl get pods -n istio-system -l istio=ingressgateway
# 3. Gateway 구성 확인
kubectl describe gateways.networking.istio.io my-gateway -n istio-system
# 4. Envoy 구성 확인
istioctl proxy-config listeners -n istio-system istio-ingressgateway-xxxVirtualService 라우팅 실패
bash
# 1. VirtualService 확인
kubectl get virtualservice
# 2. 구성 분석
istioctl analyze
# 3. 라우팅 규칙 확인
istioctl proxy-config routes -n istio-system istio-ingressgateway-xxx
# 4. 로그 확인
kubectl logs -n istio-system -l istio=ingressgateway --tail=100TLS 인증서 문제
bash
# Secret 확인
kubectl get secret -n istio-system myapp-tls
# Secret 내용 확인
kubectl describe secret -n istio-system myapp-tls
# Gateway TLS 구성 확인
istioctl proxy-config secret -n istio-system istio-ingressgateway-xxx모범 사례
- 네임스페이스 분리: Gateway는
istio-system에, VirtualService는 애플리케이션 네임스페이스에 - TLS 필수 사용: 프로덕션 환경에서는 항상 HTTPS 사용
- 명확한 호스트 지정: 와일드카드(
*) 대신 명시적 도메인 사용 - Match 조건 순서: 구체적인 조건을 먼저, 일반적인 조건은 나중에
- 리소스 네이밍: 일관된 네이밍 규칙 사용