Istio VirtualService
Istio의 Virtual Service는 서비스 메시에 있는 트래픽의 라우팅을 제어하는 중요한 구성 요소입니다. Kubernetes와 같은 환경에서 마이크로서비스 간의 통신을 세밀하게 관리하고, 서비스로의 요청 흐름을 정의하는 데 사용됩니다. Virtual Service는 서비스의 특정 버전으로 트래픽을 보낼 수 있게 하며, 라우팅 규칙, 트래픽 분할, A/B 테스트, Canary 배포, 실패 복구 등을 쉽게 설정할 수 있도록 지원합니다.
1. VirtualService 란?
주요 기능 및 개념
- 트래픽 라우팅: Virtual Service는 트래픽을 여러 버전의 서비스로 라우팅할 수 있습니다. 예를 들어, 80%의 트래픽을 서비스의 v1 버전으로 보내고, 나머지 20%는 v2 버전으로 보내는 식으로 트래픽을 분할할 수 있습니다.
- 호스트 및 경로 기반 라우팅: 특정 URL 경로나 HTTP 헤더 값에 따라 서로 다른 서비스를 호출하게 설정할 수 있습니다. 예를 들어,
/api/v1
로 오는 요청은 v1 버전 서비스로,/api/v2
로 오는 요청은 v2 버전 서비스로 라우팅하는 식입니다. - A/B 테스트 및 Canary 배포: 새로운 버전의 서비스가 배포될 때, Virtual Service를 통해 트래픽의 일부만 새 버전으로 보내서 안전하게 테스트할 수 있습니다. 이 방식으로 Canary 배포나 A/B 테스트가 가능합니다.
- 실패 복구: Virtual Service는 트래픽을 자동으로 리트라이하거나 타임아웃을 설정하는 등의 기능을 제공하여 서비스 장애 시 트래픽을 안전하게 처리할 수 있게 도와줍니다.
- 부하 분산 및 페일오버: 여러 서비스 인스턴스 간 부하를 고르게 분산시키거나 특정 인스턴스가 다운되었을 때 다른 인스턴스로 트래픽을 자동으로 전환하는 기능을 지원합니다.
Virtual Service의 구성 요소
- hosts: Virtual Service가 적용될 대상 서비스의 이름을 정의합니다.
- http, tcp, tls: 다양한 프로토콜에 따라 라우팅 규칙을 정의합니다.
- match: 요청을 구분하는 조건을 정의하는 부분으로, URL 경로, HTTP 헤더, 쿠키 등 다양한 기준을 기반으로 설정 가능합니다.
- route: 특정 매치 조건을 만족하는 트래픽을 어디로 라우팅할지 설정합니다. 보통 특정 서비스와 관련된
Destination
을 지정합니다.
Virtual Service의 예시
yaml
Copy code
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-service
spec:
hosts:
- my-service
http:
- match:
- uri:
exact: /v1
route:
- destination:
host: my-service
subset: v1
- match:
- uri:
exact: /v2
route:
- destination:
host: my-service
subset: v2
위 예시에서 /v1
로 요청이 오면 서비스의 v1으로, /v2
로 요청이 오면 서비스의 v2로 라우팅됩니다.
2. 라우팅 방식
Istio에서 트래픽을 분배하는 방식은 여러 가지가 있으며, weight 방식 외에도 다양한 라우팅 전략을 사용할 수 있습니다. 기본적으로 Istio는 트래픽을 Round Robin 방식으로 분배합니다. 이를 통해 여러 서비스 인스턴스에 균등하게 트래픽을 분산할 수 있습니다.
1. Round Robin 라우팅
Round Robin은 각 서비스 인스턴스에 순차적으로 트래픽을 전달하는 방식입니다. Istio의 기본 동작이므로 특별한 설정 없이도 라우팅을 할 수 있습니다. Round Robin은 다음과 같이 설정할 수 있습니다.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-virtualservice
spec:
hosts:
- my-service.my-namespace.svc.cluster.local
http:
- route:
- destination:
host: service-a.my-namespace.svc.cluster.local
- destination:
host: service-b.my-namespace.svc.cluster.local
위의 설정은 기본적으로 Round Robin 방식으로 service-a와 service-b 간에 트래픽을 균등하게 분배합니다.
2. Cookie 기반 세션 스티키니스 (Session Affinity)
Istio에서는 특정 사용자에게 동일한 서비스 인스턴스로 트래픽을 보내기 위해 session affinity를 설정할 수 있습니다. 이를 통해 사용자가 첫 번째 요청을 보낸 서비스에 대해 이후 요청도 같은 서비스로 라우팅할 수 있습니다.
예를 들어, HTTP 쿠키를 기반으로 세션을 유지하는 방법은 다음과 같습니다:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: destination-rule-for-my-service
spec:
host: my-service.my-namespace.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: LEAST_CONN # 최소 연결 수 기준으로 분배
3. Weighted Routing
Weighted Routing은 앞서 설명한 weight 방식으로, 여러 서비스로 트래픽을 비율에 따라 분산할 수 있는 방법입니다. 이 방법은 특정 서비스에 대한 트래픽 비율을 조절할 수 있어, 새로운 버전의 서비스로의 점진적인 롤아웃에 유용합니다.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-canary-service
spec:
hosts:
- my-service.my-namespace.svc.cluster.local
http:
- route:
- destination:
host: service-v1.my-namespace.svc.cluster.local
weight: 90
- destination:
host: service-v2.my-namespace.svc.cluster.local
weight: 10
4. A/B 테스트 및 Canary 배포
Istio는 A/B 테스트 또는 Canary 배포를 통해 일부 트래픽만 새로운 서비스 버전으로 보내고 나머지는 기존 버전으로 라우팅할 수 있습니다. 예를 들어, Canary 배포를 설정하면 다음과 같이 특정 비율의 트래픽만 새로운 서비스로 보낼 수 있습니다
5. 기타 라우팅 옵션
- Path Routing: 특정 경로에 따라 트래픽을 다른 서비스로 라우팅할 수 있습니다.
- Header Routing: HTTP 요청의 헤더에 따라 라우팅을 조정할 수 있습니다.
요약
- Round Robin은 기본적으로 지원되는 트래픽 분배 방식으로, 별도의 설정 없이 사용할 수 있습니다.
- Session Affinity를 통해 사용자 세션을 관리하거나, A/B 테스트 및 Canary 배포와 같은 방법으로 특정 서비스에만 트래픽을 보내는 것도 가능합니다.
- 다양한 라우팅 방식과 설정을 활용하여 애플리케이션의 요구사항에 맞게 Istio의 트래픽 관리를 조정할 수 있습니다.
3. Service 장애 시 분배 처리
Istio의 VirtualService에서 weight
로 트래픽을 분배하는 경우, 한쪽 서비스가 다운되었을 때 Istio는 기본적으로 트래픽을 정상적으로 동작하는 다른 서비스로 자동으로 라우팅하지는 않습니다. 즉, Istio는 주어진 weight
에 따라 트래픽을 보내려 하지만, 다운된 서비스로 트래픽을 보내면 실패할 수 있습니다.
Istio가 기본적으로 제공하는 기능:
- 헬스체크 또는 Probe: Kubernetes에서는 각 서비스에 대해 Liveness 및 Readiness Probe를 설정할 수 있습니다. 서비스가 다운되거나 비정상적인 경우, 해당 서비스로 트래픽을 보내지 않도록 Kubernetes가 관리하지만, Istio는 이와는 별개로 동작합니다.
- Istio의 기본 리트라이 기능: Istio는 서비스가 일시적으로 응답하지 않을 때 트래픽을 다시 시도할 수 있도록 리트라이(retry) 기능을 제공하지만, 완전히 다운된 경우에 대해서는 이 기능만으로는 충분하지 않습니다.
- Failover를 구현하는 방법: Istio에서 한쪽 서비스가 죽었을 때 자동으로 다른 서비스로 트래픽을 라우팅하려면 추가적인 설정이 필요합니다. 예를 들어
DestinationRule
을 이용해outlier detection
을 설정하여, 특정 조건에서 서비스가 비정상적일 때 이를 감지하고 해당 서비스로 트래픽을 보내지 않도록 할 수 있습니다.
해결 방법: Outlier Detection (오류 감지 및 제거)
이를 구현하려면 Istio의 DestinationRule
에서 Outlier Detection
을 설정해줍니다. 이 설정은 일정 횟수 이상 오류가 발생하면 해당 인스턴스를 "격리"하고 트래픽을 보내지 않도록 만듭니다.
Outlier Detection: DestinationRule
의 trafficPolicy
안에 outlierDetection
설정을 추가합니다.
- consecutive5xxErrors: 연속해서 5xx 오류가 발생한 횟수입니다. 설정된 횟수에 도달하면 해당 인스턴스가 격리됩니다.
- interval: 상태 체크 주기입니다. 이 주기마다 서비스 인스턴스의 상태를 검사합니다.
- baseEjectionTime: 격리된 인스턴스가 다시 사용할 수 있게 되기까지 대기하는 시간입니다.
- maxEjectionPercent: 서비스의 인스턴스 중 격리할 수 있는 최대 비율입니다.
다음은 예시입니다:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: destination-rule-for-my-service
spec:
host: my-service.my-namespace.svc.cluster.local
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 2 # 5xx 오류가 2회 발생하면 서비스 격리
interval: 5s # 5초마다 상태 체크
baseEjectionTime: 30s # 30초 동안 격리
maxEjectionPercent: 100 # 100%까지 인스턴스 제거 가능
이 설정이 적용되면, 연속적인 5xx 에러가 두 번 발생할 경우 해당 인스턴스는 격리되고 일정 시간 동안 트래픽을 받지 않게 됩니다. 이때 살아 있는 다른 서비스로 트래픽이 자동으로 라우팅됩니다. 인스턴스가 격리된 후, baseEjectionTime
에 설정된 30초가 지나면, 다시 상태를 확인하여 정상으로 돌아온 경우 트래픽을 다시 수용할 수 있습니다.
전체 설정 예시:
아래는 트래픽을 분산시키면서 장애가 발생한 경우 자동으로 대응하는 설정입니다.
- VirtualService: 두 서비스로 트래픽을 분배
- DestinationRule: Outlier Detection을 통한 장애 인스턴스 격리
# VirtualService
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-virtualservice
spec:
hosts:
- my-service.my-namespace.svc.cluster.local
http:
- route:
- destination:
host: service-a.my-namespace.svc.cluster.local
weight: 70
- destination:
host: service-b.my-namespace.svc.cluster.local
weight: 30
---
# DestinationRule for service-a
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: destination-rule-service-a
spec:
host: service-a.my-namespace.svc.cluster.local
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 2
interval: 5s
baseEjectionTime: 30s
maxEjectionPercent: 100
---
# DestinationRule for service-b
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: destination-rule-service-b
spec:
host: service-b.my-namespace.svc.cluster.local
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 2
interval: 5s
baseEjectionTime: 30s
maxEjectionPercent: 100
- Weight 방식만 사용하면 서비스가 죽었을 때 트래픽을 자동으로 다른 서비스로 라우팅하지 않으므로 Outlier Detection과 같은 추가적인 설정이 필요합니다.
- Outlier Detection을 사용하면 비정상적인 서비스는 자동으로 격리되고, 다른 서비스로 트래픽이 전달됩니다.
'Kubernetes > Istio' 카테고리의 다른 글
Cert Manager with SSL Domain with AWS Route53 (0) | 2024.08.15 |
---|---|
Istio Kubernetes 구축 및 Nginx 테스트 (0) | 2024.08.13 |