본문 바로가기
WIKI 기술 지식 베이스

서킷 브레이킹

원문 보기 위키 갱신

서킷 브레이킹 (Circuit Breaking)

분산 애플리케이션의 안정성을 높이는 패턴인 서킷 브레이킹을 Linkerd가 어떻게 엔드포인트 수준에서 수행하는지 알아봐요.

출처: Linkerd Circuit Breaking

본문

서킷 브레이킹(circuit breaking) 은 분산 애플리케이션의 안정성을 높이기 위한 패턴이에요. 서킷 브레이킹에서 원격 백엔드에 네트워크 호출을 하는 애플리케이션은 그 호출이 성공하는지 실패하는지 모니터링해서, 해당 백엔드가 실패 상태인지 판단하려고 해요. 특정 백엔드가 실패 상태라고 판단되면 그 서킷 브레이커가 "트립(trip)"되고, 백엔드가 정상으로 돌아왔다고 판단되기 전까지는 더 이상 요청을 보내지 않아요.

Linkerd 프록시는 구성 가능한 실패 누적(failure accrual) 전략을 사용해 HTTP 요청에 대해 엔드포인트 수준의 서킷 브레이킹을 수행할 수 있어요. 즉 Linkerd 프록시는 로드 밸런서 안의 개별 엔드포인트 수준(특정 Service의 각 Pod)에서 서킷 브레이킹을 수행하고, 실패는 HTTP 응답 상태 코드 수준에서 추적돼요.

서킷 브레이킹은 클라이언트 측 동작이므로 Linkerd 프록시의 아웃바운드 측에서 수행돼요.¹ 아웃바운드 프록시는 실패하는 엔드포인트를 사용 불가능(unavailable) 으로 표시해 로드 밸런서에서 서킷 브레이킹을 구현해요. 엔드포인트가 사용 불가능하면 로드 밸런서는 요청을 보낼 위치를 결정할 때 그 엔드포인트를 선택하지 않아요. 즉 일부 엔드포인트만 서킷 브레이커가 트립된 경우, 프록시는 그 엔드포인트들이 실패 상태인 동안 단순히 선택하지 않을 뿐이에요. 로드 밸런서의 모든 엔드포인트가 사용 불가능하면 요청은 503 Service Unavailable 오류로 실패할 수 있고, Service가 HTTPRoute의 여러 backendRef 중 하나라면 전체 백엔드 Service가 사용 불가능하다고 간주되어 다른 백엔드가 선택될 수 있어요.

outbound_http_balancer_endpoints 게이지 메트릭은 로드 밸런서의 "준비된(ready)" 엔드포인트 수와 "대기 중(pending)" 엔드포인트 수를 보고하며, "대기 중" 수에는 실패 누적으로 인해 사용 불가능해진 엔드포인트가 포함돼요.

실패 누적 정책 (Failure Accrual Policies)

실패 누적 정책(failure accrual policy) 은 엔드포인트에 대한 실패를 어떻게 추적할지, 그리고 어떤 기준으로 엔드포인트가 사용 불가능해지는지("서킷 브레이커 트립")를 결정해요.

연속 실패 (Consecutive Failures)

이 실패 누적 정책에서는 구성 가능한 횟수만큼 실패가 연속적으로(즉 성공 없이) 발생한 후에 엔드포인트가 실패로 표시돼요. 예를 들어 최대 실패 횟수가 7이면, 성공 없이 7번의 실패가 연속으로 발생하면 엔드포인트가 사용 불가능해져요. 이 실패 누적 정책에서 실패란 HTTP 5xx 서버 오류 상태 코드가 있는 HTTP 응답이거나, 다음 gRPC 상태 코드 중 하나가 있는 gRPC 응답을 의미해요.

  • DATA_LOSS
  • DEADLINE_EXCEEDED
  • INTERNAL
  • PERMISSION_DENIED
  • UNAVAILABLE

통합 (Unified)

이 실패 누적 정책에서는 다음 조건 중 하나라도 충족되면 엔드포인트가 실패로 표시돼요.

  • 성공률이 구성된 임계값 아래로 떨어짐. 성공률 계산에서 실패란 HTTP 5xx 서버 오류 또는 429 상태 코드가 있는 HTTP 응답이거나, 다음 gRPC 상태 코드 중 하나가 있는 gRPC 응답을 의미해요.
    • DATA_LOSS
    • DEADLINE_EXCEEDED
    • INTERNAL
    • PERMISSION_DENIED
    • UNAVAILABLE
    • RESOURCE_EXHAUSTED
  • 구성된 횟수만큼 실패가 연속으로 발생. 연속 실패 추적에서 실패란 HTTP 5xx 서버 오류 상태 코드가 있는 HTTP 응답이거나, 다음 gRPC 상태 코드 중 하나가 있는 gRPC 응답을 의미해요.
    • DATA_LOSS
    • DEADLINE_EXCEEDED
    • INTERNAL
    • PERMISSION_DENIED
    • UNAVAILABLE

Unified 실패 누적에 대한 자세한 내용은 Rate Limit Aware Load Balancing 문서를 참고하세요.

관찰 기간과 백오프 (Probation and Backoffs)

실패 누적 정책이 엔드포인트를 사용 불가능하게 만들면, 서킷 브레이커는 엔드포인트가 여전히 실패 상태인지 판단하고, 회복했다면 다시 사용 가능 상태로 전환하려고 시도해요. 이 과정을 관찰 기간(probation) 이라고 해요. 엔드포인트가 관찰 기간에 들어가면 일시적으로 다시 로드 밸런서에 노출되고, 프로브 요청(probe request) 이라고 하는 단일 요청을 처리하도록 허용돼요. 이 요청이 성공하면 엔드포인트는 더 이상 실패로 간주되지 않고 다시 사용 가능해져요. 프로브 요청이 실패하면 엔드포인트는 계속 사용 불가능한 상태로 남고, 백오프(backoff) 후에 다시 프로브 요청이 발행돼요.

참고

HTTP 실패 누적 맥락에서 프로브 요청은 실제 애플리케이션 요청이며, HTTP readiness/liveness 프로브와 혼동해서는 안 돼요. 즉 서킷 브레이커는 엔드포인트가 헬스 체크에 성공적으로 응답한다는 것만으로 관찰 기간을 벗어나게 하지 않아요. 엔드포인트가 다시 사용 가능해지려면 실제 애플리케이션 트래픽이 성공해야 해요.

엔드포인트의 실패 누적 정책이 서킷 브레이커를 트립하면, 최소 최소 패널티(minimum penalty) 기간 동안 사용 불가능한 상태로 유지돼요. 이 기간이 지나면 엔드포인트가 관찰 기간에 들어가요. 프로브 요청이 실패하면 백오프 기간이 지날 때까지 엔드포인트는 다시 관찰 기간에 들어가지 않아요. 프로브 요청이 실패할 때마다 백오프는 최대 패널티(maximum penalty) 기간이 정한 상한까지 지수적으로 증가해요.

jitter 라고 하는 약간의 무작위 노이즈가 각 백오프 기간에 추가돼요. jitter는 jitter ratio 라는 파라미터로 제어되며, 0.0부터 100.0까지의 부동소수점 숫자로, 원래 백오프 기간 중 jitter로 추가될 수 있는 최대 백분율을 나타내요.

실패 누적 구성

HTTP 실패 누적은 일련의 어노테이션으로 구성돼요. 이 어노테이션들이 Kubernetes Service에 추가되면, 클라이언트 프록시는 그 Service의 엔드포인트와 통신할 때 HTTP 실패 누적을 수행해요. Service에 실패 누적 어노테이션이 없으면 프록시는 실패 누적을 수행하지 않아요.

경고

서킷 브레이킹은 ServiceProfiles와 호환되지 않아요. 어노테이션이 지정된 Service에 ServiceProfile이 정의되어 있으면, 프록시는 ServiceProfile이 존재하는 한 서킷 브레이킹을 수행하지 않아요.

참고

일부 실패 누적 어노테이션 값은 기간(duration)을 나타내요. 기간은 양의 정수와 단위로 지정하며, 단위는 ms(밀리초), s(초), m(분), h(시간), d(일) 중 하나일 수 있어요.

메시가 적용된 클라이언트가 해당 Service로 트래픽을 보낼 때 서킷 브레이킹을 사용하도록 하려면 Service에 이 어노테이션을 설정하세요.

  • balancer.linkerd.io/failure-accrual: 이 Service와 통신할 때 사용할 실패 누적 정책을 선택. 이 값이 없으면 실패 누적이 수행되지 않음. 이 어노테이션의 지원 값은 consecutive와 unified.

실패 누적 모드가 "consecutive"일 때, 다음 어노테이션들이 연속 실패(consecutive-failures) 실패 누적 정책의 파라미터를 구성해요.

  • balancer.linkerd.io/failure-accrual-consecutive-max-failures: 엔드포인트가 사용 불가능해지기 전에 발생해야 하는 연속 실패 횟수를 설정. 정수여야 함. 이 어노테이션이 없으면 기본값 7.
  • balancer.linkerd.io/failure-accrual-consecutive-min-penalty: max-failures 연속 실패가 발생한 후 엔드포인트가 사용 불가능으로 표시되는 최소 패널티 기간을 설정. 이 기간이 지나면 엔드포인트가 프로브됨. 이 기간은 0이 아니어야 하며 max-penalty 기간보다 커서는 안 됨. 이 어노테이션이 없으면 기본값 1초(1s).
  • balancer.linkerd.io/failure-accrual-consecutive-max-penalty: max-failures 연속 실패가 발생한 후 엔드포인트가 사용 불가능으로 표시되는 최대 패널티 기간을 설정. 이는 프로브 요청 사이 기간의 상한. 이 기간은 0이 아니어야 하며 min-penalty 기간보다 커야 함. 이 어노테이션이 없으면 기본값 1분(1m).
  • balancer.linkerd.io/failure-accrual-consecutive-jitter-ratio: 관찰 기간 백오프에 사용되는 jitter ratio를 설정. 부동소수점 숫자이며 0.0과 100.0 사이여야 함. 이 어노테이션이 없으면 기본값 0.5.

실패 누적 모드가 "unified"일 때, 다음 어노테이션들이 unified 실패 누적 정책의 파라미터를 구성해요.

  • balancer.alpha.linkerd.io/failure-accrual-success-rate-threshold: 창 안의 응답 성공률이 이 임계값 아래로 떨어지면 엔드포인트가 사용 불가능해짐. 0.0에서 1.0 사이여야 함. HTTP 429와 gRPC RESOURCE_EXHAUSTED 같은 비율 제한 응답은 이 계산에서 실패로 간주됨. 이 어노테이션이 없으면 기본값 0.8(성공률 80%).
  • balancer.alpha.linkerd.io/failure-accrual-success-rate-window: 성공률을 계산하는 시간 창. 이 어노테이션이 없으면 기본값 10s.
  • balancer.alpha.linkerd.io/failure-accrual-success-rate-min-requests: 이 브레이커가 트립되기 전에 창 안에 있어야 하는 최소 응답 수. 이는 성공률 계산이 의미 있게 되기 전에 충분한 응답 수를 확보하기 위한 "콜드 스타트" 보호 역할을 함. 이 어노테이션이 없으면 기본값 5.
  • balancer.linkerd.io/failure-accrual-consecutive-max-failures: 위와 동일.
  • balancer.linkerd.io/failure-accrual-consecutive-min-penalty: 위와 동일.
  • balancer.linkerd.io/failure-accrual-consecutive-max-penalty: 위와 동일.
  • balancer.linkerd.io/failure-accrual-consecutive-jitter-ratio: 위와 동일.

¹ pod 내부에서 클러스터의 나머지 부분으로 가는 연결을 처리하는 프록시 부분.

더 알아보기 (Learn more)