Ba cách giám sát Kafka — và tại sao không phải cách nào cũng phù hợp
Trước khi có monitoring đúng nghĩa, mình phải SSH vào từng broker để chạy kafka-consumer-groups.sh kiểm tra lag — cực kỳ tốn thời gian và không thể phát hiện vấn đề sớm. Bây giờ chỉ cần mở dashboard là thấy hết toàn bộ cluster, từ throughput đến consumer lag theo từng group.
Nhưng trước khi đến được đó, mình đã thử qua ba hướng tiếp cận chính và mỗi cái đều có điểm yếu riêng.
Cách 1: AKHQ (Kafka HQ) — GUI thuần túy
AKHQ là web UI cho phép xem topic, consumer group, broker status. Dễ cài, trực quan, phù hợp để khám phá cluster. Nhưng điểm yếu lớn: không có time-series, không alert, không tích hợp được vào hệ thống alerting chung. Khi có sự cố lúc 3 giờ sáng, không ai mở AKHQ để check thủ công.
Cách 2: Burrow (của LinkedIn)
Burrow là tool chuyên theo dõi consumer lag với thuật toán đánh giá “consumer health” khá thông minh — không chỉ nhìn lag tức thời mà còn phân tích xu hướng. Tuy nhiên cài đặt phức tạp, cần thêm adapter để đưa metrics vào Prometheus, và cộng đồng ít active hơn từ khoảng 2022.
Cách 3: JMX Exporter + kafka-exporter kết hợp Prometheus
Đây là stack mình đang dùng cho production. Hai exporter bổ sung cho nhau: JMX Exporter lấy metrics chi tiết từ Kafka JMX (broker-level: throughput, request rate, replication lag), còn kafka-exporter lấy metrics consumer group và topic (lag, offset, partition count). Cả hai đều expose endpoint tương thích Prometheus.
Phân tích ưu nhược điểm để chọn đúng
Sau khi thử cả ba, đây là bảng so sánh thực tế:
- AKHQ: Cài nhanh, UI đẹp — nhưng không alert, không time-series, không thể tích hợp vào observability stack chung.
- Burrow: Consumer health thông minh hơn — nhưng phức tạp khi triển khai, cần adapter riêng, ít được maintain.
- JMX Exporter + kafka-exporter: Đầy đủ metrics, tích hợp Prometheus/Grafana/Alertmanager — nhưng cần cấu hình nhiều bước hơn ban đầu.
Lý do mình chọn stack thứ ba: đã có Prometheus chạy sẵn cho toàn bộ infrastructure. Grafana dashboard cho phép correlate Kafka metrics với server metrics (CPU, memory, disk I/O) — rất hữu ích khi debug performance issue mà không biết bottleneck nằm ở Kafka hay ở phía consumer service.
Chọn stack phù hợp với từng tình huống
- Team nhỏ, ít broker, cần visibility nhanh: AKHQ là đủ để bắt đầu.
- Muốn consumer lag monitoring chuyên sâu, không cần alerting phức tạp: Burrow + Burrow-exporter.
- Production, cần alerting, tích hợp với observability stack hiện có: JMX Exporter + kafka-exporter + Prometheus + Grafana.
Hướng dẫn triển khai: JMX Exporter + kafka-exporter
Bước 1: Cấu hình JMX Exporter trên Kafka Broker
JMX Exporter chạy như một Java agent gắn vào process Kafka. Tải agent jar về:
wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.20.0/jmx_prometheus_javaagent-0.20.0.jar \
-O /opt/kafka/libs/jmx_prometheus_javaagent.jar
Tạo file cấu hình /opt/kafka/config/kafka-jmx-exporter.yaml với các metrics quan trọng nhất:
startDelaySeconds: 0
ssl: false
lowercaseOutputName: true
lowercaseOutputLabelNames: true
rules:
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=MessagesInPerSec><>OneMinuteRate'
name: kafka_broker_messages_in_per_sec
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=BytesInPerSec><>OneMinuteRate'
name: kafka_broker_bytes_in_per_sec
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=BytesOutPerSec><>OneMinuteRate'
name: kafka_broker_bytes_out_per_sec
- pattern: 'kafka.server<type=ReplicaManager, name=UnderReplicatedPartitions><>Value'
name: kafka_broker_under_replicated_partitions
- pattern: 'kafka.controller<type=KafkaController, name=ActiveControllerCount><>Value'
name: kafka_broker_active_controller_count
Thêm JVM flag vào file khởi động Kafka — thường qua biến KAFKA_OPTS:
export KAFKA_OPTS="-javaagent:/opt/kafka/libs/jmx_prometheus_javaagent.jar=7071:/opt/kafka/config/kafka-jmx-exporter.yaml"
Sau khi restart broker, kiểm tra endpoint:
curl http://localhost:7071/metrics | grep kafka_broker
Bước 2: Triển khai kafka-exporter
kafka-exporter là binary Go chạy độc lập, connect vào Kafka cluster để lấy consumer group và topic metrics:
docker run -d --name kafka-exporter \
-p 9308:9308 \
danielqsj/kafka-exporter \
--kafka.server=kafka-broker-1:9092 \
--kafka.server=kafka-broker-2:9092 \
--kafka.server=kafka-broker-3:9092
Kiểm tra metrics consumer lag được expose chưa:
curl http://localhost:9308/metrics | grep kafka_consumergroup_lag
Bước 3: Cấu hình Prometheus scrape
Thêm hai job vào prometheus.yml:
scrape_configs:
- job_name: 'kafka-jmx'
static_configs:
- targets:
- 'kafka-broker-1:7071'
- 'kafka-broker-2:7071'
- 'kafka-broker-3:7071'
scrape_interval: 30s
- job_name: 'kafka-exporter'
static_configs:
- targets: ['kafka-exporter:9308']
scrape_interval: 15s
Lý do scrape interval khác nhau: JMX metrics thay đổi chậm, 30s là đủ. kafka-exporter cần 15s để bắt được lag spike sớm trước khi vượt ngưỡng alert.
Bước 4: Import Grafana Dashboard
Có hai dashboard từ Grafana.com phù hợp nhất:
- Dashboard ID 7589 — Kafka Overview (dùng kafka-exporter metrics, focus vào consumer lag)
- Dashboard ID 721 — Kafka Metrics (dùng JMX metrics, focus vào broker internals)
Import bằng cách: Grafana → Dashboards → Import → nhập ID → chọn Prometheus datasource.
Các metrics quan trọng nhất và cách viết PromQL
Consumer Lag — metric số 1 cần có alert
Consumer lag là số message producer đã ghi vào partition nhưng consumer chưa xử lý. Lag tăng liên tục có nghĩa consumer không theo kịp producer — đây là dấu hiệu đầu tiên của sự cố pipeline.
# Tổng lag của một consumer group theo từng topic
sum(kafka_consumergroup_lag{consumergroup="my-app-group"}) by (topic)
# Alert khi lag vượt ngưỡng (tùy SLA của từng group)
alert: KafkaConsumerLagHigh
expr: kafka_consumergroup_lag{consumergroup="payment-consumer"} > 5000
for: 5m
Broker Throughput
# Messages per second vào toàn cluster
sum(kafka_broker_messages_in_per_sec) by (instance)
# Bytes in/out để monitor bandwidth
sum(kafka_broker_bytes_in_per_sec) by (instance)
sum(kafka_broker_bytes_out_per_sec) by (instance)
Topic Health — Under-replicated Partitions
Đây là metric mình đặt alert priority cao nhất. Khi UnderReplicatedPartitions > 0, có nghĩa một số replica đang không đồng bộ kịp với leader — nếu broker chết lúc này, có nguy cơ mất message.
# Alert ngay khi có under-replicated partition — không cần for: delay
alert: KafkaUnderReplicatedPartitions
expr: kafka_broker_under_replicated_partitions > 0
# Active controller phải luôn bằng đúng 1 trong cả cluster
alert: KafkaControllerAbnormal
expr: sum(kafka_broker_active_controller_count) != 1
Mẹo thực tế từ môi trường production
- Tách alert consumer lag theo group: đừng alert tổng lag cả cluster — mỗi consumer group có throughput và SLA khác nhau. Group xử lý payment cần ngưỡng 1.000, group analytics có thể chịu được 100.000.
- Thêm Grafana variable: tạo variable cho
consumergroupvàtopictrong dashboard để filter nhanh khi troubleshoot, thay vì phải sửa query. - Kafka Exporter với SASL: nếu cluster bật authentication, thêm flag
--sasl.enabled --sasl.username --sasl.password --sasl.mechanismkhi chạy kafka-exporter. - Network partition alert: theo dõi thêm metric
kafka_controller_offline_partitions_count— partition offline thường báo hiệu network issue giữa các broker.
Từ khi setup xong stack này, khi có alert “consumer lag tăng đột biến”, team mình correlate ngay trên cùng một Grafana dashboard: CPU/memory của consumer service, network throughput của broker, disk I/O. Thay vì phải mở 5 terminal SSH vào 5 server khác nhau, toàn bộ thông tin nằm cùng một màn hình — thời gian debug giảm từ 20 phút xuống còn 3-4 phút.

