Kafka의 메트릭

Kafka의 모든 메트릭은 JMX(Java Management Extensions) 인터페이스를 통해 사용 가능하다.

JVM 기반의 애플리케이션에서 Prometheus에 메트릭을 공개하기 위한 Java 에이전트를 실행해 메트릭을 수집한다.

 

카프카 브로커 실행 시 JVM옵션에 jmx prometheus javaagent를 metric config와 함께 추가한다.

-javaagent:/path/to/jmx_prometheus_javaagent.jar=8080:/path/to/kafka_config.yml

 

 

kafka_config.yml

jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:6092/jmxrmi
ssl: false
lowercaseOutputName: true
rules:
- pattern: 'kafka.cluster<type=(.+), name=(.+), topic=(.+), partition=(.+)><>Value'
  name: kafka_cluster_$1_$2
  labels:
    topic: '$3'
    partition: '$4'

- pattern: 'kafka.log<type=Log, name=(.+), topic=(.+), partition=(.+)><>Value'
  name: kafka_log_$1
  labels:
    topic: '$2'
    partition: '$3'
...
  • Kafka 브로커의 메트릭 패턴을 정의하고, 해당 메트릭을 Prometheus 형식에 맞게 변환하는 규칙을 설정한다.

 

Kafka 서버가 시작될 때 jmx_prometheus_javaagent가 함께 실행되며, 메트릭이 수집되고 Prometheus에 노출된다. jmx_prometheus_javaagent가 수집한 메트릭은 /metrics 엔드포인트를 통해 확인 가능하다.

 

 

브로커 메트릭

메트릭 의미 및 대응방안
UnderReplicatedPartitions
미복제 파티션 갯수
브로커 메트릭 중 가장 중요한 메트릭 정보
리더 리플리카 브로커의 파티션을 팔로어 리플리카 브로커들이 복제하지 못한 파티션들의 총계 제공

장애 상황
0이 아닌 숫자가 변동없이 꾸준히 나타나는 경우
- 클러스터의 부하 불균형
- 리소스 자원 고갈(CPU, 네트워크 처리량, 디스크)
- 하드웨어 장애
- 다른 프로세스와의 충돌
- 로컬 구성의 차이

대응
- kafka-reassign-partition.sh를 이용한 재할당 (부하 불균형 시)
- 다른 브로커와 로컬 구성 비교

ActiveControllerCount
클러스터 컨트롤러 갯수
브로커의 클러스터 컨트롤러 여부 확인
컨트롤러인 경우 1의 값을 갖는다 (아닌 경우 0)

장애상황
1의 값을 갖는 브로커가 2개 이상인 경우
1의 값을 갖는 브로커가 한개도 없는 경우

대응
- 컨트롤러가 2개인 경우, 두 브로커 모두 재시작
- 컨트롤러가 없는 경우, 컨트롤러 스레드가 제대로 동작하지 않는 이유 찾아야함(클러스터의 모든 브로커 재시작 권장)
RequestHandlerAvgIdlePercent
요청 핸들러 유휴 비율
요청 핸들러가 사용중이 아닌 시간의 백분율(%)을 나타냄
실수이면서 0과 1사이의 값을 가짐

장애상황
이 수치가 작을수록 브로커의 작업 부담 커짐
20%미만 - 잠재적인 문제 있음으로 판단
10%미만 - 성능 문제가 진행중임
- 스레드 풀의 스레드 수가 충분하지 않은 경우
- 스레드들이 각 요청의 불필요한 작업을 수행하는 경우

BytesInPerSec
모든 토픽의 입력 바이트
모든 토픽의 바이트 입력을 초당 바이트로 나타냄
프로듀서로부터 브로커가 받는 메시지 트래픽이 얼마나 되는지 측정하는데 유용
클러스터를 확장해야하거나, 데이터 증가에 따른 다른작업을 해야할 시기를 결정하는데 도움
클러스터의 파티션들을 리밸런싱 해야하는지 평가할 때 유용
BytesOutPerSec
모든 토픽의 출력 바이트
모든 토픽의 출력 바이트
모든 토픽의 바이트 출력을 초당 바이트로 나타냄
컨슈머의 메세지 읽는 속도 측정
리플리카 트래픽도 포함됨 예) 복제팩터 2인 경우, 바이트 출력 속도는 바이트 입력속도의 두 배
MessagesInPerSec
모든 토픽의 메세지 입력 수
모든 토픽의 메세지 입력 수
초당 입력되는 개별적인 메세지 수 (메세지 크기와 무관)
평균 메시지 크기를 결정하기 위해 바이트 입력 속도와 함께 사용
PartitionCount
파티션 갯수
브로커가 갖는 모든 리플리카 파티션을 포함한 파티션 갯수
LeaderCount
리더 파티션 갯수
브로커가 현재 리더인 파티션의 수
클러스터의 모든 브로커에 걸쳐 균등해야 한다.
정기적으로 확인하고 경계할 것 권장

장애 상황
이 메트릭 값이 모든 브로커가 균등하지 않을 때
이 값이 0이 될 때
클러스터에 불균형 발생 시 브로커의 리더 갯수 서로 달라질 수 있음

대응

0인 경우에는 선호 리플리카 선출을 통해 균형을 맞추어야 함
OfflinePartitionsCount
리더가 없는 파티션 갯수
클러스터에서 현재 리더가 없는 파티션 개수
클러스터의 컨트롤러 브로커에 의해서만 제공
프로듀서에게 메시지 유실 등 영향을 줄 수 있으므로 즉시 해결 필요

장애상황
1 이상일 때
- 해당 파티션의 리더나 팔로어인 모든 브로커들이 다운되었을 때
- 해당 파티션의 리더와 팔로어간의 메세지 개수 불일치로 인해 리더가 될 수 있는 동기화 리플리카가 없고 언클린 리더 선출이 비활성화 되어있을 때

 

 

 

 

토픽 메트릭

브로커 메트릭과 매우 유사. 토픽 이름이 지정된다는 것과 지정된 토픽에만 각 메트릭이 국한된다는 점이 다르다.

이름 JMX MBean
바이트 입력 kafka.server:type=BorkerTopicMetrics, name=BytesInPerSec, topic=TOPICNAME
바이트 출력 kafka.server:type=BorkerTopicMetrics, name=BytesOutPerSec, topic=TOPICNAME
읽기 실패 요청 수 kafka.server:type=BorkerTopicMetrics, name=FailedFetchRequestsPerSec, topic=TOPICNAME
쓰기 실패 요청 수 kafka.server:type=BorkerTopicMetrics, name=FailedProduceRequestsPerSec, topic=TOPICNAME
입력 메세지 수 kafka.server:type=BorkerTopicMetrics, name=MessageInPerSec, topic=TOPICNAME
전체 읽기 요청 수 kafka.server:type=BorkerTopicMetrics, name=TotalFetchRequestsPerSec, topic=TOPICNAME
전체 쓰기 요청 수 kafka.server:type=BorkerTopicMetrics, name=TotalProduceRequestsPerSec, topic=TOPICNAME

 

 

 

파티션 메트릭

지속적으로 사용하는 관점에서 토픽 메트릭에 비해 덜 유용한 편이나, 일부 제한된 상황에서 유용할 수 있다.
(파티션 크기 측정 및 자원 추적 관리에 유용)

이름 JMX MBean
파티션 크기 kafka.log:type=Log, name=Size, topic=TOPICNAME, partition=2
로그 세그먼트 갯수 kafka.log:type=Log, name=NumLogSegments, topic=TOPICNAME, partition=2
로그 끝 오프셋 kafka.log:type=Log, name=LogEndOffset, topic=TOPICNAME, partition=2
로그 시작 오프셋 kafka.log:type=Log, name=LogStartOffset, topic=TOPICNAME, partition=2

 

 

 

프로듀서 메트릭

이름 JMX MBean
전체 프로듀서 kafka.producer:type=producer-metrics, clinet-id=CLIENTID
메시지 배치의 크기부터 메모리 버퍼 사용에 대한 속성까지 모두 제공

※ 주의 깊게 봐야할 속성
- record-error-rate : 항상 0 이어야 함. 메세지 전송 실패 시 삭제한 값을 지님
- request-latency-avg : 브로커가 produce 요청 받을 때까지 소요된 평균시간(임계값을 찾을것)


메시지 트래픽 측정 관련 속성
- outgoing-byte-rate : 초당 입력되는 메시지의 절대 크기(바이트)
- record-send-rate : 초당 쓰는 메시지 개수 형태로 트래픽을 나타냄
- request-rate : 브로커에게 전송되는 초당 produce 요청 수 제공


메시지 크기 관련 속성
- request-size-avg : 브로커에게 전송되는 produce 요청의 평균 크기(바이트)
- batch-size-avg : 한 메시지 배치의 평균 크기(바이트)
- record-size-avg :  한 레코드의 평균 크기(바이트)
- records-per-request-avg : 하나의 produce 요청에 있는 메시지의 평균 개수
프로듀서 - 브로커 kafka.producer:type=producer-node-metrics, clinet-id=CLIENTID
전체 프로듀서 메트릭에 추가하여 특정 상황의 문제점을 디버깅하는데 유용


가장 유용한 메트릭
- request-latency-avg
- outgoing-byte-rate
프로듀서- 토 kafka.producer:type=producer-topic-metrics, clinet-id=CLIENTID
두 개 이상의 토픽을 사용하는 프로듀서의 경우 프로듀서-브로커 메트릭보다 더 유용함


가장 유용한 메트릭
- record-send-rate
- record-error-rate
- byte-rate

 

 

 

컨슈머 메트릭

이름 JMX MBean
전체 컨슈머 kafka.consumer:type=consumer-metrics, client-id=CLIENTID
Fetch 매니저 kafka.consumer:type=consumer-fetch-manager-metrics, client-id=CLIENTID
컨슈머에서는 Fetch 매니저가 전체 컨슈머 메트릭보다 더 중요한 메트릭들을 들고 있다


가장 유용한 메트릭
- fetch-latency-avg : fetch 요청을 브로커가 받는 데 걸리는 시간
- bytes-consumed-rate : 컨슈머가 처리하는 메시지 트래픽 측정시 사용
- records-consumed-rate : 컨슈머가 처리하는 메시지 트래픽 측정시 사용
- fetch-rate : 컨슈머가 수행하는 초당 fetch 요청 수
- fetch-size-avg : 각 fetch 요청의 평균 크기를 제공
- records-per-request-avg : 각 fetch 요청의 평균 메시지 수
컨슈머 - 토픽 kafka.consumer:type=consumer-fetch-manager-metrics, client-id=CLIENTID, topic=TOPICNAME
컨슈머 - 브로커 kafka.consumer:type=consumer-node-metrics, client-id=CLIENTID, node id=node-BROKERID
가장 유용한 메트릭
- request-latency-avg 
- incoming-byte-rate
- request-rate
컨슈머 - 조정자 kafka.consumer:type=consumer-cordinator-metrics, client-id=CLIENTID

 

 

 

참고: https://s262701-id.tistory.com/126

모니터링 시스템에서 Pull 또는 Push 동작 방식 비교 및 선택을 위한 리서치

 

 

1.  모니터링 시스템 유형

다양한 관점에서 여러 범주로 나눌 수 있는 수백 가지가 넘는 모니터링 시스템 존재

  • 모니터링 대상: 범용(대부분의 모니터링 대상에 적합한 일반적인 모니터링 방법), 전용(Java JMX 시스템, CPU 고온 보호 등 특정 기능에 맞게 사용자 지정)
  • 데이터 수집 방법: Pull(Prometheus, SNMP, JMX), Push(CollectD, Zabbix, InfluxDB)
  • 배포 모드: Coupled(결합형, 모니터링 시스템과 함께 배포), standalone(독립형, 단일 인스턴스 배포), distributed(분산형, 수평적 확장 가능), SaaS(배포가 필요 없음, 많은 상용 회사에서 제공).
  • 데이터 수집 방법: 인터페이스 유형(일부 API를 통해서만 데이터 수집), DSL(PromQL 및 GraphQL 등 포함), SQL(표준 SQL 등).
  • 상업적 속성: 오픈 소스 및 무료(ex: Prometheus 및 InfluxDB standalone 버전), 오픈 소스 상용 유형(ex: InfluxDB 클러스터 버전, Elastic Search X-Pack), closed-source 상용 유형(예: DataDog, Splunk 및 AWS Cloud Watch).
 
 

 

2. Pull or Push?

데이터 수집 방법에 따른 동작 방식 

Pull

모니터링이 필요한 오브젝트에 원격으로 접근해 지표를 능동적으로 획득. 모니터링이 필요한 개체에 원격으로 엑세스할 수 있는 기능 필요

 

Push

모니터링이 필요한 오브젝트가 적극적으로 지표 Push

 

 

모니터링 시스템의 구축 및 선택을 위해서는 이 두 가지 방법의 장단점을 미리 이해하고 구현에 적합한 계획을 선택해야 함

-> 모니터링 시스템의 안정성을 보장하기 위한 후속 유지 관리 비용과 배포 및 O&M 비용 증가 방지

 

 

 

3. Pull과 Push 방식 Overview

 

 

 

4.  원리 및 아키텍처 비교

 

Pull Model Architecture

Pull 모델 데이터 수집의 핵심: Prometheus와 같은 모니터링 백엔드와 함께 배포되는 Pull 모듈

  1. Service discovery system에 연결할 수 있는 기능이 있어야 함 (host service discovery(일반적으로 회사의 CMDB 시스템에 의존), application service discovery(ex: Consul), PaaS service discovery(예: Kubernetes))
  2. 일반적으로 공통 프로토콜을 사용하여 원격 끝(remote end)에서 데이터 가져오며, pull interval, timeout interval, metric filtering, rename 및 간단한 프로세스 기능 제공
  3. application-end SDK는 풀링 기능을 제공하기 위해 고정 포트에 대한 수신 대기 기능 지원
  4. 다양한 미들웨어 및 기타 시스템이 Pull 프로토콜과 호환되지 않으므로, 시스템의 메트릭 가져오기를 지원하고 표준 Pull 인터페이스를 제공하기 위해 Exporter에 해당하는 에이전트 개발 필요

 

Push Model Architecture

비교적 간단한 Push 모델

  1. Push Agent는 다양한 모니터링 대상의 메트릭 데이터 가져와 서버로 푸시하는 기능 지원. 모니터링 시스템과 결합된 방식으로 배포하거나 별도로 배포 가능
  2. ConfigCenter(옵션)는 모니터링 대상, 수집 간격, 메트릭 필터링, 메트릭 처리 및 원격 대상과 같은 중앙 집중식 동적 구성 기능 제공
  3. application-end SDK는 모니터링 백엔드 또는 로컬 에이전트로 데이터 전송 지원(일반적으로 로컬 에이전트는 일련의 백엔드 인터페이스도 구현)

 

요약

Pull 모델의 배포 방식은 미들웨어 및 기타 시스템을 모니터링하기에는 너무 복잡하고 유지 관리 비용 높음

Push 모드는 상대적으로 편리하지만, Metrics 포트를 제공하거나 사전에 배포를 푸시하는데 드는 애플리케이션의 비용 거의 동일

 

 

 

5. Pull's Distributed Solution

 

 

확장성 측면에서 Push 데이터 수집은 기본적으로 분산되어 있고 모니터링 백엔드 기능이 지원되는 경우 제한 없이 수평적으로 확장 가능하나, Pull 확장성 방식은 더 번거로움

  1. Pull 모듈은 모니터링 백엔드에서 분리되어 있으며, Pull은 에이전트로서 별도 배포
  2. Pull 에이전트는 분산 협업을 실현해야 하며, 이를 위한 가장 간단한 방법은 샤딩(ex: service discovery system에서 모니터링되는 머신의 목록을 가져오고, 머신에서 해시 모듈로 작업을 수행한 다음, 샤딩을 통해 어떤 에이전트가 Pull을 담당할지 결정)
  3. Pull 에이전트를 관리하기 위한 configuration center 추가

 

이 분산 방식에 대한 문제점

  1. 단일 지점 병목 현상이 여전히 존재하며 모든 에이전트가 service discovery module 요청 필요
  2. 에이전트 확장 후 모니터링 대상 변경되어 데이터 중복 혹은 누락 가능
 

 

 

6.  모니터링 기능 비교

Monitoring Target Survivability

생존 가능성은 모니터링에 필요한 가장 기본적인 첫 번째 작업

 

Pull

목표 생존 가능성(target survivability) 모니터링이 비교적 간단

Pull 의 중앙에서 목표 지표의 요청 여부 확인 가능하며, 장애 발생 시 네트워크 시간 초과, 피어 연결 거부와 같은 간단한 오류에 대한 알림 수신

 

Push

푸시 모드는 더 번거로움

애플리케이션이 report하지 않을 시 애플리케이션 고장, 네트워크 문제 또는 애플리케이션이 다른 노드로 마이그레이션 가능성 있음

Pull 모듈은 실시간으로 service discovery와 필터 상호 작용을 수행할 수 있지만 Push 모드는 이를 수행할 수 없어 서버가 service discovery와 상호 작용한 후에야만 구체적인 장애 원인 파악 가능

 

Data Completeness Calculation

데이터 완전성의 개념은 대규모 모니터링 시스템에서 매우 중요

(ex:  1,000개의 사본이 있는 트랜잭션 애플리케이션의 QPS 모니터링 시 이 지표를 1,000개의 데이터와 결합 필요. 데이터가 완전하지 않은 경우, QPS가 2% 감소할 때 알람을 트리거하도록 구성되었다고 가정할 때, 20개 이상의 복사본에서 보고된 데이터가 네트워크 변동으로 인해 몇 초 지연되면 잘못된 알람 트리거됨. 따라서 알람을 구성할 때 데이터 완전성 고려 필요)

 

데이터 완전성 계산은 service discovery 모듈에 따라 달라짐

 

Pull

Pull 방식은 데이터를 한 라운드씩 차례로 가져오는 방식이므로, 한 라운드가 끝나면 데이터가 완성

일부 Pull이 실패하더라도 불완전한 데이터의 비율 파악 가능

 

Push

Push 모드에서는 각 에이전트와 애플리케이션이 능동적으로 푸시 수행

각 클라이언트의 푸시 간격과 네트워크 지연 시간은 달라 과거 상황에 따라 서버가 데이터 완전성을 계산해야 하므로 막대한 비용이 발생

 

 

Short Lifecycle/Serverless Application Monitoring

실제 시나리오에서는 short-lifecycle/serverless 애플리케이션이 많으며, 특히 비용 측면에서 많은 수의 작업, 탄력적 인스턴스, 서버리스 애플리케이션 사용 (ex: 렌더링 작업이 도착한 후 탄력적 컴퓨팅 인스턴스가 시작되고 완료되면 즉시 해제. 머신 러닝 학습 작업, 이벤트 기반 서버리스 워크플로우, 정기적으로 실행되는 작업(리소스 정리, 용량 확인, 보안 스캔 등))

 

수명 주기가 짧은 애플리케이션을 관리하기 위해 순수 Pull 시스템은 애플리케이션의 사전 예방적 푸시를 수락한 다음 모니터링 시스템에 풀 포트를 제공하는 중간 계층(예: Prometheus Push Gateway)을 제공하나, 이는 추가적인 중간 계층의 관리 및 O&M 비용으로 이어짐

이 모드는 푸시를 시뮬레이션하는 Pull을 통해 이루어지기 때문에 보고 지연 시간이 길어지고, 즉시 사라지는 이러한 메트릭을 제때 정리해야 함

 

 

Flexibility and Coupling

Flexibility(유연성) 측면에서는 Pull 모드가 다소 유리

Pull 모듈에서 원하는 지표를 구성하고 지표에 대해 간단한 계산과 보조 처리를 할 수 있으나

Push SDK/에이전트에서도 이러한 파라미터를 구성할 수 있고 구성 센터의 도움으로 구성 관리가 간단

Coupling(결합성) 측면에서 Pull모델은 백엔드 간의 결합도가 낮고 백엔드가 이해할 수 있는 인터페이스만 제공하면 됨

어떤 백엔드가 연결되어 있고 백엔드에 어떤 지표가 필요한지 알 필요 없이 분업이 명확합

애플리케이션 개발자는 애플리케이션의 지표만 노출하면 되고, SRE는 이러한 지표 확인 가능 

Push 모델은 결합 정도가 더 높음

애플리케이션이 백엔드 주소와 인증 정보를 구성해야 함

그러나 로컬 push 에이전트에 의존하면 애플리케이션은 로컬 주소만 푸시하면 되므로 큰 비용이 들지 않음

 

 

 

7.  Resource 와 O&M 비용

Resource 비용

전체 비용 측면에서는 두 접근 방식 간에 약간의 차이가 있지만 비용 분포 고려 시

  • Pull 모드의 비용은 주로 모니터링 시스템 단에 집중. 애플리케이션 단에서는 비용 적음
  • Push 모드의 핵심 소비는 푸시 에이전트 단에 집중.  모니터링 시스템 단에서의 비용은 Pull보다 훨씬 적음

O&M 비용

Pull모드의 비용이 더 높음

  • Pull 모드의 O&M을 담당하는 구성 요소에는 다양한 exporters, service discovery, Pull Agent, 모니터링 백엔드 포함
  •  Push 모드는 Push 에이전트, 모니터링 백엔드, configuration center(선택 사항, 일반적으로 모니터링 백엔드와 함께 배포 완료됨)에 대한 O&M만 수행

 

한 가지 주의할 점 - Pull 모드에서는 서버가 클라이언트에 대한 요청을 능동적으로 시작하기 때문에 네트워크에서 애플리케이션 측의 클러스터 간 연결 및 네트워크 보호 ACL을 고려해야 함. Push 모드에 비해 네트워크 연결은 간단하며, 서버가 각 노드가 액세스할 수 있는 도메인 이름/VIP만 제공하면 됨

 

 

 

8.  Pull or Push 선택

Pull 패턴의 대표적인 오픈소스 솔루션: Prometheus 패밀리 솔루션. (Prometheus 확장성이 제한적이기 때문에 패밀리라고 지칭. Prometheus에는 Thanos, VicoriaMetrics, Cortex 등 기술 커뮤니티에 분산된 솔루션이 많이 있음)

Push 패턴의 대표적 솔루션: InfluxDB의 TICK(Telegraf, InfluxDB, Chronograf, Kapacitor)

 

두 솔루션 모두 장단점 존재

클라우드 네이티브라는 배경에서 Prometheus는 CNCF와 Kubernetes의 인기와 함께 번성하기 시작하여 이미 많은 오픈 소스 소프트웨어가 Prometheus 모드에서 Pull 포트를 제공

그러나 많은 시스템이 설계 초기부터 Pull 포트를 제공하는 데 어려움을 겪어왔습니다. 이러한 시스템을 모니터링하는 데는 Push 에이전트 방식이 더 적합

 

사내 실제 시나리오를 기반으로 Pull, Push 방식 선택 필요

ex: 사내 네트워크 클러스터가 매우 복잡하거나 수명주기가 짧은 애플리케이션 사용 시 Push 선택. 모바일 애플리케이션의 경우 Push만 사용 가능. 시스템 자체는 service discovery위해 Consul을 사용하고 Pull 포트 export해 쉽게 구현 가능

 

회사 내 모니터링 시스템의 경우 Pull과 Push 기능을 모두 갖춘 것이 최적의 솔루션

  1. 호스트, 프로세스, 미들웨어 모니터링은 Push 에이전트 사용
  2. Kubernetes 및 기타 직접 노출(exposed)된 Pull 포트는 Pull 모드를 사용
  3. 애플리케이션은 실제 시나리오에 따라 Pull 또는 Push 선택

'기타' 카테고리의 다른 글

Airflow  (0) 2023.11.24

+ Recent posts