왜 헬스체크만으로는 부족한가
액티브 헬스체크는 /healthz 같은 엔드포인트를 주기적으로 찔러 보고 응답이 오면 정상으로 판단한다. 하지만 실제 장애는 헬스체크가 통과하는 상태에서도 발생한다. 특정 파드만 GC 스톨로 지연이 튀거나, 커넥션 풀이 고갈돼 5xx를 뿜거나, 디스크가 느려져 일부 요청만 실패하는 경우다. 헬스체크는 "살아있는가"만 보지만, 사용자 트래픽은 "제대로 응답하는가"를 요구한다. 이 간극을 메우는 것이 Envoy의 아웃라이어 감지(outlier detection)다.
아웃라이어 감지는 실제 서비스 트래픽의 결과를 관찰해, 다른 엔드포인트보다 유독 실패가 많은 호스트를 로드밸런싱 풀에서 일시적으로 빼낸다. 별도 프로브 없이 패시브하게 동작한다는 점이 핵심이다.
동작 원리: 연속 실패와 성공률
Envoy는 각 업스트림 호스트별로 요청 결과를 집계하고, 두 가지 축으로 이상치를 판정한다.
- 연속 오류(consecutive): 5xx 또는 게이트웨이 오류가 연속으로 N회 발생하면 즉시 격리(eject).
- 성공률 기반(success rate): 클러스터 전체 호스트의 평균 성공률과 표준편차를 계산해, 통계적으로 벗어난 호스트를 격리.
격리된 호스트는 base_ejection_time만큼 풀에서 빠졌다가 복귀한다. 반복 격리되면 대기 시간이 곱연산으로 늘어나, 만성 불량 호스트일수록 오래 격리된다.
기본 설정 예시
클러스터 정의에 outlier_detection 블록을 추가한다. 아래는 연속 5xx와 성공률을 함께 쓰는 실전 설정이다.
clusters:
- name: backend
connect_timeout: 1s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: backend
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: backend, port_value: 8080 }
outlier_detection:
consecutive_5xx: 5
interval: 10s
base_ejection_time: 30s
max_ejection_percent: 50
success_rate_minimum_hosts: 5
success_rate_request_volume: 100
success_rate_stdev_factor: 1900
enforcing_consecutive_5xx: 100
enforcing_success_rate: 100
max_ejection_percent는 안전장치다. 이 값이 없으면 전면 장애 시 모든 호스트가 격리돼 트래픽을 받을 곳이 사라진다. 절반 이상은 남기는 것을 권장한다.
주요 파라미터 비교
| 파라미터 | 역할 | 실무 기준 |
|---|---|---|
| consecutive_5xx | 연속 5xx 격리 임계 | 5 (짧은 스파이크 무시) |
| interval | 분석 주기 | 10s |
| base_ejection_time | 기본 격리 시간 | 30s |
| max_ejection_percent | 최대 격리 비율 | 50 이하 |
| success_rate_request_volume | 성공률 판정 최소 요청 수 | 100 |
| success_rate_stdev_factor | 편차 배수(÷1000) | 1900 = 1.9σ |
격리 상태 확인하기
실제로 호스트가 빠지는지 반드시 관측해야 한다. Envoy 어드민 통계에서 격리 카운터를 확인한다.
# 현재 격리된 호스트 수와 격리 이벤트 누계
curl -s localhost:9901/stats | grep outlier
# cluster.backend.outlier_detection.ejections_active: 1
# cluster.backend.outlier_detection.ejections_enforced_total: 7
# cluster.backend.outlier_detection.ejections_enforced_consecutive_5xx: 5
# 어떤 엔드포인트가 빠졌는지 상세 확인
curl -s localhost:9901/clusters | grep -E "backend|health_flags"
health_flags에 /failed_outlier_check가 붙은 엔드포인트가 격리 대상이다. 이 두 통계를 대시보드에 올려 두면 "왜 특정 파드로 트래픽이 안 가는지" 추적이 쉬워진다.
운영 시 주의점
enforcing 값을 단계적으로 올려라. 처음부터 enforcing_*: 100으로 두면 오탐 시 정상 호스트까지 빠진다. 도입 초기에는 enforcing_consecutive_5xx: 0으로 두면 판정은 하되 실제 격리는 하지 않아, 통계만 보며 임계를 튜닝할 수 있다.
5xx의 정의를 확인하라. 애플리케이션이 정상적인 비즈니스 오류를 500으로 반환하면, 코드 문제 없는 호스트가 격리된다. 재시도 정책과 함께 사용할 때는 재시도로 인한 부하 쏠림도 고려해야 한다.
소규모 클러스터에서는 성공률 감지를 조심하라. 호스트가 success_rate_minimum_hosts보다 적으면 성공률 감지는 아예 동작하지 않는다. 이 경우 연속 오류 감지가 유일한 방어선이 되므로 임계를 보수적으로 잡는다.
아웃라이어 감지는 장애의 원인을 고치지 않는다. 나쁜 호스트를 잠시 격리해 사용자 영향을 줄이는 완충 장치일 뿐이다. 격리가 잦다면 통계를 근거로 근본 원인을 파고들어야 한다.