Späť na blog

Envoy outlier detection brownouty: keď mesh vyhodí zdravé pody

|
| kubernetes, service-mesh, istio, envoy, reliability

Aplikácia vyzerá zdravá. Pody sú Ready. CPU je v norme. A predsa klienti vidia bursty 503 a chyby nekorelujú s app logmi.

Ak bežíte Istio (alebo iný Envoy mesh), častý vinník je outlier detection: Envoy rozhodne, že endpoint je “zlý” a dočasne ho vyradí z load balancingu. Pri malom počte podov, agresívnych retry politikách alebo zone obmedzeniach sa táto “self-healing” funkcia zmení na generátor brownoutov.

Testované na: Kubernetes 1.29–1.31, Istio 1.21–1.23, Envoy 1.29–1.31 (sidecar), HTTP/2 + gRPC workloady.

Incident (anonymizovaný)

Payments API bežalo so 6 podmi za Istio Gateway. Ako súčasť “hardeningu” sa nasadilo nové DestinationRule:

  • outlier detection vyhadzuje endpoint po jednom 5xx
  • retries zapnuté (3 pokusy)
  • malé connection pool limity

Počas bežného deployu mala časť podov 1–2 sekundové cold-start stall (JIT + warmup cache). Envoy to interpretoval ako “unhealthy”, vyhodil endpointy, a retries zosilnili load na zvyšné pody. Systém osciloval:

  • eject → menej endpointov → viac loadu → viac 5xx → viac eject

Blast radius: 30–50% trafficu ~12 minút, kým sme spravili rollback.

Constraint: nemohli sme vypnúť mesh (mTLS + routing pravidlá boli povinné).

Timeline

  • T-0: 503 špička na gateway; app dashboardy sú väčšinou zelené.
  • T+5m: Istio access logy ukazujú nárast response flags UF a UH.
  • T+12m: Envoy stats ukazujú outlier_detection.ejections_active > 0 pre upstream cluster.
  • T+20m: istioctl proxy-config cluster odhalí agresívne outlier settings na service clustri.
  • T+30m: rýchla mitigácia: uvoľniť outlier thresholdy + znížiť retries.
  • T+45m: ejection oscilácia skončí; 503 sa vrátia na baseline.

Mechanizmus: ako outlier detection vytvorí brownout

Outlier detection je per-proxy a lokálny

Každý Envoy (sidecar/gateway) drží lokálne error štatistiky pre upstream endpointy. Ak endpoint prekročí threshold (napr. consecutive 5xx), Envoy ho ejectne na baseEjectionTime.

Pri veľa klientoch (veľa sidecarov) viete dostať synchronizované ejections, aj keď je problém iba transient.

Malý pool a locality policy to zosilnia

Ak máte:

  • málo podov
  • prísnu zone affinity / locality load balancing
  • “prefer local zone” politiku

tak vyhodenie 1–2 podov vie preťažiť zvyšok. Retries potom situáciu zhoršia.

Retries sú load multiplikátor

  • 1 request + 3 retries = až 4 upstream pokusy
  • ak je upstream už na hrane, retries zvýšia chyby a spustia ďalšie ejections

Výsledkom je oscilácia.

Runbook: ako dokázať, že root cause je outlier detection

Čo skontrolovať ako prvé

  1. Envoy response flags v access logoch

Na gateway alebo sidecar logoch hľadajte x-envoy-response-flags (alebo ekvivalent v log formáte).

Typické flags v týchto incidentoch:

  • UF (upstream connection failure)
  • UH (no healthy upstream)
  • UO (upstream overflow)
  • URX (upstream retry limit exceeded)
  • UC (upstream connection termination)

Príklad:

... "response_code":503, "response_flags":"UH", "upstream_cluster":"outbound|8080||payments.default.svc.cluster.local" ...
  1. Potvrďte ejections cez Envoy admin stats

Vyberte gateway (najľahšie) a vytiahnite stats:

kubectl -n istio-system exec deploy/istio-ingressgateway -c istio-proxy -- \
  curl -s localhost:15000/stats | grep -E 'outlier|eject|healthy|panic' | head

Ako potvrdiť hypotézu

A. Pozrite xDS config (Istio pohľad na Envoy config)

istioctl proxy-config cluster -n default deploy/payments-api --fqdn payments.default.svc.cluster.local

Hľadajte:

  • outlier detection settings
  • connection pool settings
  • circuit breakers / max requests
  • locality / LB policy

B. Nájdite, odkiaľ to prišlo (DestinationRule / VirtualService)

kubectl -n default get destinationrule -o yaml | grep -n "payments.default.svc.cluster.local" || true

Otvoríte konkrétne DestinationRule a pozriete trafficPolicy.outlierDetection.

C. Korelujte periodicitu s baseEjectionTime

Ak máte bursty približne každých 30s a baseEjectionTime je 30s, je to silný signál ejection loopu.

Bezpečné mitigácie

  1. Uvoľniť outlier detection pre malé pooly
  • zvýšiť consecutive5xx
  • zvýšiť interval
  • znížiť baseEjectionTime
  • dať maxEjectionPercent pod 50–60%
  1. Znížiť alebo dočasne vypnúť retries
  • retries majú byť budget, nie default
  1. Scale endpointov pred ejection
  • pri 2–3 podoch je outlier detection extrémne rizikový
  1. Opraviť readiness/startup
  • nenechať routovať traffic na cold-start pody
  • graceful shutdown počas rolloutov

Rizikové mitigácie

  1. Vypnúť outlier detection všade
  • môžete zakryť reálny unhealthy endpoint problém
  1. Zvýšiť retries ako “fix”
  • často len presunie problém do ďalšej špičky
  1. Príliš malé connection pooly
  • môžu spúšťať UO/overflow pri burstoch

Čo sme zmenili (konkrétne diffs)

DestinationRule bol extrémne agresívny.

Predtým:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: payments-api
spec:
  host: payments.default.svc.cluster.local
  trafficPolicy:
    outlierDetection:
      consecutive5xx: 1
      interval: 1s
      baseEjectionTime: 5m
      maxEjectionPercent: 100

Potom (bezpečnejšie defaulty pre 6–10 podov):

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: payments-api
spec:
  host: payments.default.svc.cluster.local
  trafficPolicy:
    outlierDetection:
      consecutive5xx: 5
      interval: 10s
      baseEjectionTime: 30s
      maxEjectionPercent: 50

A znížili sme retries vo VirtualService počas rolloutov:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: payments-api
spec:
  hosts:
  - payments.default.svc.cluster.local
  http:
  - retries:
      attempts: 1
      perTryTimeout: 200ms
      retryOn: "5xx,connect-failure,refused-stream"

Ako verifikovať (merateľné)

  1. Ejections prestanú oscilovať
  • ejections_active je väčšinu času 0 (okrem reálnych výpadkov).
  1. Zmena 503 flags
  • UH zmizne alebo je extrémne zriedkavé.
  • Ak chyby ostanú, korelujú so saturáciou appky alebo reálnym upstream issue.
  1. Retry budget drží
  • sledujte URX a upstream attempt rate vs request rate.
  1. Rollout nevyvolá brownout
  • canary, pozorovať ejections a 503.

Prevencia / guardrails

Reliability kontrakty

  • Žiadny outlier detection pre služby s < N endpointami (napr. 5–10 podľa trafficu).
  • Retry budget kontrakt: retries musia byť < X% upstream attemptov.
  • Ejection budget: alert, ak ejections prekročia malé číslo/min.

Alerty, ktoré dávajú zmysel

  • ejections_active > 0 na kritických clustroch > 5 min
  • špička UH alebo UO flags na gateway
  • upstream attempt rate rastie rýchlejšie než request rate (retry amplifikácia)

Súvisiace čítanie

Súvisiace články

Citujte tento článok

Ak na článok odkazujete, pridajte pôvodnú URL a uveďte autora.

Michal Drozd. "Envoy outlier detection brownouty: keď mesh vyhodí zdravé pody". https://www.michal-drozd.com/sk/blog/envoy-outlier-detection-brownouty/ (Publikované 6. novembra 2025).