Introduction
Istio는 다양한 resiliency features, 즉 Timeout, Retry, Circuit Breaker, Rate Limiting을 제공하지만, 이러한 다양성이 오히려 각기 어떤 문제에 대한 해결책인지 구분이 잘 안되는 혼선을 일으키고는 한다. 이는 마치 개발 시 요구사항이 불분명하거나 동일 요구사항에 대한 각기 다른 솔루션이 제시된 상황과 비슷하다. 또한, 잘못된 설정은 시스템 안정성을 직접적으로 위협하는 와중에 설정 자체가 까다롭기까지 하다. 따라서 명확한 이해가 더욱 요구된다.
본 문서는 이에 대한 대응으로, 이해와 함께 구체적 실행 방법을 요약한다.
참조 문서는 Istio, Envoy, Kubernetes 공식 문서 및 AI(주로 Grok, Gemini. Claude는 그림 정도…)이며, AI의 환각 이슈 대응도 함께 하였다(AI 간 cross checking, 타당성, 일관성 중심 검토). 용어는 되도록이면 canonical term을 쓰려고 ‘노력’했다(별도 권위있는 문서는 찾아볼 여유가 없었단게 변명 아닌 변명. 그나마 아래 Google SRE book을 일부 참조했지만 문서 작성 막바지에야 알게 되어서리…).
이외에 실험 기반이 아닌 개인 경험과 및 참조 문서에 의존한 내용임도 밝힌다.
장애 시나리오 예시
용이한 설명을 위해 먼저 장애 시나리오를 상정하였다. 서비스 A와 B(각각 10개 pod, pod 당 10 RPS 처리 가능)가 있을 때, A → B 호출 시 트래픽이 100 RPS에서 200 RPS로 급증(spike)한다고 가정한다. 이때 아래와 같은 순서로 장애가 발생 가능하다.
1.
높은 지연(High Latency): 과부하로 인한 B의 일부 pod 응답 시간이 5초로 증가, A의 대기 시간 증가.
2.
일시적 장애(Transient Failure): B의 pod에서 request queue 포화, 네트워크 혼잡 등으로 일시 또는 간헐적 5XX 오류 발생, A의 요청 실패.
3.
반복적 장애(Persistent/Repeated Failure): B의 특정 pods에서 5xx 오류 지속, B의 가용성 저하.
4.
연쇄적 장애(Cascading Failure)
•
서비스 내(Intra-service) CF: routing 대상 LB pool에서 장애 pods 제외 → healthy pods로 트래픽 집중 → healthy pods 장애
•
서비스 간(Inter-service) CF: B의 장애 및 높은 지연으로 인한 A의 자원 고갈 → A도 느려지거나 장애.
이외에, 서버 자원 고갈(Server Resource Exhaustion; B의 과부하)와 클라이언트 자원 고갈(Client Resource Exhaustion, A의 자원 고갈)은 상기 장애 전반의 기저 원인이 된다.
참고
•
여기서 서버와 클라이언트란, Istio 환경 내 모든 서비스에 대한 피호출자(서버), 호출자(클라이언트)를 의미한다. 마이크로서비스 환경에서 서비스 각각은 서버와 클라이언트 역할 모두를 하기 마련이다.
•
당연스럽게도 각각의 장애는 본 시나리오에만 국한된 것이 아니다. 즉, 각각의 장애는 본 시나리오나 타 장애와 관계 없이 개별적으로 나타날 수 있다. 특히 높은 지연이나 일시적 장애가 그러하다.
Overview: 장애 단계 별 각 feature의 역할
상기 장애 발생 시나리오의 각 장애 단계에 따른 Timeout, Retry, Circuit Breaker, Rate Limiting의 역할에 대한 overview이다. 이들은 각기 다른 문제를 주로 담당함과 동시에 서로의 보완책이 된다. 상세 내용은 이후 섹션에서 이어진다.
Timeout | Retry | Circuit Breaker | Rate Limiting | |
높은 지연 | - | - | - | |
일시적 장애 | - | - | - | |
반복적 장애 | - | - | ||
연쇄적 장애 | ||||
서버 자원 고갈(과부하) | - | |||
클라이언트 자원 고갈 |
Istio Resiliency features 동작 위치
각 Istio Resiliency feature 세부 설명에 앞서 feature 별 동작 위치를 먼저 논한다. 동작 위치 식별은 매우 중요한데, 위치를 식별해야 정확한 설정이 가능하기 때문이다.
아래 그림은 Rate Limiting는 server-side istio-proxy에서, 이외 나머지는 Service B의 VirtualService, DestinationRule임에도 client-side istio-proxy에서 동작함을 보여준다. Timeout, Retry는 VirtualService, Circuit Breaker는 DestinationRule, Rate Limiting은 EnvoyFilter를 통해 설정한다. 이는 왜 Timeout, Circuit Breaker가 클라이언트 자원 고갈 문제를, Rate Limiting이 서버 자원 고갈 문제를 해결하는지에 대한 이유이기도 하다.
Istio resiliency feature의 동작 위치. Rate limiter는 server-side에서, 나머지는 VirtualService, DestinationRule의 client-side에서 동작한다.
또한 위 그림에 보이듯 istio-proxy간의 상태 공유가 없기에, 각종 resiliency 관리를 위한 각종 상태값(e.g. CB의 오류 횟수, rate limiter의 요청 횟수)은 각각의 istio-proxy 별로 이루어진다는 점도 설정 시 고려할 필요가 있다.