监控有助于推动生产力,提高服务的可用性。Apache Kafka也不例外。随着Apache Kafka越来越受欢迎,并成为微服务架构中分布式消息传递的事实标准,对于DevOps工程师来说,了解一些关键指标是非常重要的,比如 - 消费者滞后?复制不足的分区?或者你的Kafka集群坏了吗? - 以便拥有一个高度可靠和可用的Kafka集群,并保持对数据和应用健康的关注。
监控Apache Kafka的工具
有很多工具可以用来监控Apache Kafka,包括。
- LinkedIn Burrow
- 雅虎Kafka管理器
- KafDrop
- Confluent控制中心 - 如果你使用Confluent Kafka和其他许多工具的话
我们还可以使用Java管理扩展(JMX)与流行的JMX客户端(如Prometheus、Telegraf等)来监控Apache Kafka。
在这篇文章中,我将通过使用Telegraf和Grafana监控部署在Azure云上的Apache Kafka。 请注意,Azure也提供了使用HDInsight Kafka的管理Kafka。 但如果你想建立一个与云无关的Apache Kafka集群,那么为该集群提供一个监控解决方案是很重要的。在这篇文章中,我将指导你安装、设置和运行使用Telegraf代理的监控解决方案,以及Grafana、Jolokia代理、Azure Monitor。因此,我们会在Grafana这边的仪表盘上看到系统、Kafka Broker、Kafka Consumer和Kafka Producer的指标。
让我们来看看这些组件中的一些。
Jolokia代理
Jolokia是一个基于JMX-HTTP代理的方法,支持许多平台。除了基本的JMX操作外,它还通过批量请求和细粒度的安全策略等独特的功能增强了JMX远程。
Telegraf
Telegraf是一个轻量级的服务器进程,能够收集、处理和汇总指标。Telegraf是一个插件驱动的服务器代理,用于收集和发送来自数据库、系统和物联网传感器的指标和事件。
格拉法纳
Grafana是一个流行的全功能的开源前台仪表盘解决方案。这是一个可视化工具,旨在与各种数据源如Graphite、InfluxDB、Elasticsearch等合作。这个解决方案可以为用户快速、轻松地开发仪表盘。
Azure监控器
Azure监控器从各种企业内部和Azure来源收集监控遥测数据。Azure监控器允许收集细化的性能和利用率数据、活动和诊断日志,以及来自Azure资源的通知。
构建监控系统架构
这是一个高层次的架构图,为Azure虚拟机上托管的Apache Kafka构建一个监控解决方案。
在这里,我创建了两个子网--一个用于Kafka集群,另一个用于设置监控解决方案,以隔离访问责任。当你在一个单独的子网中设置监控解决方案时,请确保你已经更新了子网各自NSG中的入站/出站规则,以便进行适当的通信。监控子网将有一个虚拟机来托管Grafana和Telegraf代理。
为了处理HA,你需要创建2个VM,并使用Azure应用网关来平衡负载。让我们来看看这个设置。
1.安装Jolokia
- 从这里下载最新版本的Jolokia JVM-Agent。( jolokia-jvm-1.7.1-agent.jar版本是目前最新的)
- 将jolokia-jvm-1.7.1-agent.jar保存在Kafka服务器的/opt/kafka/libs或任何位置。
- 配置Kafka以使用Jolokia。
在kafka-server-start.sh中添加以下片段。
export JMX_PORT=9999 export RMI_HOSTNAME=<KAFKA_SERVER_IP_ADDRESS> export KAFKA_JMX_OPTS="-javaagent:/opt/kafka/libs/jolokia-agent.jar=port=8778,host=$RMI_HOSTNAME -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=$RMI_HOSTNAME -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT"
- 重新启动Kafka服务。
- 通过运行验证你可以访问端口8778的Jolokia。
Curl -http://KAFKA_SERVER_IP_ADDRESS:8778/jolokia/version
2.安装Telegraf代理
这个集成使用Jolokia的Telegraf输入插件来通过JMX获得Kafka指标。
你可以从这里下载最新的Telegraf代理。
3. 配置Jolokia输入插件
在/etc/telegraf/telegraf.d
,创建一个名为jolokia-kafka.conf
的文件,并输入以下内容。
注意:将KAFKA_SERVER_IP_ADDRESS替换为Kafka服务器IP地址。
## Read JMX metrics through Jolokia
[[inputs.jolokia2_agent]]
## An array of Kafka servers URI to gather stats.
urls = ["http://KAFKA_SERVER_IP_ADDRESS:8778/jolokia"]
name_prefix = "kafka."
## List of metrics collected on above servers
[[inputs.jolokia2_agent.metric]]
name = "heap_memory_usage"
mbean = "java.lang:type=Memory"
paths = ["HeapMemoryUsage"]
## This collects thread counts metrics.
[[inputs.jolokia2_agent.metric]]
name = "thread_count"
mbean = "java.lang:type=Threading"
paths = ["TotalStartedThreadCount","ThreadCount","DaemonThreadCount","PeakThreadCount"]
## This collects garbage collection metrics.
[[inputs.jolokia2_agent.metric]]
name = "garbage_collector"
mbean = "java.lang:type=GarbageCollector,name=*"
paths = ["CollectionCount","CollectionTime"]
tag_keys = ["name"]
# Kafka Server Broker Topic Metrics
[[inputs.jolokia2_agent.metric]]
name = "server_brokertopics_messagesinpersec"
mbean = "kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec"
[[inputs.jolokia2_agent.metric]]
name = "server_brokertopics_bytesinpersec"
mbean = "kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec"
[[inputs.jolokia2_agent.metric]]
name = "server_brokertopics_bytesoutpersec"
mbean = "kafka.server:type=BrokerTopicMetrics,name=BytesOutPerSec"
# Kafka Server Request Handler Metrics
[[inputs.jolokia2_agent.metric]]
name = "server_requesthandler_avgidlepct"
mbean = "kafka.server:name=RequestHandlerAvgIdlePercent,type=KafkaRequestHandlerPool"
# Kafka Server Delayed Operation Purgatory Metrics
[[inputs.jolokia2_agent.metric]]
name = "server_delayedoperationpugatory_fetch"
mbean = "kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize,delayedOperation=Fetch"
[[inputs.jolokia2_agent.metric]]
name = "server_delayedoperationpugatory_produce"
mbean = "kafka.server:type=DelayedOperationPurgatory,name=PurgatorySize,delayedOperation=Produce"
# Kafka Server Replica Fetcher Manager Metrics
[[inputs.jolokia2_agent.metric]]
name = "server_replicafetchmanager.maxlag"
mbean = "kafka.server:type=ReplicaFetcherManager,name=MaxLag,clientId=Replica"
# Kafka Server Replica Manager Metrics
[[inputs.jolokia2_agent.metric]]
name = "server_replicamanager_underreplicated"
mbean = "kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions"
[[inputs.jolokia2_agent.metric]]
name = "server_replicamanager_partitioncount"
mbean = "kafka.server:type=ReplicaManager,name=PartitionCount"
[[inputs.jolokia2_agent.metric]]
name = "server_replicamanager_leadercount"
mbean = "kafka.server:type=ReplicaManager,name=LeaderCount"
[[inputs.jolokia2_agent.metric]]
name = "server_replicamanager_isrshrinkspersec"
mbean = "kafka.server:type=ReplicaManager,name=IsrShrinksPerSec"
[[inputs.jolokia2_agent.metric]]
name = "server_replicamanager_isrexpandspersec"
mbean = "kafka.server:type=ReplicaManager,name=IsrExpandsPerSec"
# Kafka Network Request Metrics
[[inputs.jolokia2_agent.metric]]
name = "network_requestmetrics_requests_fetch_consumer"
mbean = "kafka.network:type=RequestMetrics,name=RequestsPerSec,request=FetchConsumer"
[[inputs.jolokia2_agent.metric]]
name = "network_requestmetrics_requests_fetch_follower"
mbean = "kafka.network:type=RequestMetrics,name=RequestsPerSec,request=FetchFollower"
[[inputs.jolokia2_agent.metric]]
name = "network_requestmetrics_requests_produce"
mbean = "kafka.network:type=RequestMetrics,name=RequestsPerSec,request=Produce"
[[inputs.jolokia2_agent.metric]]
name = "network_requestmetrics_totaltime_fetch_consumer"
mbean = "kafka.network:type=RequestMetrics,name=TotalTimeMs,request=FetchConsumer"
[[inputs.jolokia2_agent.metric]]
name = "network_requestmetrics_totaltime_fetch_follower"
mbean = "kafka.network:type=RequestMetrics,name=TotalTimeMs,request=FetchFollower"
[[inputs.jolokia2_agent.metric]]
name = "network_requestmetrics_totaltime_produce"
mbean = "kafka.network:type=RequestMetrics,name=TotalTimeMs,request=Produce"
# Kafka Network Processor Metrics
[[inputs.jolokia2_agent.metric]]
name = "network_processor_avgidlepct"
mbean = "kafka.network:name=NetworkProcessorAvgIdlePercent,type=SocketServer"
# Kafka Controller Metrics
[[inputs.jolokia2_agent.metric]]
name = "controller_activecontrollers"
mbean = "kafka.controller:type=KafkaController,name=ActiveControllerCount"
[[inputs.jolokia2_agent.metric]]
name = "controller_offlinepartitions"
mbean = "kafka.controller:type=KafkaController,name=OfflinePartitionsCount"
[[inputs.jolokia2_agent.metric]]
name = "controller_stats_leaderelectionrateandtime"
mbean = "kafka.controller:type=ControllerStats,name=LeaderElectionRateAndTimeMs"
[[inputs.jolokia2_agent.metric]]
name = "controller_stats_uncleanleaderelections"
mbean = "kafka.controller:type=ControllerStats,name=UncleanLeaderElectionsPerSec"
# Zookeeper Metrics
[[inputs.jolokia2_agent.metric]]
name = "zookeeper_disconnects"
mbean = "kafka.server:type=SessionExpireListener,name=ZooKeeperDisconnectsPerSec"
paths = ["Count","OneMinuteRate","FiveMinuteRate","FifteenMinuteRate","MeanRate"]
[[inputs.jolokia2_agent.metric]]
name = "zookeeper_sync_connects"
mbean = "kafka.server:type=SessionExpireListener,name=ZooKeeperSyncConnectsPerSec"
paths = ["Count","OneMinuteRate","FiveMinuteRate","FifteenMinuteRate","MeanRate"]
[[inputs.jolokia2_agent.metric]]
name = "zookeeper_auth_failures"
mbean = "kafka.server:type=SessionExpireListener,name=ZooKeeperAuthFailuresPerSec"
paths = ["Count","OneMinuteRate","FiveMinuteRate","FifteenMinuteRate","MeanRate"]
[[inputs.jolokia2_agent.metric]]
name = "zookeeper_readonly_connects"
mbean = "kafka.server:type=SessionExpireListener,name=ZooKeeperReadOnlyConnectsPerSec"
paths = ["Count","OneMinuteRate","FiveMinuteRate","FifteenMinuteRate","MeanRate"]
[[inputs.jolokia2_agent.metric]]
name = "zookeeper_authentications"
mbean = "kafka.server:type=SessionExpireListener,name=ZooKeeperSaslAuthenticationsPerSec"
paths = ["Count","OneMinuteRate","FiveMinuteRate","FifteenMinuteRate","MeanRate"]
[[inputs.jolokia2_agent.metric]]
name = "zookeeper_expires"
mbean = "kafka.server:type=SessionExpireListener,name=ZooKeeperExpiresPerSec"
paths = ["Count","OneMinuteRate","FiveMinuteRate","FifteenMinuteRate","MeanRate"]
将上述指标扩展到所有的JMX指标,以便对Apache Kafka有一个完整的了解。你可以参考Apache Kafka文档中的JMX端点和度量。
4. 配置Azure Monitor输出插件
[[outputs.azure_monitor]]
## Timeout for HTTP writes.
# timeout = "20s"
## Set the namespace prefix, defaults to "Telegraf/<input-name>".
namespace_prefix = "kafka/"
## Azure Monitor doesn't have a string value type, so convert string
## fields to dimensions (a.k.a. tags) if enabled. Azure Monitor allows
## a maximum of 10 dimensions so Telegraf will only send the first 10
## alphanumeric dimensions.
# strings_as_dimensions = false
## Both region and resource_id must be set or be available via the
## Instance Metadata service on Azure Virtual Machines.
#
## Azure Region to publish metrics against.
## ex: region = "southcentralus"
# region = ""
#
## The Azure Resource ID against which metric will be logged, e.g.
## ex: resource_id = "/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.Compute/virtualMachines/<vm_name>"
# resource_id = ""
## Optionally, if in Azure US Government, China, or other sovereign
## cloud environment, set the appropriate REST endpoint for receiving
## metrics. (Note: region may be unused in this context)
# endpoint_url = "https://monitoring.core.usgovcloudapi.net"
5.重新启动Telegraf
执行 sudo service telegraf重启来重新启动Telegraf代理。
6.创建服务主体/Azure管理身份
为了从Grafana连接Azure Monitor,我们需要在Grafana安装的虚拟机上启用管理身份,使用管理身份在Grafana中配置Azure Monitor。这将简化数据源的配置,需要对数据源进行安全认证,而不必通过Azure AD应用注册为每个数据源手动配置凭证。
你也可以在Azure AD中创建一个应用注册和服务主体,以验证数据源,并在Grafana配置中配置服务主体。 确保你为服务委托人提供贡献者角色/查看者角色。
7.安装Grafana
关于在支持的操作系统上安装Grafana的各种选项,请参考这里。Grafana有OSS版和企业版,根据你的需要选择。
8**.将Azure Monitor配置为Grafana的数据源**
要为Grafana启用管理身份,请在Grafana服务器配置的[azure]部分设置 managed_identity_enabled标志。
[azure]
managed_identity_enabled = true
然后,在Azure Monitor数据源配置中,将认证设置为管理身份。该数据源将使用管理身份来验证Azure监控指标、日志和Azure资源图。关于使用管理身份或使用服务委托人的数据源配置,请参考本文档。
9. 重启Grafana
配置完成后重启Grafana服务器,现在你应该可以访问Grafana用户界面了。 你也可以通过将Grafana与Azure AD集成,将Grafana的访问权限制在一组用户中。你可以参考这里的文档。
10. 为Kafka关键指标创建监控仪表板
在Grafana中创建关键指标仪表盘,如CPU使用率、JVM使用率、在GC中花费的时间、每个主题中的消息、消费者滞后等。
注意:如果你想在AWS或GCP上建立Apache Kafka集群,我们也可以在其他云供应商如AWS和GCP上使用上述解决方案。Telegraf代理有输出插件支持AWS CloudWatch和GCP云监控(以前被称为Stackdriver)。因此,使用这个插件,你可以将指标数据存储在公共云提供的本地监控解决方案中,并使用Grafana,它对GCP和AWS监控解决方案都有本地支持。