이전 글을 참고하면 좋습니다. [*] - Istio 트래픽 관리
Session Affinity
카나리 버전을 일정 비율로 배포하였고, 어떤 유저가 방문하여 카나리 버전을 사용하게 되었다고 가정하자. 그 유저가 계속 카나리 버전을 사용하도록, 즉 같은 유저의 요청에 대해서는 같은 응답을 하도록 할 수 있을까?
https://istio.io/latest/docs/reference/config/networking/destination-rule/
Destination Rule 문서에는 sticky session을 설정하는 예제가 있다. 유저의 쿠키를 해시 키로 사용하여 해시 기반 로드 밸런서를 사용한다. (trafficPolicy 필드 참고)
들어오는 요청에 대해서, 요청이 가진 특정 값을 해싱하고, 다음 요청때 해시값을 이용해 같은 대상으로 갈 수 있도록 하는 기능이다.
kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: a-service-vs
namespace: default
spec:
hosts:
- a-service
http:
- route:
- destination:
host: a-service
subset: safe-group
weight: 90
- destination:
host: a-service
subset: risky-group
weight: 10
--
kind: DestinationRule
apiVersion: networking.istio.io/v1alpha3
metadata:
name: a-service-dr
namespace: default
spec:
host: a-service
trafficPolicy:
loadBalancer:
consistentHash:
useSourceIp: true # source IP 기반으로 해싱한다.
subsets:
- labels:
version: safe
name: safe-group
- labels:
version: risky
name: risky-group
웹 프론트엔드 단에서 보내는 헤더에 대해 알고 있을 경우, 이것을 기준으로 해시를 적용할 수도 있고, 프론트엔드가 유저별로 쿠키를 만들 경우 쿠키로 해싱할 수도 있으며, ip를 사용해 해싱할 수도 있다.
하지만 테스트를 해봤을 때, 첫 번째로 만난 subset이 아닌 다른 subset으로 요청이 전달되며 제대로 동작하지 않는 것을 확인하였다. 이는 weight subset과 session affinity가 동시에 동작할 수 없기 때문이다. (envoy가 지원하지 않는다.)
이는 아마도 가중치 규칙이 먼저 적용이된 후에 Loadbalancer가 개입하게 되므로, 이미 가중치 규칙에 따라 특정 Loadbalancer로 이동해버렸기 때문에 해싱이 의미가 없어짐으로 추측할 수 있다.
https://github.com/istio/istio/issues/9764
논이슈므로 깃헙 이슈에서 확인 가능하다.
ConsistentHashing
그렇다고 consistentHashing 자체가 의미가 없는 것은 아니다. 가중치를 사용하지 않는 해싱은 문제가 없다.
가중치를 사용하지 않을 때는 모든 pod을 타게팅할 수 있는 레이블로 destination을 하나만 정의하면 된다. (가중치 값을 기재하지 말자.)
kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
name: a-service-vs
namespace: default
spec:
hosts:
- a-service
http:
- route:
- destination:
host: a-service
subset: all-target-a-service-pods
---
kind: DestinationRule
apiVersion: networking.istio.io/v1alpha3
metadata:
name: a-service-dr
namespace: default
spec:
host: a-service
trafficPolicy:
loadBalancer:
consistentHash:
httpHeaderName: "x-myval"
subsets:
- labels:
app: a-app
name: all-target-a-service-pods
ip 기반은 테스트가 어려우니 header 기반 해싱으로 바꾸어 테스트 해보자.
$ curl http://localhost:30080/api/a --header "x-myval: 111"
curl 을 통해 해당 header을 지정하여 요청하면, 항상 같은 pod으로 요청이 전달되어 같은 응답을 받을 것이다.
만약 header 기반 consistentHash를 이용하고 여러개의 microservice를 통과하는 MSA 구조라면, 코드에서 헤더 확산을 해주어야 할 것이다.
이런 consistentHash는 사용자가 일관된 pod으로 요청을 보내야하는 상황에 유용하다. 예를들면, pod이 많은 작업을 하는 경우, (계산량이 많은 경우) 성능 향상을 위해서 클라이언트 별로 어떤 결과값을 캐싱할 수 있을 것이다. 다음 번에 같은 클라이언트가 같은 요청을 보낼시 캐싱된 결과를 보내줄 수 있게 된다.
물론, 이 기능을 pod과 클라이언트의 커뮤니케이션을 위한 세션과 같이 사용하면 안된다. MSA 구조에서 무조건 특정 pod으로 전달되는 구조는 지양된다. pod은 많은 이유로 삭제될 수도 있고, 다른 노드에서 재실행될 수도 있다. pod은 어떤 클라이언트를 위해 세션을 유지할 수 없다. 성능 향상 용도로만 사용하도록 하자.
'DevOps' 카테고리의 다른 글
[Istio] Dark Release (0) | 2024.01.30 |
---|---|
[Istio] Gateway & Edge Proxy (0) | 2024.01.30 |
[Istio] 트래픽 관리 (+카나리 배포) (0) | 2024.01.23 |
[Istio] Telemetry (kiali, jaeger) (0) | 2024.01.14 |
[Istio] Overview (0) | 2023.12.11 |