본문 바로가기
기타/기타

[Envoy 이해하기] Circuit_Breaker (outlier_detection)

by 사바라다 2025. 5. 1.
반응형

안녕하세요. 오늘은 Envoy 이해하기 3번째 시간으로 envoy에서 서비스 회복성(Resilience)을 위한 설정을 들을 알아보는 시간을 가져보도록 하겠습니다.

개발을 하다보면 서비스의 부하를 막기 위해서 RateLimit를 건다던지 장애 전파를 막기 위해서 Circuit Breaker를 추가한다는 일을 많이 하곤 합니다. 이러한 설정은 만약 Java/Kotiln을 사용하신다면 Resilience4j 등을 사용할 수 있습니다.

그런데 사실 이러한 서비스 회복성 관련된것은 대부분 네트워크 관련된 것으로써 envoy가 이러한 역할을 해줄 수 있습니다. envoy에 이러한 설정을 맡겨버리면 Service 개발자는 Application 개발에 집중할 수 있게됩니다. 관련된 내용과 설정하는 방법을 오늘은 한번 알아보도록 하겠습니다.

Circuit Breaker

Circuit Breaker는 Spring Cloud Hystrix에서 나온 개념으로 의존성을 가지고 있는 서버가 과부하일 때 자동으로 해당 연결을 끊고 시스템을 보호하는 역할을 합니다.

특정 서버가 장애상황이 발생했고 그 상황을 인지하지 못한 호출자가 지속적으로 호출하게 된다면 호출 했던 곳은 에러를 지속적으로 받을 수 있습니다. 특히 일반적으로 이러한 경우 latency가 증가하게 됩니다. 증가된 평균 latency는 호출자 서버에 채류하는 요청을 많아지게 만들어서 CPU 또는 메모리 리소스 부하를 일으킬 수 있습니다.

이러 상황은 down stream에 발생한 장애가 up stream 까지 전파될 수 있습니다. 그리고 이것을 장애 전파라고 하는데요. 이를 막기위해서 Circuit Breaker를 사용하여 더 이상 호출이 무의미하다고 판단되는 서버에로의 호출을 중단하고 fallback 로직을 수행하는 등의 방법을 사용할 수 있습니다.

Circuit Breaker에 대해서 좀 더 자세히 알고 싶으신 분들을 위해서 5년전이지만 작성했던 블로그가 도움이 될 것 같아 남깁니다. [MSA] Spring Cloud Hystrix - 개념편

그렇다면 아래에서 Circuit Breaker의 시나리오를 작성하고 직접 테스트해보도록 하겠습니다. Envoy는 하위 dependency로 Backend와 Backend-2를 가지고 있습니다.

Envoy를 통한 Circuit Breaker

Envoy를 통해서 Circuit Breaker를 테스트하기 위해서는 outlier_detection 설정을 이용할 수 있습니다. outlier_detection특정 시간마다 error count를 측정하고 만약 error의 수가 일정치를 넘으면 해당 reverse server로는 데이터를 흘리지 않도록 설정할 수 있습니다.

envoy에 circuit_breaker의 이름의 설정이 있지만 이것은 request로 들어오는 connection 또는 request 수에 의해서 limit가 걸리는 시스템이기 때문에 기본적으로 알려져있는 circuit_breaker와는 의미가 다르기 때문에 주의하는게 좋습니다.

envoy 기반의 outlier_detection에 대해서 설정 테스트를 한번 진행해보도록 하겠습니다.

시나리오

상황

  • backend라고 하는 cluster가 있습니다.
  • 해당 cluster에는 down stream server로 backend와 backend-2가 있습니다.
  • 해당 cluster는 round robin으로 down stream server에 1번씩돌아가면서 요청합니다.
  • 1번 서버는 항상 500 에러를 발생합니다.

outlier_detection 설정

  • 5xx 에러가 5번 이상 발생하면 reverse proxy 에서 해당 서버를 제거합니다.
  • 이는 3초마다 체크합니다.
  • 한번 제거되면 30초 동안은 지속적으로 제거된 상태로 둡니다.
  • 최대 제거될 수 있는 서버는 50% 입니다.

시나리오

  1. 요청은 계속 날아간다 (k6, curl 등으로)
  2. 1번 서버에서 실패(5xx) 요청이 발생한다
  3. Envoy는 매 interval (3초) 마다 전체 엔드포인트를 스캔한다
  4. 그 시점consecutive_5xx 조건이 충족되었으면 ejection 시킨다
  5. ejection 후 base_ejection_time 동안 제외한다.
  6. 이후 요청은 모두 2번서버로 날아간다.
  7. 그 이후 다시 복귀시킨다

참고

  • envoy의 outlier_detection은 하위 endpoints가 1대일 경우에는 정상적으로 동작하지 않습니다.

설정 yaml

envoy는 아래와 같은 설정을 가지고 있습니다.

  clusters:
  - name: backend
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: backend
      endpoints:
        - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: backend
                  port_value: 8080
          - endpoint:
              address:
                socket_address:
                  address: backend-2
                  port_value: 8080
    outlier_detection:
      consecutive_5xx: 5       # 5번 5xx 오류 발생 시 제거
      interval: 3s            # 3초마다 체크
      base_ejection_time: 30s  # 제거 후 30초 동안 ejection
      max_ejection_percent: 50 # 전체 서버의 최대 50%까지 제거 가능``````

테스트

테스트 툴로는 k6를 사용했습니다. 테스트를 진행했을 때의 결과는 아래와 같습니다.

clients logs

 █ TOTAL RESULTS

    CUSTOM
    backend_internal_server_error_counter........................................: 5      0.164966/s
    backend_success_counter......................................................: 1995   65.821625/s

여러번 테스트했을 때 backend_internal_server_error_counter 가 5가 아닌 케이스도 있었습니다. 이것의 이유는 envoy의 outlier_detection는 시간단위로 bucket에 들어온 request 수의 resopnse를 기반으로 체크하기 때문에 기준시간이 되었는가에 따라서 판단이 달라질 수 있는것입니다.

envoy logs

[2025-04-26 12:28:11.965][1][debug][upstream] [source/common/upstream/cluster_manager_impl.cc:959] host 192.168.48.3:8080 in cluster backend was ejected by the outlier detector

envoy에서 서버가 빠졌을 때 ejected 되었다고 판단하고 이를 로그로 남깁니다.

마무리

오늘은 이렇게 envoy에서 제공하는 circuit breaker인 outlier detection에 대해서 알아보는 시간을 가져보았습니다.

감사합니다.

참고

[1] # [MSA] Spring Cloud Hystrix - 개념편

[2] https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/outlier_detection.proto#

반응형

댓글