리그캣의 개발놀이터

kafka lag, Fluentd 트러블 슈팅 (Trouble Shooting) 본문

인프라/Logging Metric

kafka lag, Fluentd 트러블 슈팅 (Trouble Shooting)

리그캣 2023. 3. 12. 17:54

현재 운영하는 시스템을 보면 하기와 같이 되어있다.

 

log txt producer(ex. filebeat) -> message Q(kafka) -> consumer (ex. fluentd) -> es

 

자중 발생하는 문제가 있는데 kafka의 lag이 쌓인다는 것이다.

카프카 lag은 카프카 운영에 있어서 중요한 모니터링 지표인데, 카프카 파티션에 데이터가 하나씩 들어가면서 각 데이터에 오프셋이라는 숫자가 붙는다.  즉 데이터 하나가 파티션에 인입되면 0 그다음 데이터가 인입되면 1 ..2...3.. 이렇게 오프셋이 붙기 시작한다. 

 

참고 : https://strimzi.io/blog/2021/01/07/consumer-tuning/

 

이 오프셋을 참고해서 producer <-> kafka  <-> consumer 사이의  데이터 전송을 대략적으로 확인할 수 있는데, consumer 읽어오늘 offset과 kafka에 인입된 offset의 차이를 lag이라고 생각하면 된다. 

그라파나에서 해당 lag의 지표를 보면 하기와 같다.

참고 : https://www.lightbend.com/blog/monitor-kafka-consumer-group-latency-with-kafka-lag-exporter

 

그래도 위의 경우는 lag을 빠르게 소비하는 경우다. 실제 운영환경에서는 빠르게 대응을 하지못하면 해당 lag이 시간이 지날수록 늘어난다.



간단하게, lag이 커지면 consumer(fluentd)가  kafka의 데이터를 못가져온다는 뜻으로 이해하면된다.
이렇게 못가져오는 이유는 여러가지가 있는데

이미 kafka에 데이터가 인입된었기 때문에 producer는 제외하고 kafka <-> consumer <-> es(최종 데이터 엔드포인트) 관계를 잘 따라서 대응해야한다.

 

예를 들면, kafka 에서 consumer에 데이터를 못보내고 있는것일 수 있으며 반대로 consumer에서 kafka데이터를 못받고 있는 상태일 수 있다. 

 

consumer에서 kafka의 데이터를 못받고 있는 상태는 여러가지로 나눌 수 있는데 최종 목적이지인 es에서 거절이 일어나서 consumer가 데이터를 못보내주기 때문에 buffer (데이터가 저장되는 큐라고 생각하면 편할것같다.)가 차서 kafka에서 데이터를 못읽어오고 있을수도 있다. 

 

해당 포스팅은 이러한 lag을 처리해주기 위한 방법중 하나로 consumer(Fluentd)를 트러블 슈팅하기 위한 내용을 작성해보았다.

물론 대부분의 내용은 Fluentd에서 제공하는 Trouble Shooting 가이드에 이미 잘 작성된 내용을 번역해본것이다.

 

Fluentd 가 데이터 엔드포인트에 데이터를 잘 인입시키고 있던 환경에서 Lag이 벌어진다면, consumer 로그 및 메트릭으로 문제가 없는지 확인 후 대응할 수 있다.


1. 먼저 리소스가 충분한지 확인해봐야한다.

이러한 수치는 fluentd에서 제공하는 메트릭 또는 pod 리소스 메트릭을 기반으로 추측할 수 있다.

- memory가 충분한가.

- cpu가 충분한가.

 

만약 부족하다면 스케일 아웃 또는 스케일 업을 추천한다. 


2. es(endpoint)에서 잘 받아주고 있는지 확인한다.

현재 es(endpoint)가 잘 받아주고 있는 상태인지 확인해봐야한다. 로그와 운영 메트릭을 기반으로 endpoint 서비스가 정상적으로 데이터를 받아주고 있는 상태인지 확인해봐야한다. 그렇지 않다면 리소스 조정 또는 튜닝을 통해서 endpoint가 정상적인 환경을 제공할 수 있도록 해야한다.

 

3. network 환경에 문제가 없는지 확인한다.

정상적으로 로깅데이터가 인입이 되고있다가 안된다. 그렇다면, 네트워크에 문제가 없는지 확인해봐야한다. fluent-cat등 더미 데이터를 제공해주는 서브툴이 있는데 이를 확인해서 네트워크에 문제가 없는지 확인 후 처리해자.

 

4. fluentd의 retry 액션으로 인해서 데이터가 지연되는 이슈
network failure(3번의 경우) 또는 application log rejection으로 인해서 백엔드쪽으로 fluentd가 닿지 않는 문제가 있는데, 이때 Fluentd는 자동으로 exponential backoff sequence에 참여하게 된다. 하기의 작동방식을 이해하고 현재 환경에 맞춰서 fluentd를 튜닝하는 방식이 있다.

Exponnential Backoff 는 어떤식으로 동작할까?
기본적으로 Fluentd는 재시도할 때마다 대기 간격을 기하급수적으로 늘린다. 예를 들어, 초기 대기 간격이 1초로 설정되고 exponential factor(지수 계수)가 2라고 가정하면 각 시도는 다음 시점에서 발생한다.
0.. 1.. 3.. 7… 15
  1. 실패가 발생한다.
  2. 첫번째 시도는 1초가 걸린다.
  3. 두번째 시도는 2초가 걸린다.
  4. 세번째 시도는 4초가 걸린다.
  5. 네번째 시도는 8초가 걸린다.

대기 간격은 기본적으로 무작위로 지정된다.

  • Fluentd는 임의로 선택한 값(0.875에서 1.125 사이)을 곱하여 대기 간격을 다양화 시키는데, retry_randomize 설정을 ‘false’로 하여 해당 옵션을 끌 수 있다.
  • 대기간격은 제한될 수 있는데. ‘retry_max_interval’을 5초로 설정되면 4번째재시도에서 8초가 아닌 5초로 제한되게 된다.

이 외의 fluentd의 retry 관련 파라미터를 이해하고, 본인의 운영환경에 맞게 파라미터 튜닝을 해볼 수 있을 것 같다.

 

5. fluentd 로그가 BufferOverflow 에러로 꽉채워지는 이슈

  • Fluentd OutPut 플러그인은 일반적으로 메모리(기본값) 또는 디스크에 저장된 버퍼를 포함한다.
  • 이러한 버퍼는 Chunks를 포함하는데 버퍼가 가득차있으나, Fluentd에 Log가 인입되면 Fluentd는 자동으로 ‘BufforOverflowError’를 반환한다.

buffer 플러그인은 I/O 워크로드를 최적화 하기 위해서, 로그 이벤트의 일괄 처리 및 임시 캐싱에 중점을 두는 플러그인이다.

먼저 fluentd의 buffer flushing 방법을 이해해보자.

  • buffer file에 tag값과 time 키 값으로 chunk가 쌓이게 된다.
  • chunk가 flushing 된다 (되는 조건)
    • buffer chunk가 쌓이고 'flush_interval' (기본 60s)시간이 지나면 flushing된다. 
    • buffer chunk가 chunk_limit_size * chunk_full_threshold에 도달한 경우
  • flush가 발생하면 enqueue가 발생한다.
  • queue에 쌓이는 데이터가 output이 된다.

이러한 buffer flushing에 과정에서 Overflow가 발생함으로 하기 파라미터등을 주로 튜닝을 해보면 된다.

  • `flush_interval`을 조정하자. (공식 가이드에서는 낮게 조정하는 것을 추천)
  • `worker`와 `flush_thread_count`를 증가시키자
  • `chunk_limit_size`를 증가시키자.

해당 파라미터 외에도 다양한 버퍼 관련 파라미터 등이 있으니 자세히 이해하고 조정을 하면서 개발환경에서 테스트를 해보고 적용해보면 lag이 쌓이는 증상을 파악할 수 있지않을까 생각한다.

 

실 운영을 하면서 느낀점은 위의 flush하는 동작 방식을 파악하다보니, buffer_flush와 chunk_limit_size, chuk_full_threshold등 우선순위와 상관관계가 있기때문에 consumer 튜닝이 쉽지 않았다. 

또한, HTTP RPC를 사용해서 reload 하여, 파라미터를 바꿀 수 있을것같으나 운영환경에서 값을 바꾸기전에는 선행 테스트가 필요하니 시간이 오래걸린다.  
그래도 동작방식과 파라미터를 좀 더 자세히 이해하고, 적용하다보면 좀 더 안정적이고 빠른 로깅환경을 제공할 수 있지 않을까?

Comments