LabHub
배우기 러닝패스 코스

Istio 심화 — 왜 그렇게 흐르는가 · DestinationRule 트래픽 정책이 클러스터가 되기까지 · 이론

서킷 브레이커를 걸었는데 효과가 없는 이유

LabHub 에서 이어서 보기

한 줄 요약

DestinationRule 의 trafficPolicy 는 Envoy 클러스터의 필드로 옮겨진다. loadBalancerlb_policy, connectionPoolcircuit_breakers.thresholds, outlierDetectionoutlier_detection. 옮겨진 숫자는 그대로 동작한다 — 한도를 넘친 요청은 업스트림에 가지도 않고 503 이 되고, 연달아 실패한 엔드포인트는 실패를 겪은 뒤에 빠진다.

개념 지도: 뒤에 · 기대가 틀린 것 · 덩어리째 · 부하 시험에서 서킷 브레이커가 안 열린다.

왜 이게 필요했나

"서킷 브레이커를 걸었는데 효과가 없다", "이상치 감지를 켰는데 에러가 계속 난다" 는 질문이 끝없이 나온다. 대부분은 설정이 틀린 게 아니라 기대가 틀린 것이다. 서킷 브레이커의 한도는 서비스 전체가 아니라 호출하는 사이드카 하나의 클러스터마다 따로 센다. 이상치 감지는 예방이 아니라 사후 조치라서 정해 둔 횟수만큼은 사용자가 먼저 맞는다. 그리고 서브셋에 정책을 따로 주면 부모 정책이 필드 하나하나가 아니라 덩어리째 덮어쓰여, 적지 않은 한도가 조용히 사라진다.

이것들은 YAML 을 아무리 들여다봐도 보이지 않는다. Envoy 클러스터로 번역된 모습을 보고, 실제로 넘치게 하고 실패시켜 봐야 보인다.

어떻게 동작하나

| DestinationRule | Envoy 클러스터 |
| --- | --- |
| loadBalancer.simple | lb_policy |
| connectionPool.tcp.maxConnections | circuit_breakers.thresholds[0].max_connections |
| connectionPool.http.http1MaxPendingRequests | …max_pending_requests |
| connectionPool.http.http2MaxRequests | …max_requests |
| outlierDetection.consecutive5xxErrors | outlier_detection.consecutive_5xx |
| outlierDetection.baseEjectionTime · maxEjectionPercent | base_ejection_time · max_ejection_percent |

적지 않은 한도는 Envoy 의 기본값 1024 가 아니라 Istio 가 넣는 4294967295(사실상 무제한)가 된다. 서브셋은 클러스터를 따로 가지므로 정책도 따로 적용되는데, 합치는 규칙은 공식 문서 한 줄 — 서브셋의 정책이 해당 설정을 덮어쓴다 — 이 전부다. 덮어쓰는 단위는 connectionPool·loadBalancer·outlierDetection·tls 같은 덩어리다.

서킷 브레이커의 셈은 단순하다. 연결이 max_connections 개 묶여 있으면 새 요청은 대기열에 서고, 대기열이 max_pending_requests 를 넘으면 Envoy 가 바로 503 과 x-envoy-overloaded: true 를 돌려준다. 이상치 감지는 엔드포인트마다 연속 실패를 세다가 consecutive_5xx 에 닿으면 base_ejection_time 동안 부하 분산에서 뺀다. 다만 max_ejection_percent 가 한 번에 뺄 수 있는 비율을 막는다 — 전부 빼면 보낼 곳이 없어지기 때문이다.

현장에서 만나는 모습

부하 시험에서 서킷 브레이커가 안 열린다. 한도는 호출하는 쪽 사이드카마다 센다. 호출 파드가 열 개면 서비스가 실제로 받는 동시 연결은 한도의 열 배다. 반대로 호출 파드가 하나뿐인 배치 작업은 작은 한도에 바로 걸린다.

카나리 서브셋만 가끔 503 이 쏟아진다. 서브셋에 tcp.maxConnections 하나를 적었더니 부모의 http1MaxPendingRequests 가 사라진 경우이거나, 반대로 서브셋에 작은 http 한도를 적고 잊은 경우다. proxy-config cluster 로 서브셋 클러스터의 한도를 부모와 나란히 놓고 본다.

이상치 감지를 켰는데 대시보드의 5xx 가 0 이 안 된다. 빠지기 전의 실패와, 빠진 시간이 끝나 돌아온 뒤의 실패가 계속 보인다. 이상치 감지는 에러를 없애는 장치가 아니라 오래 끄는 것을 막는 장치다. 재시도와 함께 써야 사용자가 보는 에러가 준다.

공식 문서: [DestinationRule](https://istio.io/latest/docs/reference/config/networking/destination-rule/) · [Circuit breaking](https://istio.io/latest/docs/tasks/traffic-management/circuit-breaking/) · [Envoy cluster](https://www.envoyproxy.io/docs/envoy/v1.38.3/api-v3/config/cluster/v3/cluster.proto)

다음 실습에서 할 것

트래픽 정책이 든 DestinationRule 을 쓰고, 필드 대응표를 만들어 그대로 클러스터를 세운 뒤 config_dump 로 되읽는다. 늘 실패하는 엔드포인트를 섞어 이상치 감지가 몇 번 맞은 뒤 빼는지 세고, 서브셋 정책이 부모를 덩어리째 덮어쓰는 것을 /clusters 로 확인하고, 느린 업스트림에 동시에 요청을 몰아 서킷 브레이커의 503 을 센다.