Skip to content

Split View: Istio 트래픽 관리 엔진 심층 분석

|

Istio 트래픽 관리 엔진 심층 분석

들어가며

Istio의 트래픽 관리는 시험 범위의 40%를 차지할 만큼 핵심적인 영역입니다. 이 글에서는 Istio CRD가 어떻게 Envoy 구성으로 변환되고, Envoy가 실제로 트래픽을 어떻게 처리하는지 내부 메커니즘을 분석합니다.

VirtualService에서 Envoy RouteConfiguration으로

변환 파이프라인

VirtualService (Istio CRD)
Pilot 변환 엔진
Envoy Route Configuration
  ├── VirtualHost (호스트 기반 매칭)
  │   ├── Route (경로/헤더 매칭)
  │   │   ├── RouteAction (라우팅 대상)
  │   │   ├── WeightedCluster (가중치 기반 분할)
  │   │   └── RetryPolicy (리트라이 정책)
  │   └── Route (기본 경로)
  └── VirtualHost (다른 호스트)

매칭 우선순위

VirtualService의 HTTP 매치 규칙은 정의 순서대로 평가됩니다. Envoy의 RouteConfiguration에서도 동일한 순서를 유지합니다:

  1. 가장 구체적인 매치가 먼저 (exact > prefix > regex)
  2. 여러 match 블록이 있으면 첫 번째 매칭이 적용
  3. 매치 조건이 없는 route는 catch-all로 동작

트래픽 분할 (Traffic Shifting)

가중치 기반 트래픽 분할의 내부 구현:

# Istio VirtualService
spec:
  http:
    - route:
        - destination:
            host: reviews
            subset: v1
          weight: 75
        - destination:
            host: reviews
            subset: v2
          weight: 25

이것이 Envoy에서는 WeightedCluster로 변환됩니다:

{
  "route": {
    "weighted_clusters": {
      "clusters": [
        {
          "name": "outbound|9080|v1|reviews.default.svc.cluster.local",
          "weight": 75
        },
        {
          "name": "outbound|9080|v2|reviews.default.svc.cluster.local",
          "weight": 25
        }
      ],
      "total_weight": 100
    }
  }
}

Envoy는 각 요청마다 난수를 생성하고, 가중치 범위에 따라 클러스터를 선택합니다. 이는 확률적 분할이므로, 정확히 75:25가 아닌 근사치로 동작합니다.

DestinationRule에서 Envoy Cluster Configuration으로

Cluster 구성 변환

DestinationRule은 Envoy의 Cluster 구성으로 변환됩니다:

DestinationRule
  ├── host → Cluster name prefix
  ├── subsets → 개별 Cluster 생성
  │   ├── subset v1 → outbound|9080|v1|reviews.default.svc.cluster.local
  │   └── subset v2 → outbound|9080|v2|reviews.default.svc.cluster.local
  └── trafficPolicy → Cluster-level 설정
      ├── connectionPool → circuit_breakers
      ├── outlierDetection → outlier_detection
      └── loadBalancer → lb_policy

Cluster 이름 규칙

Envoy Cluster의 이름은 다음 형식을 따릅니다:

방향|포트|서브셋|FQDN

예시:
outbound|9080|v1|reviews.default.svc.cluster.local
inbound|8080||productpage.default.svc.cluster.local

로드밸런싱 알고리즘

Round Robin (기본값)

요청 1Endpoint A
요청 2Endpoint B
요청 3Endpoint C
요청 4Endpoint A  (순환)

Envoy 구현: 각 엔드포인트에 순서대로 요청을 분배합니다. 가중치가 있으면 Weighted Round Robin으로 동작합니다.

Least Connections

Endpoint A: 활성 연결 3Endpoint B: 활성 연결 1개  ← 다음 요청 여기로
Endpoint C: 활성 연결 5

Envoy 구현: O(1) 연산으로 가장 적은 활성 요청을 가진 엔드포인트를 선택합니다.

Random

각 요청마다 무작위로 엔드포인트 선택
대규모에서는 통계적으로 균등 분배

Consistent Hash

세션 어피니티가 필요한 경우 사용합니다:

spec:
  trafficPolicy:
    loadBalancer:
      consistentHashLB:
        httpHeaderName: x-user-id

Envoy 구현: Ketama 해시 알고리즘 기반. 해시 링에 엔드포인트를 배치하고, 요청 키를 해싱하여 가장 가까운 엔드포인트를 선택합니다.

해시 링:
   0 ─── EP_A ─── EP_B ─── EP_C ─── MAX
         │              │
    x-user-id:alice  x-user-id:bob
    (항상 EP_A)      (항상 EP_B)

장점:

  • 엔드포인트 추가/제거 시 최소한의 재매핑
  • 동일 키는 항상 동일 엔드포인트로 (스티키 세션)

서킷 브레이커 구현

DestinationRule outlierDetection에서 Envoy 변환

# Istio DestinationRule
spec:
  trafficPolicy:
    outlierDetection:
      consecutive5xxErrors: 5
      interval: 10s
      baseEjectionTime: 30s
      maxEjectionPercent: 50

Envoy에서의 동작:

{
  "outlier_detection": {
    "consecutive_5xx": 5,
    "interval": "10s",
    "base_ejection_time": "30s",
    "max_ejection_percent": 50,
    "enforcing_consecutive_5xx": 100
  }
}

서킷 브레이커 상태 머신

[Closed] ──── 연속 5xx >= 5 ────→ [Open/Ejected]
   ▲                                    │
   │                              baseEjectionTime 경과
   │                                    │
   └──────── 성공 요청 ──────── [Half-Open]
                                   (재시도)

상세 동작:

  1. Closed: 정상 상태. 모든 요청이 엔드포인트로 전달
  2. Open (Ejected): 연속 에러 임계값 초과. 해당 엔드포인트가 로드밸런싱 풀에서 제거
  3. Half-Open: baseEjectionTime 후 엔드포인트가 풀에 복귀. 재실패 시 ejection 시간 증가

연결 풀 기반 서킷 브레이커

spec:
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        h2UpgradePolicy: DEFAULT
        http1MaxPendingRequests: 1024
        http2MaxRequests: 1024
        maxRequestsPerConnection: 10
        maxRetries: 3

Envoy 내부 동작:

요청 도착
maxConnections (100) 초과? ──→ 503 (overflow)
No
http1MaxPendingRequests (1024) 초과? ──→ 503 (overflow)
No
http2MaxRequests (1024) 초과? ──→ 503 (overflow)
No
요청 처리 시작
maxRequestsPerConnection (10) 도달? ──→ 연결 종료 후 새 연결

리트라이 구현

VirtualService retries에서 Envoy 변환

spec:
  http:
    - route:
        - destination:
            host: reviews
      retries:
        attempts: 3
        perTryTimeout: 2s
        retryOn: gateway-error,connect-failure,retriable-4xx

Envoy 리트라이 정책:

{
  "retry_policy": {
    "retry_on": "gateway-error,connect-failure,retriable-4xx",
    "num_retries": 3,
    "per_try_timeout": "2s",
    "retry_host_predicate": [
      {
        "name": "envoy.retry_host_predicates.previous_hosts"
      }
    ]
  }
}

리트라이 동작 상세

원본 요청 → Endpoint A (실패, 503)
리트라이 1Endpoint B (실패, 503)  ← previous_hosts로 A 회피
리트라이 2Endpoint C (실패, 503)A, B 회피
리트라이 3Endpoint A (성공, 200)  ← 후보 소진 시 재사용
최종 응답: 200

핵심 포인트:

  • previous_hosts: 이전에 실패한 호스트를 회피하여 다른 엔드포인트에 리트라이
  • perTryTimeout: 각 시도별 타임아웃 (전체 타임아웃과 별개)
  • 리트라이 버짓: Envoy 내부적으로 동시 리트라이 수를 제한

retryOn 조건 상세

조건Envoy 동작
5xx업스트림이 5xx 응답 반환 시
gateway-error502, 503, 504 응답 시
connect-failureTCP 연결 실패 시
retriable-4xx409 (Conflict) 등 특정 4xx
refused-stream업스트림이 REFUSED_STREAM 에러 코드로 스트림 리셋 시
reset응답 없이 연결이 리셋된 경우

폴트 인젝션 구현

지연 주입 (Delay Injection)

spec:
  http:
    - fault:
        delay:
          percentage:
            value: 10
          fixedDelay: 5s
      route:
        - destination:
            host: reviews

Envoy 구현: envoy.filters.http.fault 필터가 HTTP 필터 체인에 삽입됩니다.

요청 도착
Fault Filter: 난수 생성 (0-100)
    ├── 난수 <= 105초 지연 후 다음 필터로 전달
    └── 난수 > 10 → 즉시 다음 필터로 전달
Router Filter → 업스트림으로 전달

중단 주입 (Abort Injection)

spec:
  http:
    - fault:
        abort:
          percentage:
            value: 20
          httpStatus: 503
      route:
        - destination:
            host: reviews

Envoy 구현:

요청 도착
Fault Filter: 난수 생성 (0-100)
    ├── 난수 <= 20 → 즉시 503 응답 반환 (업스트림에 요청 안 함)
    └── 난수 > 20 → 다음 필터로 전달

복합 폴트 인젝션

지연과 중단을 동시에 적용할 수 있습니다:

spec:
  http:
    - fault:
        delay:
          percentage:
            value: 50
          fixedDelay: 3s
        abort:
          percentage:
            value: 10
          httpStatus: 500

평가 순서: 지연이 먼저 적용되고, 그 다음 중단이 평가됩니다.

트래픽 미러링 구현

VirtualService mirror에서 Envoy 변환

spec:
  http:
    - route:
        - destination:
            host: reviews
            subset: v1
      mirror:
        host: reviews
        subset: v2
      mirrorPercentage:
        value: 100

Envoy 구현:

요청 도착
    ├── 원본 요청 → reviews v1 (응답을 클라이언트에 반환)
    └── 미러 요청 → reviews v2 (응답 무시, fire-and-forget)
         └── Host 헤더에 "-shadow" 접미사 추가
             : reviews → reviews-shadow

핵심 특징:

  • 미러 요청의 응답은 완전히 무시됨
  • 미러 요청 실패가 원본 요청에 영향 없음
  • Host 헤더에 "-shadow"가 추가되어 미러 트래픽 식별 가능

ServiceEntry: 메시 확장

외부 서비스 등록

apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: external-api
spec:
  hosts:
    - api.external-service.com
  location: MESH_EXTERNAL
  ports:
    - number: 443
      name: https
      protocol: TLS
  resolution: DNS

이것이 Envoy에서 생성하는 리소스:

ServiceEntry
    ├── Listener: 0.0.0.0:443 (아웃바운드)에 필터 체인 추가
    ├── Cluster: outbound|443||api.external-service.com
    │   ├── type: STRICT_DNS
    │   └── dns_lookup_family: V4_ONLY
    └── Route: api.external-service.com → 해당 Cluster로 라우팅

Resolution 모드별 동작

ResolutionEnvoy Cluster Type동작
NONEORIGINAL_DST원래 요청 주소로 전달
STATICSTATICendpoints 필드의 IP 직접 사용
DNSSTRICT_DNSDNS로 주기적 해석
DNS_ROUND_ROBINLOGICAL_DNSDNS 결과 중 하나를 라운드 로빈

고급 라우팅 패턴

헤더 기반 카나리 배포

spec:
  http:
    - match:
        - headers:
            x-canary:
              exact: 'true'
      route:
        - destination:
            host: reviews
            subset: v2
    - route:
        - destination:
            host: reviews
            subset: v1

URI 기반 라우팅

spec:
  http:
    - match:
        - uri:
            prefix: '/api/v2'
      route:
        - destination:
            host: api-v2
    - match:
        - uri:
            prefix: '/api'
      route:
        - destination:
            host: api-v1

소스 기반 라우팅

spec:
  http:
    - match:
        - sourceLabels:
            app: frontend
            version: v2
      route:
        - destination:
            host: reviews
            subset: v2
    - route:
        - destination:
            host: reviews
            subset: v1

디버깅 도구

istioctl 명령어 모음

# VirtualService 적용 상태 확인
istioctl analyze -n NAMESPACE

# 특정 서비스의 라우팅 구성 확인
istioctl proxy-config routes PODNAME -o json | python3 -m json.tool

# Envoy의 클러스터 통계 확인
istioctl proxy-config clusters PODNAME --fqdn reviews.default.svc.cluster.local

# 서킷 브레이커 상태 확인 (Envoy 관리 포트)
kubectl exec PODNAME -c istio-proxy -- curl -s localhost:15000/clusters | grep outlier

# 리트라이 통계
kubectl exec PODNAME -c istio-proxy -- curl -s localhost:15000/stats | grep retry

일반적인 문제 패턴

  1. 503 UC (Upstream Connection): 업스트림 연결 실패 - connectionPool 설정 확인
  2. 503 UO (Upstream Overflow): 서킷 브레이커 트리거 - maxConnections/maxPendingRequests 확인
  3. 503 NR (No Route): 라우트 매칭 실패 - VirtualService host/match 확인
  4. 503 UH (Upstream Unhealthy): 모든 엔드포인트 ejected - outlierDetection 설정 확인

마무리

Istio의 트래픽 관리 엔진은 결국 Envoy의 강력한 프록시 기능 위에 구축됩니다. Istio CRD는 사용자 친화적인 추상화이고, 실제 동작은 Envoy의 리스너, 라우트, 클러스터, 엔드포인트 구성에 의해 결정됩니다.

트래픽 관리 문제를 디버깅할 때는 항상 최종적으로 Envoy에 전달된 구성을 확인하는 것이 핵심입니다. istioctl proxy-config 명령어를 숙지하면 대부분의 트래픽 문제를 빠르게 진단할 수 있습니다.

다음 글에서는 Istio 보안 모델의 내부 구현을 살펴보겠습니다.

Istio Traffic Management Engine Deep Dive

Introduction

Istio traffic management is a core domain, accounting for 40% of the exam scope. This post analyzes how Istio CRDs are translated into Envoy configurations and how Envoy actually processes traffic internally.

VirtualService to Envoy RouteConfiguration

Translation Pipeline

VirtualService (Istio CRD)
Pilot Translation Engine
Envoy Route Configuration
  ├── VirtualHost (host-based matching)
  │   ├── Route (path/header matching)
  │   │   ├── RouteAction (routing target)
  │   │   ├── WeightedCluster (weight-based splitting)
  │   │   └── RetryPolicy (retry policy)
  │   └── Route (default path)
  └── VirtualHost (other hosts)

Match Priority

VirtualService HTTP match rules are evaluated in definition order. The same order is maintained in Envoy RouteConfiguration:

  1. Most specific match first (exact > prefix > regex)
  2. If multiple match blocks exist, the first match applies
  3. Routes without match conditions act as catch-all

Traffic Shifting

Internal implementation of weight-based traffic splitting:

# Istio VirtualService
spec:
  http:
    - route:
        - destination:
            host: reviews
            subset: v1
          weight: 75
        - destination:
            host: reviews
            subset: v2
          weight: 25

This is translated to WeightedCluster in Envoy:

{
  "route": {
    "weighted_clusters": {
      "clusters": [
        {
          "name": "outbound|9080|v1|reviews.default.svc.cluster.local",
          "weight": 75
        },
        {
          "name": "outbound|9080|v2|reviews.default.svc.cluster.local",
          "weight": 25
        }
      ],
      "total_weight": 100
    }
  }
}

Envoy generates a random number for each request and selects a cluster based on weight ranges. This is probabilistic splitting, so it operates as an approximation rather than exactly 75:25.

DestinationRule to Envoy Cluster Configuration

Cluster Configuration Translation

DestinationRule is translated to Envoy Cluster configuration:

DestinationRule
  ├── host → Cluster name prefix
  ├── subsets → Individual Cluster creation
  │   ├── subset v1 → outbound|9080|v1|reviews.default.svc.cluster.local
  │   └── subset v2 → outbound|9080|v2|reviews.default.svc.cluster.local
  └── trafficPolicy → Cluster-level settings
      ├── connectionPool → circuit_breakers
      ├── outlierDetection → outlier_detection
      └── loadBalancer → lb_policy

Cluster Naming Convention

Envoy Cluster names follow this format:

direction|port|subset|FQDN

Examples:
outbound|9080|v1|reviews.default.svc.cluster.local
inbound|8080||productpage.default.svc.cluster.local

Load Balancing Algorithms

Round Robin (Default)

Request 1Endpoint A
Request 2Endpoint B
Request 3Endpoint C
Request 4Endpoint A  (cycles back)

Envoy implementation: Distributes requests to endpoints in order. With weights, operates as Weighted Round Robin.

Least Connections

Endpoint A: 3 active connections
Endpoint B: 1 active connection  ← next request goes here
Endpoint C: 5 active connections

Envoy implementation: O(1) operation to select the endpoint with the fewest active requests.

Random

Randomly selects an endpoint for each request
Statistically even distribution at scale

Consistent Hash

Used when session affinity is needed:

spec:
  trafficPolicy:
    loadBalancer:
      consistentHashLB:
        httpHeaderName: x-user-id

Envoy implementation: Based on the Ketama hash algorithm. Places endpoints on a hash ring and selects the nearest endpoint by hashing the request key.

Hash Ring:
   0 ─── EP_A ─── EP_B ─── EP_C ─── MAX
         │              │
    x-user-id:alice  x-user-id:bob
    (always EP_A)    (always EP_B)

Benefits:

  • Minimal remapping when endpoints are added/removed
  • Same key always goes to the same endpoint (sticky sessions)

Circuit Breaker Implementation

DestinationRule outlierDetection to Envoy Translation

# Istio DestinationRule
spec:
  trafficPolicy:
    outlierDetection:
      consecutive5xxErrors: 5
      interval: 10s
      baseEjectionTime: 30s
      maxEjectionPercent: 50

Envoy behavior:

{
  "outlier_detection": {
    "consecutive_5xx": 5,
    "interval": "10s",
    "base_ejection_time": "30s",
    "max_ejection_percent": 50,
    "enforcing_consecutive_5xx": 100
  }
}

Circuit Breaker State Machine

[Closed] ──── consecutive 5xx >= 5 ────→ [Open/Ejected]
   ▲                                          │
   │                                   baseEjectionTime elapsed
   │                                          │
   └──────── successful request ──────── [Half-Open]
                                          (retry)

Detailed behavior:

  1. Closed: Normal state. All requests forwarded to the endpoint
  2. Open (Ejected): Consecutive error threshold exceeded. Endpoint removed from load balancing pool
  3. Half-Open: After baseEjectionTime, endpoint returns to pool. Ejection time increases on re-failure

Connection Pool Circuit Breaker

spec:
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        h2UpgradePolicy: DEFAULT
        http1MaxPendingRequests: 1024
        http2MaxRequests: 1024
        maxRequestsPerConnection: 10
        maxRetries: 3

Envoy internal behavior:

Request arrives
maxConnections (100) exceeded? ──→ 503 (overflow)
No
http1MaxPendingRequests (1024) exceeded? ──→ 503 (overflow)
No
http2MaxRequests (1024) exceeded? ──→ 503 (overflow)
No
Start processing request
maxRequestsPerConnection (10) reached? ──→ Close connection, create new one

Retry Implementation

VirtualService retries to Envoy Translation

spec:
  http:
    - route:
        - destination:
            host: reviews
      retries:
        attempts: 3
        perTryTimeout: 2s
        retryOn: gateway-error,connect-failure,retriable-4xx

Envoy retry policy:

{
  "retry_policy": {
    "retry_on": "gateway-error,connect-failure,retriable-4xx",
    "num_retries": 3,
    "per_try_timeout": "2s",
    "retry_host_predicate": [
      {
        "name": "envoy.retry_host_predicates.previous_hosts"
      }
    ]
  }
}

Retry Behavior Detail

Original request → Endpoint A (fails, 503)
Retry 1Endpoint B (fails, 503)  ← avoids A via previous_hosts
Retry 2Endpoint C (fails, 503)  ← avoids A, B
Retry 3Endpoint A (succeeds, 200)  ← reuses when candidates exhausted
Final response: 200

Key points:

  • previous_hosts: Avoids previously failed hosts and retries on different endpoints
  • perTryTimeout: Per-attempt timeout (separate from overall timeout)
  • Retry budget: Envoy internally limits the number of concurrent retries

retryOn Conditions Detail

ConditionEnvoy Behavior
5xxWhen upstream returns a 5xx response
gateway-errorOn 502, 503, 504 responses
connect-failureOn TCP connection failure
retriable-4xxSpecific 4xx like 409 (Conflict)
refused-streamWhen upstream resets stream with REFUSED_STREAM
resetWhen connection is reset without a response

Fault Injection Implementation

Delay Injection

spec:
  http:
    - fault:
        delay:
          percentage:
            value: 10
          fixedDelay: 5s
      route:
        - destination:
            host: reviews

Envoy implementation: The envoy.filters.http.fault filter is inserted into the HTTP filter chain.

Request arrives
Fault Filter: Generate random number (0-100)
    ├── random <= 10 → delay 5 seconds then pass to next filter
    └── random > 10 → immediately pass to next filter
Router FilterForward to upstream

Abort Injection

spec:
  http:
    - fault:
        abort:
          percentage:
            value: 20
          httpStatus: 503
      route:
        - destination:
            host: reviews

Envoy implementation:

Request arrives
Fault Filter: Generate random number (0-100)
    ├── random <= 20 → immediately return 503 (no upstream request)
    └── random > 20 → pass to next filter

Combined Fault Injection

Delay and abort can be applied simultaneously:

spec:
  http:
    - fault:
        delay:
          percentage:
            value: 50
          fixedDelay: 3s
        abort:
          percentage:
            value: 10
          httpStatus: 500

Evaluation order: Delay is applied first, then abort is evaluated.

Traffic Mirroring Implementation

VirtualService mirror to Envoy Translation

spec:
  http:
    - route:
        - destination:
            host: reviews
            subset: v1
      mirror:
        host: reviews
        subset: v2
      mirrorPercentage:
        value: 100

Envoy implementation:

Request arrives
    ├── Original request → reviews v1 (response returned to client)
    └── Mirror request → reviews v2 (response ignored, fire-and-forget)
         └── "-shadow" suffix added to Host header
             e.g., reviews → reviews-shadow

Key characteristics:

  • Mirror request responses are completely ignored
  • Mirror request failures do not affect the original request
  • "-shadow" is appended to the Host header to identify mirror traffic

ServiceEntry: Mesh Expansion

External Service Registration

apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: external-api
spec:
  hosts:
    - api.external-service.com
  location: MESH_EXTERNAL
  ports:
    - number: 443
      name: https
      protocol: TLS
  resolution: DNS

Resources created in Envoy:

ServiceEntry
    ├── Listener: Filter chain added to 0.0.0.0:443 (outbound)
    ├── Cluster: outbound|443||api.external-service.com
    │   ├── type: STRICT_DNS
    │   └── dns_lookup_family: V4_ONLY
    └── Route: api.external-service.com → routes to that Cluster

Behavior by Resolution Mode

ResolutionEnvoy Cluster TypeBehavior
NONEORIGINAL_DSTForward to original request address
STATICSTATICUse IPs from endpoints field directly
DNSSTRICT_DNSPeriodic DNS resolution
DNS_ROUND_ROBINLOGICAL_DNSRound robin among DNS results

Advanced Routing Patterns

Header-Based Canary Deployment

spec:
  http:
    - match:
        - headers:
            x-canary:
              exact: 'true'
      route:
        - destination:
            host: reviews
            subset: v2
    - route:
        - destination:
            host: reviews
            subset: v1

URI-Based Routing

spec:
  http:
    - match:
        - uri:
            prefix: '/api/v2'
      route:
        - destination:
            host: api-v2
    - match:
        - uri:
            prefix: '/api'
      route:
        - destination:
            host: api-v1

Source-Based Routing

spec:
  http:
    - match:
        - sourceLabels:
            app: frontend
            version: v2
      route:
        - destination:
            host: reviews
            subset: v2
    - route:
        - destination:
            host: reviews
            subset: v1

Debugging Tools

istioctl Command Collection

# Check VirtualService application status
istioctl analyze -n NAMESPACE

# Check routing config for a specific service
istioctl proxy-config routes PODNAME -o json | python3 -m json.tool

# Check Envoy cluster statistics
istioctl proxy-config clusters PODNAME --fqdn reviews.default.svc.cluster.local

# Check circuit breaker status (Envoy admin port)
kubectl exec PODNAME -c istio-proxy -- curl -s localhost:15000/clusters | grep outlier

# Retry statistics
kubectl exec PODNAME -c istio-proxy -- curl -s localhost:15000/stats | grep retry

Common Problem Patterns

  1. 503 UC (Upstream Connection): Upstream connection failure - check connectionPool settings
  2. 503 UO (Upstream Overflow): Circuit breaker triggered - check maxConnections/maxPendingRequests
  3. 503 NR (No Route): Route matching failure - check VirtualService host/match
  4. 503 UH (Upstream Unhealthy): All endpoints ejected - check outlierDetection settings

Conclusion

Istio's traffic management engine is built on top of Envoy's powerful proxy capabilities. Istio CRDs are user-friendly abstractions, and actual behavior is determined by Envoy listener, route, cluster, and endpoint configurations.

When debugging traffic management issues, always verify the final configuration delivered to Envoy. Mastering the istioctl proxy-config commands enables rapid diagnosis of most traffic problems.

In the next post, we will examine the internals of the Istio security model.