오랜만에 글을 작성한다.
게시물로 정리하고 공유하고 싶은 내용은 많은데 시간이 부족하다는 핑계로.. 글을 올리는 텀이 점점 길어진다.
이대로는 안되겠다 싶어서 최근 진행한 Istio 구조와 localityLb 설정에 대해서만 공유하고자 한다!!
잘못된 내용이 있을 수 있습니다. 잘못된 내용을 지적해주시면 확인하고 반영하도록 하겠습니다.
Istio LocalityLbSetting 이란?
Istio는 MSA 구조의 아키텍처 서비스를 구현할 때 일반적으로 사용되는 오픈소스이다. 그리고 MSA 구조 특성상 여러 서비스가 분리되어 있어 상시로 서비스를 호출하게 된다. 이때 CrossAZ 데이터 전송 비용이 발생한다.
Istio LocalityLb는 Istio를 사용하는 환경에서 동일 AZ 서비스 엔드포인트 호출을 우선시하여, CrossAZ 데이터 전송 비용과 네트워크 홉을 줄일 수 있는 설정이다.
Istio LocalityLb 기대 효과
ASIS 데이터 호출 흐름
기존에는 아래와 같이 서비스를 호출하게 되면 ROUNDROBIN 방식으로 엔드포인트 서비스를 호출하며 CrossAZ 비용이 발생한다.
- Destination에서 TrafficPolicy 설정을 다르게 줬다면 해당 알고리즘에 의해 라우팅을 하게 된다.
그리고 이때 A -> B -> C Zone에 있는 엔드포인트로 호출하게 되고, 이때 CrossAZ 데이터 전송 비용이 발생하게 된다.
- 외부 사용자가 A 서비스를 호출하고, A 서비스는 MSA 구조로 되어 있어 B, C 서비스를 차례로 호출한다.
- 데이터 호출 흐름
- 외부 사용자가 전송한 요청을 A Zone에 있는 A 서비스가 받고, B 서비스를 호출한다.
- istio localityLB Setting이 되어 있지 않기 때문에 다른 Zone의 B 서비스에게 요청할 수 있다.
- CrossAZ 데이터 전송 비용 발생
- B Zone에 있는 B 서비스가 호출을 당하고, C 서비스를 호출한다.
- CrossAZ 데이터 전송 비용 발생
- C Zone에 있는 C 서비스가 호출을 당한다.
- 외부 사용자가 전송한 요청을 A Zone에 있는 A 서비스가 받고, B 서비스를 호출한다.
물론 트래픽이 적다면 큰 비용이 아니겠지만 트래픽이 많은 곳에서는 무시하지 못할 비용 수준이고, 비용적인 부분 외 CrossAZ 호출을 하게되면 네트워크 홉이 늘어나는 문제도 발생한다.
그렇다면 LocalityLb를 설정하고 난 다음에는 어떻게 변할까?
TOBE 데이터 호출 흐름
TOBE를 보면 우선적으로 동일AZ 엔드포인트를 호출하는 흐름이다.
실제로도 테스트 해보면 아래와 같은 결과를 얻을 수 있다. 이것이 LocalityLb를 적용했을 때의 장점을 극명하게 보여주는 그림이다.
검은색, 붉은색, 파란색으로 3가지 시나리오로 구분하였을 때 각 시나리오별 흐름은 아래와 같다.
- 시나리오 1) A, B, C 서비스가 모두 동일한 Zone에 위치에 있다. (위 그림에서는 A Zone, 검은색 선)
- 데이터 호출 흐름
- 외부 사용자가 전송한 요청을 A Zone에 있는 A 서비스가 받고, B 서비스를 호출한다.
- istio localityLB Setting이 되어 있기 때문에 동일 Zone의 B 서비스를 우선 호출한다.
- CrossAZ 데이터 전송 비용 발생하지 않음
- A Zone에 있는 B 서비스가 호출을 당하고, C 서비스를 호출한다.
- CrossAZ 데이터 전송 비용 발생하지 않음
- A Zone에 있는 C 서비스가 호출을 당한다.
- 외부 사용자가 전송한 요청을 A Zone에 있는 A 서비스가 받고, B 서비스를 호출한다.
- 데이터 호출 흐름
- 시나리오 2)
- A, B 서비스만 동일한 Zone에 위치해있다. (위 그림에서는 C Zone, 붉은색 선)
- 데이터 호출 흐름
- 외부 사용자가 전송한 요청을 C Zone에 있는 A 서비스가 받고, B 서비스를 호출한다.
- istio localityLB Setting이 되어 있지 않기 때문에 동일 Zone의 B 서비스를 우선 호출한다.
- CrossAZ 데이터 전송 비용 발생하지 않음
- C Zone에 있는 B 서비스가 호출을 당하고, C 서비스를 호출한다.
- 하지만 이때 C Zone에는 C 서비스가 없고, A 또는 B Zone에 위치한 C 서비스를 호출한다.
- 다운타임 없으며, 즉시 다른 Zone에 서비스를 호출한다.
- 이게 가능한 이유는 istio envoy에서 각 SVC별로 각 Zone에 위치한 Pod의 가중치 정보를 가지고 있다.
- CrossAZ 데이터 전송 비용 발생하지 않음
- B Zone에 있는 C 서비스가 호출을 당한다.
- 외부 사용자가 전송한 요청을 C Zone에 있는 A 서비스가 받고, B 서비스를 호출한다.
- 시나리오 3)
- A, C 서비스만 동일한 Zone에 위치해있다. (위 그림에서는 B Zone, 파란색 선)
- 데이터 호출 흐름
- 외부 사용자가 전송한 요청을 B Zone에 있는 A 서비스가 받고, B 서비스를 호출한다.
- 하지만 이때 B Zone에는 B 서비스가 없고, A 또는 B Zone에 위치한 B 서비스를 호출한다.
- CrossAZ 데이터 전송 비용 발생 함
- A Zone에 있는 B 서비스가 호출을 당하고, C 서비스를 호출한다.
- A Zone에는 B, C 서비스가 모두 존재한다.
- CrossAZ 데이터 전송 비용 발생하지 않음
- A Zone에 있는 C 서비스가 호출을 당한다.
- 외부 사용자가 전송한 요청을 B Zone에 있는 A 서비스가 받고, B 서비스를 호출한다.
Istio LocalityLb 적용 방법
적용하는 방법은 매우 간단하다. localityLbSetting만 설정하면 의도한것과 같이 동작하지 않는다. 그래서 outlierDetection 또는 distribute을 같이 설정해줘야 한다. 적용하는 방법은 크게 2가지가 있다.
- 만약 localityLbSetting만 설정했을 때는 동일 AZ에 엔드포인트가 없을 경우 방법이 없다. 그래서 이 경우를 대비한 fail-over 방법을 적용해줘야 비로서 localityLb가 제대로 동작한다.
필자는 2안의 방법으로 진행하였다. 여러 커뮤니티와 사례를 보면 2의 방법이 일반적으로 적용하는 방법이고 distribute은 Region Fail-over때 사용한다고 판단했기 때문이다.
1안) outlierDetection + localityLbSetting 설정
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: test
namespace: test-dev
spec:
host: "*.cluster.local"
loadBalancer:
localityLbSetting:
enabled: true
distribute:
- from: ap-northeast-2/ap-northeast-2a/*
to:
"ap-northeast-2/ap-northeast-2a/*": 100
- from: ap-northeast-2/ap-northeast-2b/*
to:
"ap-northeast-2/ap-northeast-2b/*": 100
- from: ap-northeast-2/ap-northeast-2c/*
to:
"ap-northeast-2/ap-northeast-2c/*": 100
2안) localityLbSetting + outlierDetection 설정
2안으로 설정하면 outlierDetection에 대해 궁금할 수 있다. 하지만 이는 코드는 있지만 실제로는 적용되지 않는것 같다.
- 아래 설정만 본다면 10초마다 점검을 해서 2,000이상의 500 에러가 발생하면 해당 pod을 30s 동안 엔드포인트에서 제외한다는 옵션이다.
- 하지만, 실제로 적용해보면 동일AZ에 서비스가 없을 경우 즉시, 다른 AZ 서비스로 트래픽이 전환된다.
- 즉, 서비스 다운타임이 발생하지 않는다.
- 실제로 보면 outlierDetection을 빈 값으로 두고 설정하는 방법도 있다.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: test
namespace: test-dev
spec:
host: "*.svc.cluster.local"
trafficPolicy:
loadBalancer:
localityLbSetting:
enabled: true
outlierDetection:
consecutive5xxErrors: 2000
interval: 10s
baseEjectionTime: 30s
Istio LocalityLb 테스트 결과
LocalityLb가 설정되어 있는 경우
목적지 서비스 엔드포인트가 a, b, c AZ에 균등 배포 되어 있는 경우
아래의 내용을 보면 출발지의 kyle-test는 각 az에 균등 배포가 되고 있다. 그리고 목적지의 서비스 엔드포인트를 호출해보면 모두 동일한 AZ에 위치한 서비스에서 응답이 오는것을 확인할 수 있다.
- 목적지의 서비스 엔드포인트는 자체 제작한 이미지로 해당 API의 응답으로는 엔드포인트가 배포된 노드와 Pod 이름을 반환한다.
- 그래서 165번 c Zone에 위치한 blossomops pod에서 응답을 준다.
만약 특정 Zone의 Pod이 죽게되면?
kyle-test-5778cd94ff-29xzk는 165번 노드에 위치하고 해당 노드는 c Zone에 있다.
만약 위와 같은 상태에서 165번 노드(c Zone)에 위치한 Pod이 delete가 된다고 하면 즉시 다른 Zone에 위치한 Pod으로 트래픽이 전달된다.
- 이때 다운타임은 발생하지 않는다.
그리고 Pod이 Delete 되고, 새로 Running 상태가 되면 다시 c Zone(25번 노드)로 트래픽이 전달됨을 알 수 있다.
- 기존에는 165번 노드(c zone)에 배포되어 있었으나, delete 되고 create 되면서 25번 노드(c zone)으로 배포가 되었다.
Istio LocalityLb를 바로 설정하면 좋으나 아래의 2가지 전제조건이 필요하다.
- istio ingressgateways가 각 AZ별로 균등 배포되어 있을 것
- 균등 배포 되어 있지 않다면 특정 AZ에 있는 서비스로 부하가 몰리게 되며, 서비스에 영향을 줄 수 있다.
- Istio sidecar가 주입된 서비스들도 각 AZ별로 균등 배포
- 필수 사항은 아니다. 하지만 서비스 엔드포인트가 특정 AZ에 몰려있다면 Istio LocalityLb의 효과가 반감될 수 있다.
그리고 이러한 전제조건을 만족하기 위해서는 Deployment에서 topologySpreadConstraints를 적용하면 된다.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app.kubernetes.io/name: test
실제로 적용해보면 크게 어렵진 앟으나, 자사 서비스가 균등 배포 되어 있는가? 다중 AZ Subnet을 사용하고 있는가?에 따라서 적용 가능 유/무가 달라질 수 있다.
Istio Docs와 커뮤니티를 잘 참고해서 적용하면 AWS 비용이 줄어들기 때문에 적용해보면 좋을것 같다.
그럼 이만 끝!!
'기술 이모저모 > [Ops] Devops' 카테고리의 다른 글
[AWS][istio] istio-operator를 통한 istio 배포 (2) | 2023.11.26 |
---|---|
[AWS][Istio] Istio proxy_config 엔드포인트 Priority 확인 방법 (0) | 2023.11.05 |
[ArgoCD] Application 생성 방법 = ArgoCD를 이용한 배포 (0) | 2023.05.14 |
[ArgoCD] Github 연동 및 Webhook Event 설정 방법 (0) | 2023.05.13 |
[ArgoCD] CD Tool 도입개요 및 설치방법 (0) | 2023.05.13 |