Java web应用性能分析之【系统监控工具prometheus】_javaweb服务器性能监控工具-CSDN博客
Java web应用性能分析之【prometheus+Grafana监控springboot服务和服务器监控】_grafana 导入 prometheus-CSDN博客
因为篇幅原因,前面没有详细说明Prometheus的监控指标,这里就拿出来单独说明。主要是从Exporter对linux服务器、k8s节点、以及常用的exporter、node进行说明,这些都是通用的监控。后面会单独说明自定义监控指标,自定义的主要是结合业务特色进行监控。
Prometheus组件构成简介
Prometheus是一个开源的监控和告警工具包,其常用的组件主要包括以下几个部分:
- Prometheus Server
- 功能:Prometheus Server是Prometheus的核心组件,负责定时从被监控组件(如Kubernetes、Docker、主机等)中拉取(pull)数据,并将其存储在本地的时间序列数据库中。它还提供了灵活的查询语言(PromQL)来查询和分析这些数据。
- 数据存储:Prometheus Server本身就是一个时序数据库,将采集到的监控数据按照时间序列的方式存储在本地磁盘当中。
- 服务发现:Prometheus Server支持多种服务发现机制,如文件、DNS、Consul、Kubernetes等,可以动态地管理监控目标。
- Web UI:Prometheus Server内置了一个Web UI,通过这个UI可以直接通过PromQL实现数据的查询以及可视化。
- Exporters
- 功能:Exporters是一组工具,用于将那些本身不支持直接暴露监控指标的应用程序或服务的指标数据转换为Prometheus可以抓取的格式。
- 常见类型:例如,Node Exporter用于收集机器级别的指标(如CPU、内存、磁盘使用情况等),而MySQL Exporter则用于收集MySQL数据库的指标数据。其他常见的Exporter还包括Blackbox Exporter(用于网络探测)、Process Exporter(用于监控进程状态)等。
- Client Libraries
- 功能:Client Libraries提供了在应用程序中实现自定义指标的方式。这些库支持多种编程语言(如Go、Java、Python等),使得开发者可以轻松地在自己的应用中添加和暴露自定义的Prometheus指标。
- 使用场景:当开发者需要在自己的应用程序中实现更细粒度的监控时,可以使用Client Libraries来定义和暴露自定义的监控指标。
- Pushgateway(生产环境必须组件)
- 功能:Pushgateway是一个可选的组件(生产环境必须组件,很多时候服务器上监控网络),用于接收由短期作业或批处理作业生成的指标数据,并允许Prometheus Server从Pushgateway中拉取这些数据。
- 使用场景:当某些作业或服务由于网络限制或其他原因无法直接被Prometd heus Server访问时,可以使用Pushgateway作为中间缓存he 层来收集和转发这些指标数据。
- Alertmanager
- 功能:Alertmanager是Prometheus的告警管理工具,负责处理由Prometheus规则生成的警报,并将其发送给指定的接收者(如邮件、PagerDuty等)。
- 告警处理:Alertmanager支持对告警进行去重、分组和路由配置,以便将不同类型的告警发送给不同的接收者。此外,它还支持告警的沉默和抑制功能,以减少不必要的告警噪音。
- Grafana(可选组件)
- 功能:Grafana是一个开源的数据可视化和监控平台,可以与Prometheus无缝集成,提供丰富的图表和仪表盘来展示Prometheus存储的监控数据。
- 使用场景:当用户需要更直观地查看和分析监控数据时,可以使用Grafana来创建自定义的图表和仪表盘。Grafana支持多种数据源和插件扩展,可以满足各种复杂的监控需求。
这些组件共同构成了Prometheus的完整监控和告警解决方案,使得用户可以方便地收集、存储、查询和处理各种监控数据。
Prometheus指标类型
对于由许多组件组成的现代动态系统,云原生基金会(CNCF)中的项目Prometheus已经成为最受欢迎的开源监控软件,并有效地成为指标监控的行业标准。Prometheus定义了一个度量说明格式和一个远程写入协议,社区和许多供应商都采用这个协议来说明和收集度量成为事实上的标准。OpenMetrics是另一个CNCF项目,它建立在Prometheus导出格式的基础上,为收集度量标准提供了一个与厂商无关的标准化模型,旨在成为互联网工程任务组(IEFT)的一部分。
Prometheus四种主要的指标类型包括Counter、Gauge、Histogram和Summary,以及相应的PromQL实例如下:(需要注意的是,以上PromQL实例仅供参考,实际使用时需要根据具体的指标名称、标签和查询需求进行调整。同时,由于Prometheus查询语言的复杂性和多样性,还有很多其他的查询方式和技巧可以探索和学习。)
Prometheus使用拉取模型来收集这些指标;也就是说,Prometheus主动抓取暴露指标的HTTP端点。这些端点可以是由被监控的组件自然暴露,也可以通过社区建立的数百个Prometheus导出器之一暴露出来。Prometheus提供了不同编程语言的客户端库,你可以用它来监控你的代码。
由于服务发现机制和集群内的共享网络访问,拉取模型在监控Kubernetes集群时效果很好,但用Prometheus监控动态的虚拟机集群、AWS Fargate容器或Lambda函数就比较困难了。
为什么呢?主要原因是交易确定要抓取的指标端点,而且对这些端点的访问可能受到网络安全策略的限制。为了解决其中的一些问题,社区在2021年底发布了Prometheus Agent Mode,它只收集指标并使用远程写入协议将其发送到监控后端。
Prometheus可以抓取Prometheus暴露格式和OpenMetrics格式的指标。在这两种情况下,指标通过HTTP接口暴露,使用简单的基于文本的格式(更常用和广泛支持)或更有效和强大的Protobuf格式。文本格式的一大优势是它的可读性,这意味着你可以在浏览器中打开它或使用像curl这样的工具来检索当前暴露的指标集。
Prometheus使用一个非常简单的指标模型,有四种指标类型,只在客户端SDK中支持。所有的指标类型都是用一种数据类型或由多个单一数据类型的组合在暴露格式中表示。这个数据类型包括一个指标名称、一组标签和一个浮点数。时间戳是由监控后端(例如Prometheus)或代理在抓取指标时添加的。
指标名称和标签集的每个唯一组合定义了一条时间序列,而每个时间戳和浮点数定义了一个系列中的样本(即一个数据点)。
-
Counter(计数器)
- 作用:只增不减的计数器,常用于记录请求次数、任务完成数、错误发生次数等。重启进程后,计数会被重置。
- PromQL实例:假设我们有一个HTTP请求次数的Counter类型指标
http_requests_total
,我们想要查询最近一小时内增长最快的10个HTTP请求路径:
-
promql`topk(10, delta(http_requests_total[1h]))`
Counter类型指标被用于单调增加的测量结果。因此它们总是累积的数值,值只能上升。唯一的例外是Counter重启,在这种情况下,它的值会被重置为零。
Counter的实际值通常本身并不十分有用。一个计数器的值经常被用来计算两个时间戳之间的delta或者随时间变化的速率。
例如,Counter的一个典型用例是记录API调用次数,这是一个总是会增加的测量值。
# HELP http_requests_total Total number of http api requests
# TYPE http_requests_total counter
http_requests_total{api="add_product"} 4633433
指标名称是http_requests_total,它有一个名为api的标签,值为add_product,Counter的值为4633433。这意味着自从上次服务启动或Counter重置以来,add_product的API已经被调用了4633433次。按照惯例,Counter类型的指标通常以_total为后缀。
这个绝对数字并没有给我们提供多少信息,但当与PromQL的rate函数(或其他监控后端的类似函数)一起使用时,它可以帮助我们了解该API每秒收到的请求数。下面的PromQL查询计算了过去5分钟内每秒的平均请求数。
rate(http_requests_total{api="add_product"}[5m])
为了计算一段时期内的绝对变化,我们将使用delta函数,在PromQL中称为increate():
increase(http_requests_total{api="add_product"}[5m])
这将返回过去5分钟内的总请求数,这相当于用每秒的速率乘以间隔时间的秒数(在我们的例子中是5分钟):
rate(http_requests_total{api="add_product"}[5m]) * 5 * 60
其他你可能会使用Counter类型指标的例子:测量电子商务网站的订单数量,在网络接口上发送和接收的字节数,或者应用程序中的错误数量。如果它是一个会一直上升的指标,那么就使用一个Counter。
下面是一个例子,说明如何使用Prometheus客户端库在Python中创建和增加一个计数器指标:
from prometheus_client import Counter
api_requests_counter = Counter(
'http_requests_total',
'Total number of http api requests',
['api']
)
api_requests_counter.labels(api='add_product').inc()
需要注意的是,由于Counter可以被重置为零,你要确保你用来存储和查询指标的后端能够支持这种情况,并且在Counter重启的情况下仍然提供准确的结果。Prometheus和兼容PromQL的Prometheus远程存储系统,如Promscale,可以正确处理Counter重启。
-
Gauge(仪表)
- 作用:反映系统的当前状态,样本数据可增可减。常用于表示CPU使用率、内存使用率、磁盘空间使用率等。
- PromQL实例:如果我们想要查询当前系统中CPU使用率最高的前三个节点:
promql`topk(3, 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100))`
Gauge指标用于可以任意增加或减少的测量。这是你可能更熟悉的指标类型,因为即使没有经过额外处理的实际值也是有意义的,它们经常被使用到。例如,测量温度、CPU和内存使用的指标,或者队列的大小都是Gauge。
例如,为了测量一台主机的内存使用情况,我们可以使用一个Gauge指标,比如:
# HELP node_memory_used_bytes Total memory used in the node in bytes
# TYPE node_memory_used_bytes gauge
node_memory_used_bytes{hostname="host1.domain.com"} 943348382
上面的指标表明,在测量时,节点host1.domain.com使用的内存约为900 MB。该指标的值是有意义的,不需要任何额外的计算,因为它告诉我们该节点上消耗了多少内存。
与使用Counter指标时不同,rate和delta函数对Gauge没有意义。然而,计算特定时间序列的平均数、最大值、最小值或百分比的函数经常与Gauge一起使用。在Prometheus中,这些函数的名称是avg_over_time、max_over_time、min_over_time和quantile_over_time。要计算过去10分钟内在host1.domain.com上使用的平均内存,你可以这样做:
avg_over_time(node_memory_used_bytes{hostname="host1.domain.com"}[10m])
要使用Prometheus客户端库在Python中创建一个Gauge指标,你可以这样做:
from prometheus_client import Gauge
memory_used = Gauge(
'node_memory_used_bytes',
'Total memory used in the node in bytes',
['hostname']
)
memory_used.labels(hostname='host1.domain.com').set(943348382)
-
Histogram(直方图)
- 作用:表示样本数据的分布情况,通常用于统计请求的耗时、大小等。它提供了多个时间序列,包括_sum(总和)、_count(总数)以及多个_bucket(分桶统计)。
- PromQL实例:假设我们有一个请求耗时的Histogram类型指标
http_request_duration_seconds
,我们想要查询请求耗时在0.5秒到1秒之间的请求次数:
promql`histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{le="1"}[5m])) by (le)) - histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{le="0.5"}[5m])) by (le))`
注意:这个查询可能并不准确,因为Histogram类型不直接提供区间内的计数,而是通过累计的方式来表示分布。在实际应用中,我们更常用的是查询某个分位数的请求耗时,如95%的请求耗时在多少以内。
Histogram指标对于表示测量的分布很有用。它们经常被用来测量请求持续时间或响应大小。
直方图将整个测量范围划分为一组区间,称为桶,并计算每个桶中有多少测量值。
一个直方图指标包括几个项目:
-
一个包含测量次数的Counter。指标名称使用_count后缀。
-
一个包含所有测量值之和的Counter。指标名称使用_sum后缀。
-
直方图桶被暴露为一系列的Counter,使用指标名称的后缀_bucket和表示桶的上限的le label。Prometheus中的桶是包含桶的边界的,即一个上限为N的桶(即le label)包括所有数值小于或等于N的数据点。
例如,测量运行在host1.domain.com实例上的add_productAPI端点实例的响应时间的Histogram指标可以表示为:
# HELP http_request_duration_seconds Api requests response time in seconds
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_sum{api="add_product" instance="host1.domain.com"} 8953.332
http_request_duration_seconds_count{api="add_product" instance="host1.domain.com"} 27892
http_request_duration_seconds_bucket{api="add_product" instance="host1.domain.com" le="0"}
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="0.01"} 0
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="0.025"} 8
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="0.05"} 1672
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="0.1"} 8954
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="0.25"} 14251
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="0.5"} 24101
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="1"} 26351
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="2.5"} 27534
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="5"} 27814
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="10"} 27881
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="25"} 27890
http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com", le="+Inf"} 27892
上面的例子包括sum、counter和12个桶。sum和counter可以用来计算一个测量值随时间变化的平均值。在PromQL中,过去5分钟的平均请求响应时间可以通过如下方式计算得到。
rate(http_request_duration_seconds_sum{api="add_product", instance="host1.domain.com"}[5m]) / rate(http_request_duration_seconds_count{api="add_product", instance="host1.domain.com"}[5m])
它也可以被用来计算各时间序列的平均数。下面的PromQL查询将计算出所有API和实例在过去5分钟内的平均请求响应时间。
sum(rate(http_request_duration_seconds_sum[5m])) / sum(rate(http_request_duration_seconds_count[5m]))
利用Histogram,你可以在查询时计算单个时间序列以及多个时间序列的百分位。在PromQL中,我们将使用histogram_quantile函数。Prometheus使用分位数而不是百分位数。它们本质上是一样的,但是以0到1的比例表示的,而百分位数是以0到100的比例表示的。要计算在host1.domain.com上运行的add_product API响应时间的第99百分位数(0.99四分位数),你可以使用以下查询。
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket{api="add_product", instance="host1.domain.com"}[5m]))
Histograms的一大优势是可以进行汇总。下面的查询返回所有API和实例的响应时间的第99个百分点:
histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
在云原生环境中,通常有许多相同组件的多个实例在运行,能否跨实例汇总数据是关键。
Histograms有三个主要的缺点:
-
首先,桶必须是预定义的,这需要一些前期的设计。
如果你的桶没有被很好地定义,你可能无法计算出你需要的百分比,或者会消耗不必要的资源。例如,如果你有一个总是需要超过一秒钟的API,那么拥有上限(le label)小于一秒钟的桶将是无用的,只会消耗监控后端服务器的计算和存储资源。另一方面,如果99.9%的API请求耗时少于50毫秒,那么拥有一个上限为100毫秒的初始桶将无法让你准确测量API的性能。
-
第二,他们提供的是近似的百分位数,而不是精确的百分位数。
这通常没什么问题,只要你的桶被设计为提供具有合理准确性的结果。
-
第三,由于百分位数需要在服务器端计算,当有大量数据需要处理时,它们的计算成本会非常高。
在Prometheus中减轻这种情况的一个方法是使用录制规则来预先计算所需的百分位数。
下面的例子显示了如何使用Prometheus的Python客户端库创建一个带有自定义桶的直方图指标。
from prometheus_client import Histogram
api_request_duration = Histogram(
name='http_request_duration_seconds',
documentation='Api requests response time in seconds',
labelnames=['api', 'instance'],
buckets=(0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 25 )
)
api_request_duration.labels(
api='add_product',
instance='host1.domain.com'
).observe(0.3672)
-
Summary(摘要)
- 作用:类似于Histogram,但更注重于分位数的计算。它同样提供了_sum、_count以及多个quantile(分位数)。
- PromQL实例:假设我们有一个请求耗时的Summary类型指标
http_request_duration_seconds
,我们想要查询95%分位数的请求耗时:
promql`http_request_duration_seconds{quantile="0.95"}`
像直方图一样,Summary指标对于测量请求持续时间和响应体大小很有用。
像直方图一样,汇总度量对于测量请求持续时间和响应大小很有用。
一个Summary指标包括这些指标:
-
一个包含总测量次数的Counter。指标名称使用_count后缀。
-
一个包含所有测量值之和的Counter。指标名称使用_sum后缀。可以选择使用带有分位数标签的指标名称,来暴露一些测量值的分位数指标。由于你不希望这些量值是从应用程序运行的整个时间内测得的,Prometheus客户端库通常会使用流式的分位值,这些分位值是在一个滑动的(通常是可配置的)时间窗口上计算得到的。
例如,测量在host1.domain.com上运行的add_productAPI端点实例的响应时间的Summary指标可以表示为:
# HELP http_request_duration_seconds Api requests response time in seconds
# TYPE http_request_duration_seconds summary
http_request_duration_seconds_sum{api="add_product" instance="host1.domain.com"} 8953.332
http_request_duration_seconds_count{api="add_product" instance="host1.domain.com"} 27892
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0"}
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0.5"} 0.232227334
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0.90"} 0.821139321
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0.95"} 1.528948804
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0.99"} 2.829188272
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="1"} 34.283829292
上面这个例子包括总和和计数以及五个分位数。分位数0相当于最小值,分位数1相当于最大值。分位数0.5是中位数,分位数0.90、0.95和0.99相当于在host1.domain.com上运行的add_product API端点响应时间的第90、95和99个百分位。
像直方图一样,Summary指标包括总和和计数,可用于计算随时间的平均值以及不同时间序列的平均值。
Summary提供了比Histogram更精确的百分位计算结果,但这些百分位有三个主要缺点:
-
首先,客户端计算百分位是很昂贵的。这是因为客户端库必须保持一个有序的数据点列表,以进行这种计算。在Prometheus SDK中的实现限制了内存中保留和排序的数据点的数量,这降低了准确性以换取效率的提高。注意,并非所有的Prometheus客户端库都支持汇总指标中的量值。例如,Python SDK就不支持。
-
第二,你要查询的量值必须由客户端预先定义。只有那些已经提供了指标的量值才能通过查询返回。没有办法在查询时计算其他百分位。增加一个新的百分位指标需要修改代码,该指标才可以被使用。
-
第三,也是最重要的一点,不可能把多个Summary指标进行聚合计算。这使得它们对动态现代系统中的大多数用例毫无用处,在这些用例中,通常我们对一个特定的组件感兴趣,这个视角是全局的,它不与特定的实例关联。
因此,想象一下,在我们的例子中,add_product的API端点运行在10个主机上,在这些服务之前有一个负载均衡器。我们没有任何聚合函数可以用来计算add_product API接口在所有请求中响应时间的第99百分位数,无论这些请求被发送到哪个后端实例上。我们只能看到每个主机的第99个百分点。同样地,我们也只能知道某个接口,比如add_productAPI端点的(在某个实例上的)第99百分位数,而不能对不同的接口进行聚合。
下面的代码使用Prometheus的Python客户端库创建了一个Summary指标。
from prometheus_client import Summary
api_request_duration = Summary(
'http_request_duration_seconds',
'Api requests response time in seconds',
['api', 'instance']
)
api_request_duration.labels(api='add_product', instance='host1.domain.com').observe(0.3672)
上面的代码没有定义任何量化指标,只会产生总和和计数指标。Prometheus的Python SDK不支持Summary指标中的分位数计算。
Histogram还是Summary?
在大多数情况下,直方图是首选,因为它更灵活,并允许汇总百分位数。
在不需要百分位数而只需要平均数的情况下,或者在需要非常精确的百分位数的情况下,汇总是有用的。例如,在履行关键系统的合约责任的情况下。
下表总结了直方图和汇总表的优点和缺点。
Prometheus常用监控指标Exporter
广义上讲所有可以向Prometheus提供监控样本数据的程序都可以被称为一个Exporter。而Exporter的一个实例称为target,Prometheus通过轮询的方式定期从这些target中获取样本数据。
Exporter分类
从Exporter的来源上来讲,主要分为两类:
-
社区提供的
Prometheus社区提供了丰富的Exporter实现,涵盖了从基础设施,中间件以及网络等各个方面的监控功能。这些Exporter可以实现大部分通用的监控需求。下表列举一些社区中常用的Exporter:
范围 | 常用Exporter |
数据库 | MySQL Exporter, Redis Exporter, MongoDB Exporter, MSSQL Exporter等 |
硬件 | Apcupsd Exporter,IoT Edison Exporter, IPMI Exporter, Node Exporter等 |
消息队列 | Beanstalkd Exporter, Kafka Exporter, NSQ Exporter, RabbitMQ Exporter等 |
存储 | Ceph Exporter, Gluster Exporter, HDFS Exporter, ScaleIO Exporter等 |
HTTP服务 | Apache Exporter, HAProxy Exporter, Nginx Exporter等 |
API服务 | AWS ECS Exporter, Docker Cloud Exporter, Docker Hub Exporter, GitHub Exporter等 |
日志 | Fluentd Exporter, Grok Exporter等 |
监控系统 | Collectd Exporter, Graphite Exporter, InfluxDB Exporter, Nagios Exporter, SNMP Exporter等 |
其它 | Blockbox Exporter, JIRA Exporter, Jenkins Exporter, Confluence Exporter等 |
-
用户自定义的
除了直接使用社区提供的Exporter程序以外,用户还可以基于Prometheus提供的Client Library创建自己的Exporter程序,目前Promthues社区官方提供了对以下编程语言的支持:Go、Java/Scala、Python、Ruby。同时还有第三方实现的如:Bash、C++、Common Lisp、Erlang,、Haskeel、Lua、Node.js、PHP、Rust等。
Exporter的运行方式
从Exporter的运行方式上来讲,又可以分为:
独立使用的
以我们已经使用过的Node Exporter为例,由于操作系统本身并不直接支持Prometheus,同时用户也无法通过直接从操作系统层面上提供对Prometheus的支持。因此,用户只能通过独立运行一个程序的方式,通过操作系统提供的相关接口,将系统的运行状态数据转换为可供Prometheus读取的监控数据。 除了Node Exporter以外,比如MySQL Exporter、Redis Exporter等都是通过这种方式实现的。 这些Exporter程序扮演了一个中间代理人的角色。
集成到应用中的
为了能够更好的监控系统的内部运行状态,有些开源项目如Kubernetes,ETCD等直接在代码中使用了Prometheus的Client Library,提供了对Prometheus的直接支持。这种方式打破的监控的界限,让应用程序可以直接将内部的运行状态暴露给Prometheus,适合于一些需要更多自定义监控指标需求的项目。
node-exporter
常用监控指标
- CPU相关指标:
node_cpu_seconds_total{mode="idle"}
:CPU空闲时间(秒)的总和。这是评估CPU使用率的重要指标之一。node_cpu_seconds_total{mode="system"}
、node_cpu_seconds_total{mode="user"}
等:分别表示CPU在内核态和用户态的运行时间。
- 内存相关指标:
node_memory_MemTotal_bytes
:内存总量(以字节为单位)。node_memory_MemFree_bytes
:空闲内存大小(以字节为单位)。node_memory_Buffers_bytes
和node_memory_Cached_bytes
:分别表示被内核用作缓冲和缓存的内存大小。node_memory_SwapTotal_bytes
和node_memory_SwapFree_bytes
:分别表示交换空间的总大小和空闲大小。
- 磁盘相关指标:
node_filesystem_size_bytes
:文件系统的大小(以字节为单位)。node_filesystem_free_bytes
和node_filesystem_avail_bytes
:分别表示文件系统的空闲空间和非root用户可用的空间大小。node_disk_io_now
、node_disk_io_time_seconds_total
等:与磁盘I/O操作相关的指标,如当前正在进行的I/O操作数以及花费在I/O操作上的总时间。
- 网络相关指标:
node_network_receive_bytes_total
和node_network_transmit_bytes_total
:分别表示网络接口接收和发送的总字节数。这些指标对于评估网络流量和带宽使用情况非常重要。
- 系统负载相关指标:
node_load1
、node_load5
、node_load15
:分别表示系统在过去1分钟、5分钟和15分钟的平均负载。这些指标有助于了解系统的整体忙碌程度和性能表现。
要获取完整的指标列表,可以访问 node-exporter
的 metrics 端点(通常是 /metrics
)。
mysql-exporter
常用监控指标:
- MySQL 全局状态指标:
mysql_global_status_uptime
:MySQL 服务器的运行时间(以秒为单位)。mysql_global_status_threads_connected
:当前打开的连接数。mysql_global_status_threads_running
:当前正在运行的线程数。mysql_global_status_queries
:从服务器启动开始执行的查询总数。mysql_global_status_questions
:从服务器启动开始接收的客户端查询总数。
- MySQL 复制指标(如果配置了复制):
mysql_slave_status_slave_io_running
:表示 IO 线程是否正在运行(1 为运行,0 为停止)。mysql_slave_status_slave_sql_running
:表示 SQL 线程是否正在运行(1 为运行,0 为停止)。mysql_slave_status_seconds_behind_master
:从服务器相对于主服务器的延迟时间(以秒为单位)。
- InnoDB 存储引擎指标:
mysql_global_status_innodb_buffer_pool_read_requests
:InnoDB 缓冲池执行的逻辑读请求数。mysql_global_status_innodb_buffer_pool_reads
:不能满足 InnoDB 缓冲池而直接从磁盘读取的请求数。mysql_global_status_innodb_row_lock_time_avg
:平均行锁定时间(以毫秒为单位)。mysql_global_status_innodb_row_lock_time_max
:最大行锁定时间(以毫秒为单位)。
- 连接和资源使用指标:
mysql_global_variables_max_connections
:MySQL 配置的最大连接数。mysql_global_status_aborted_connects
:尝试连接到 MySQL 服务器但失败的连接数。mysql_global_status_connection_errors_total
:由于各种原因导致的连接错误总数。
- 查询缓存指标(如果启用了查询缓存):
mysql_global_status_qcache_hits
:查询缓存命中次数。mysql_global_status_qcache_inserts
:插入到查询缓存中的查询次数。mysql_global_status_qcache_not_cached
:由于查询类型或其他原因而无法缓存的查询次数。
- 其他常用指标:
mysql_exporter_last_scrape_duration_seconds
:mysql-exporter
上次抓取指标所花费的时间。mysql_exporter_scrape_errors_total
:mysql-exporter
在抓取过程中遇到的错误总数。
要获取完整的指标列表,可以访问 mysql-exporter
的 metrics 端点(通常是 /metrics
)。此外,对于特定的监控需求,可能还需要结合 MySQL 的性能和配置进行进一步的定制和选择。
redis-exporter
常用监控指标
- Redis 连接相关指标:
redis_connected_clients
:当前连接的 Redis 客户端数量。redis_connected_slaves
:当前连接的 Redis 从节点数量。redis_blocked_clients
:正在等待 Redis 的客户端数量(通常因为 BLPOP、BRPOP、BRPOPLPUSH 等命令阻塞)。
- Redis 性能相关指标:
redis_instantaneous_ops_per_sec
:每秒执行的操作数,反映 Redis 的处理速度。redis_latency_spike_duration_seconds
:最近一次延迟峰值持续了多长时间(秒),这是检测性能问题的一个标志。
- 内存使用相关指标:
redis_mem_used_bytes
:Redis 使用的内存大小(字节)。redis_mem_fragmentation_ratio
:内存碎片率,当该值远大于 1 时,表示存在较多的内存碎片。redis_evicted_keys_total
:由于 maxmemory 限制而被淘汰的 key 的总数量。redis_expired_keys_total
:已过期的 key 的总数量。
- 持久性相关指标:
redis_rdb_last_save_time_seconds
:自从 Redis 服务器启动以来,最后一次 RDB 持久化的 UNIX 时间戳。redis_rdb_changes_since_last_save
:自从最后一次 RDB 持久化以来,数据库发生的改变次数。redis_aof_current_size_bytes
:当前 AOF 文件的大小(字节)。redis_aof_last_rewrite_time_seconds
:上一次 AOF 重写操作的耗时(秒)。
- 其他常用指标:
blackbox-exporter
常用监控指标
- HTTP指标:
http_status_code
:HTTP响应状态码,如200、404、500等。http_content_length
:HTTP响应内容长度。http_request_duration_seconds
:HTTP请求延迟。http_ssl_expiry_seconds
:HTTPS证书过期时间。
- DNS指标:
dns_lookup_time_seconds
:DNS查询时间。dns_lookup_error
:DNS查询是否出错。
- TCP指标:
tcp_connect_time_seconds
:TCP连接时间。tcp_connection_refused
:TCP连接是否被拒绝。
- ICMP指标:
icmp_response
:ICMP响应是否正常,通常用于检测远程主机是否在线(存活状态)。
kafka-exporter
常用监控指标
Kafka集群和Broker相关指标
kafka_cluster_id
:Kafka集群的唯一标识符。kafka_broker_id
:Broker的唯一标识符。kafka_broker_version
:Kafka Broker的版本号。kafka_controller_count
:集群中控制器的数量。kafka_broker_requests_total
:Broker接收到的请求总数。
主题和分区相关指标
kafka_topic_partitions_count
:每个主题的分区数量。kafka_topic_partition_current_offset
:每个分区的当前偏移量。kafka_topic_partition_leader_replica_count
:每个分区的Leader副本数量。kafka_topic_partition_isr_replica_count
:每个分区的ISR(In-Sync Replicas)副本数量。kafka_topic_partition_replica_count
:每个分区的副本总数。kafka_topic_partition_under_replicated_partitions
:分区副本数量少于期望值的分区数。
生产者相关指标
kafka_producer_request_rate
:生产者发送请求的速率。kafka_producer_request_size_max
:生产者发送的最大请求大小。kafka_producer_record_send_rate
:生产者发送记录的速率。kafka_producer_record_errors_total
:生产者发送失败的消息数量。kafka_producer_batch_size_avg
:生产者批处理大小的平均值。
消费者相关指标
kafka_consumer_group_current_offset
:消费者组在每个分区上的当前偏移量。kafka_consumer_group_lag
:消费者组在每个分区上的滞后量(即当前偏移量与最后一条消息的偏移量之差)。kafka_consumer_group_membership_count
:每个消费者组中的消费者成员数量。kafka_consumer_fetch_rate
:消费者从Broker拉取消息的速率。kafka_consumer_fetch_size_bytes
:消费者从Broker拉取消息的大小(以字节为单位)。
复制和同步相关指标
kafka_replica_fetch_manager_max_lag
:每个副本的最大滞后量。kafka_replica_fetch_manager_min_fetch_rate
:副本拉取的最小速率。kafka_replica_leader_elections_per_sec
:每秒发生的Leader选举次数。
请注意,以上指标列表并不完整,Kafka Exporter可能还提供了其他更详细的监控指标。你可以根据实际需求选择关注哪些指标,并在Prometheus中进行相应的配置和查询。同时,确保Kafka Exporter已经正确配置并运行,以便能够收集到这些指标数据。
Spring Boot Actuator
常用监控指标
Spring Boot Actuator是一个用于暴露应用程序自身信息的模块,它可以提供一系列生产就绪的端点,这些端点可以用于监视和管理Spring Boot应用程序。通过Actuator,您可以轻松地获取应用程序的运行时信息,如健康状态、性能指标、环境属性、系统属性等。
以下是一些常见的可以通过 /actuator/prometheus
监控的指标类型:
- 系统指标:
- CPU 使用率
- 内存使用情况(堆内存、非堆内存、JVM内存池等)
- 系统负载
- 磁盘空间和使用情况
- 网络I/O
- 文件描述符使用
- 线程状态和数量
- 垃圾回收活动
- 应用指标:
- HTTP 请求的计数、速率、延迟和百分位数
- 数据库连接的池使用情况、查询次数和性能
- 消息队列的消费和生产速率
- 缓存命中率、大小和驱逐次数
- 调度任务的执行情况和延迟
- 外部API调用的次数、失败率和延迟
- 业务指标:
- 用户注册、登录和会话数
- 订单处理速率和失败率
- 购物车放弃率
- 页面浏览量和跳出率
- 任何与你的业务逻辑直接相关的自定义指标
- 健康指标:
- 数据库连接健康状态
- 外部服务可达性(如API网关、认证服务等)
- 磁盘空间不足警告
- 应用程序内部特定组件的健康检查(如缓存服务、消息队列等)
- 自定义指标:
- 你可以定义自己的度量来监控应用程序中任何重要的方面。
Prometheus监控Spring Boot应用的方式主要有以下几种:
- 使用Spring Boot Actuator提供的监控功能:首先,在Spring Boot程序中加入
spring-boot-starter-actuator
依赖。这样,Spring Boot在运行时就会自动放开/actuator/health
和/actuator/info
这两个endpoint,我们就可以通过这两个endpoint查看当前Spring Boot运行的情况。然后,Prometheus可以通过这些endpoint来拉取Spring Boot应用的指标数据。 - 集成micrometer-registry-prometheus:这是一种更为专业和详细的监控方式。你需要确保你的Spring Boot和micrometer的版本号相互兼容。然后,你可以使用micrometer提供的各种监控功能来收集Spring Boot应用的指标数据,并通过Prometheus的pull机制来获取这些数据。
- 使用Prometheus的push gateway:虽然Prometheus主要是基于pull模型来获取数据的,但你也可以通过Prometheus的push gateway来实现push效果。这在你需要主动推送数据到Prometheus时非常有用。
spring-boot-starter-actuator主要提供了基本的监控和管理功能,包括暴露应用程序的各种信息;
micrometer-registry-prometheus则是更具体的一个实现,它将Micrometer的指标暴露给Prometheus,以实现与Prometheus的集成和更深入的监控。
在实际项目中,通常会根据具体需求来决定是否需要同时引入这两个模块。如果只需要基本的监控功能,那么引入spring-boot-starter-actuator可能就足够了;如果需要与Prometheus进行集成以实现更深入的监控,那么还需要引入micrometer-registry-prometheus。
总的来说,Prometheus监控Spring Boot应用的方式主要取决于你的具体需求和你的应用环境。你可以根据自己的情况选择最适合你的方式来进行监控。同时,Prometheus还提供了丰富的查询语言和图形化界面,可以帮助你更好地分析和展示监控数据。
Prometheus的k8s监控指标
针对于K8s集群,主要是对三方面进行监控,分别是Node、Namespace、Pod。
一、 Node监控
针对于节点的维度,主要监控内存、CPU使用率、磁盘和索引的使用率,过高告警。还要监控NodeNotReady的情况。
1、NodeMemorySpaceFillingUp
监控Node内存使用率,如果大于80%则报警。
1 2 3 4 5 6 7 8 9 | alert:NodeMemorySpaceFillingUp expr:((1 - (node_memory_MemAvailable_bytes{job="node-exporter"} / node_memory_MemTotal_bytes{job="node-exporter"}) * on(instance) group_left(nodename) (node_uname_info) > 0.8) * 100) for: 5m labels:cluster: criticaltype: node annotations:description: Memory usage on `{{$labels.nodename}}`({{ $labels.instance }}) up to {{ printf "%.2f" $value }}%.summary: Node memory will be exhausted. |
2、NodeCpuUtilisationHigh
监控Node CPU使用率,如果大于80%则报警。
1 2 3 4 5 6 7 8 9 | alert:NodeFilesystemAlmostOutOfSpace expr:((node_filesystem_avail_bytes{fstype!="",job="node-exporter"} / node_filesystem_size_bytes{fstype!="",job="node-exporter"} * 100 < 20 and node_filesystem_readonly{fstype!="",job="node-exporter"} == 0) * on(instance) group_left(nodename) (node_uname_info)) for: 5m labels:cluster: criticaltype: node annotations:description: Filesystem on `{{ $labels.device }}` at `{{$labels.nodename}}`({{ $labels.instance }}) has only {{ printf "%.2f" $value }}% available space left.summary: Node filesystem has less than 20% space left. |
3、NodeFilesystemAlmostOutOfSpace
监控Node磁盘使用率,剩余空间<10%则报警。
1 2 3 4 5 6 7 8 9 | alert:NodeFilesystemAlmostOutOfSpace expr:((node_filesystem_avail_bytes{fstype!="",job="node-exporter"} / node_filesystem_size_bytes{fstype!="",job="node-exporter"} * 100 < 10 and node_filesystem_readonly{fstype!="",job="node-exporter"} == 0) * on(instance) group_left(nodename) (node_uname_info)) for: 5m labels:cluster: criticaltype: node annotations:description: Filesystem on `{{ $labels.device }}` at `{{$labels.nodename}}`({{ $labels.instance }}) has only {{ printf "%.2f" $value }}% available space left.summary: Node filesystem has less than 10% space left. |
4、NodeFilesystemAlmostOutOfFiles
监控Node索引节点使用率,剩余空间<10%则报警。
1 2 3 4 5 6 7 8 9 | alert:NodeFilesystemAlmostOutOfFiles expr:((node_filesystem_files_free{fstype!="",job="node-exporter"} / node_filesystem_files{fstype!="",job="node-exporter"} * 100 < 10 and node_filesystem_readonly{fstype!="",job="node-exporter"} == 0) * on(instance) group_left(nodename) (node_uname_info)) for: 5m labels:cluster: criticaltype: node annotations:description: Filesystem on `{{ $labels.device }}` at `{{$labels.nodename}}`({{ $labels.instance }}) has only {{ printf "%.2f" $value }}% available inodes left.summary: Node filesystem has less than 10% inodes left. |
5、KubeNodeNotReady
监控Node状态,如果有Node Not Ready则报警。
1 2 3 4 5 6 7 8 9 | alert:KubeNodeNotReady expr:(kube_node_status_condition{condition="Ready",job="kube-state-metrics",status="true"} == 0) for: 5m labels:cluster: criticaltype: node annotations:description: {{ $labels.node }} has been unready for more than 15 minutes.summary: Node is not ready. |
6、KubeNodePodsTooMuch
监控Node上pod数量,我们设置的最大每个Node上最多运行110个Pod,如果使用率>80%则报警。
1 2 3 4 5 6 7 8 9 | alert:KubeNodePodsTooMuch expr:(sum by(node) (kube_pod_info) * 100 / 110 > 80) for: 5m labels:cluster: criticaltype: node annotations:description: Pods usage on `{{$labels.node}}` up to {{ printf "%.2f" $value }}%.summary: Node pods too much. |
二、Namespace监控
Namespace关于CPU和内存有三个值,分别是limit、request和usage。
我的理解是:
-
limit 最多可以申请多少资源(Pod 维度))
cpu:namespace_cpu:kube_pod_container_resource_limits:sum
memory:namespace_memory:kube_pod_container_resource_requests:sum
-
request 申请了多少资源(Pod 维度))
cpu:namespace_cpu:kube_pod_container_resource_requests:sum
memory:namespace_memory:kube_pod_container_resource_limits:sum
-
usage 实际使用了多少资源(Pod 维度))
cpu:sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate) by (namespace)
memory:sum(node_namespace_pod_container:container_memory_working_set_bytes) by (namespace)
我们在kubord里面可以设置namespace的limit内存和cpu,这个暂时不知道如何从Prometheus获取,后续会持续关注。
当request/limit > 80%则说明Namespace资源可能不够,需要扩大namespace资源。
1、NamespaceCpuUtilisationHigh
监控namespace cpu使用率,高于90%则报警。
1 2 3 4 5 6 7 8 9 | alert:NamespaceCpuUtilisationHigh expr:(sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_limits:sum) by (namespace) * 100 > 90) for: 5m labels:cluster: criticaltype: namespace annotations:description: CPU utilisation on `{{$labels.namespace}}` up to {{ printf "%.2f" $value }}%.summary: Namespace CPU utilisation high. |
2、NamespaceCpuUtilisationLow
监控namespace cpu使用率,低于10%则报警。
1 2 3 4 5 6 7 8 9 | alert:NamespaceCpuUtilisationLow expr:(sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_limits:sum) by (namespace) * 100 < 10) for: 5m labels:cluster: criticaltype: namespace annotations:description: CPU utilisation on `{{$labels.namespace}}` as low as {{ printf "%.2f" $value }}%.summary: Namespace CPU underutilization. |
3、NamespaceMemorySpaceFillingUp
监控namespace 内存使用率,高于90%则报警。
1 2 3 4 5 6 7 8 9 | alert:NamespaceMemorySpaceFillingUp expr:(sum(node_namespace_pod_container:container_memory_working_set_bytes) by (namespace) / sum(namespace_memory:kube_pod_container_resource_limits:sum) by (namespace) * 100 > 90) for: 5m labels:cluster: criticaltype: namespace annotations:description: Memory usage on `{{$labels.namespace}}` up to {{ printf "%.2f" $value }}%.summary: Namespace memory will be exhausted. |
4、NamespaceMemorySpaceLow
监控namespace 内存使用率,低于10%则报警。
1 2 3 4 5 6 7 8 9 | alert:NamespaceMemorySpaceLow expr:(sum(node_namespace_pod_container:container_memory_working_set_bytes) by (namespace) / sum(namespace_memory:kube_pod_container_resource_limits:sum) by (namespace) * 100 < 10) for: 5m labels:cluster: criticaltype: namespace annotations:description: Memory usage on `{{$labels.namespace}}` as low as {{ printf "%.2f" $value }}%.summary: Under-utilized namespace memory. |
5、KubePodNotReady
监控pod状态,如果存在pod持续not-ready
达到十五分钟则报警。
1 2 3 4 5 6 7 8 9 | alert:KubePodNotReady expr:(sum by(namespace, pod) (max by(namespace, pod) (kube_pod_status_phase{job="kube-state-metrics",namespace=~".*",phase=~"Pending|Unknown"}) * on(namespace, pod) group_left(owner_kind) topk by(namespace, pod) (1, max by(namespace, pod, owner_kind) (kube_pod_owner{owner_kind!="Job"}))) > 0) for: 5m labels:cluster: criticaltype: namespace annotations:description: Pod {{ $labels.namespace }}/{{ $labels.pod }} has been in a non-ready state for longer than 15 minutes.summary: Pod has been in a non-ready state for more than 15 minutes. |
6、KubeContainerWaiting
监控pod状态,如果存在pod持续waiting
达到十五分钟则报警。
1 2 3 4 5 6 7 8 9 | alert:KubeContainerWaiting expr:(sum by(namespace, pod, container) (kube_pod_container_status_waiting_reason{job="kube-state-metrics",namespace=~".*"}) > 0) for: 5m labels:cluster: criticaltype: namespace annotations:description:Pod {{ $labels.namespace }}/{{ $labels.pod }} container {{$labels.container}} has been in waiting state for longer than 15 minutes.summary: Pod container waiting longer than 15 minutes. |
7、PodRestart
这个告警配置的就是如果kube-system这个namespace下面存在某个pod重启了则发送告警。
因为在kube-system这个namespace下面,存在很多集群相关的pod,比如我们的日志收集组件Fluentd和corends等,所以如果这个namespace下面有容器重启,那么需要警惕一下是否集群出现了问题。
1 2 3 4 5 6 7 8 9 | alert:PodRestart expr:(floor(increase(kube_pod_container_status_restarts_total{namespace="kube-system"}[1m])) > 0) for: 5m labels:cluster: criticaltype: namespace annotations:description:Pod {{ $labels.namespace }}/{{ $labels.pod }} restart {{ $value }} times in last 1 minutes.summary: Pod restart in last 1 minutes. |
8、PrometheusOom
Prometheus自己也是存在宕机的风险,所以我们加了一个监控来检测Prometheus,如果内存使用率达到90%则可能出现异常,所以发送告警。
1 2 3 4 5 6 7 8 9 | alert:PrometheusOom expr:(container_memory_working_set_bytes{container="prometheus"} / container_spec_memory_limit_bytes{container="prometheus"} > 0.9) for: 5m labels:cluster: criticaltype: namespace annotations:description:Memory usage on `Prometheus` up to {{ printf "%.2f" $value }}%.summary: Prometheus will be oom. |
三、Pod监控
1.1 pod性能指标(k8s集群组件自动集成)
k8s组件本身提供组件自身运行的监控指标以及容器相关的监控指标。通过cAdvisor 是一个开源的分析容器资源使用率和性能特性的代理工具,集成到 Kubelet中,当Kubelet启动时会同时启动cAdvisor,且一个cAdvisor只监控一个Node节点的信息。cAdvisor 自动查找所有在其所在节点上的容器,自动采集 CPU、内存、文件系统和网络使用的统计信息。cAdvisor 通过它所在节点机的 Root 容器,采集并分析该节点机的全面使用情况。
当然kubelet也会输出一些监控指标数据,因此pod的监控数据有kubelet和cadvisor,监控url分别为
https://NodeIP:10250/metrics
https://NodeIP:10250/metrics/cadvisor
1.2 K8S资源监控(k8s集群内部署)
kube-state-metrics是一个简单的服务,它监听Kubernetes API服务器并生成关联对象的指标。它不关注单个Kubernetes组件的运行状况,而是关注内部各种对象(如deployment、node、pod等)的运行状况。
注:先手动检查下集群,是否已经安装kube-state-metrics
如果集群没有安装,可参考如下步骤进行部署:
1 2 3 4 5 |
|
1.3 编辑kube-state-metrics.yml文件
1 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
|
1.4 启动yaml文件
1 |
|
1.5 查看pod信息
1 |
|
1.6 查看service信息
1 |
|
这里可以看到k8s集群对外暴露的端口为 62177
1.7 查看集群信息
1 |
|
然后查看metrics信息
可以手动
1 |
|
正常,数据metrics就会出现
二、创建token供集群外部访问
集群外部监控K8s集群,通过访问kube-apiserver来访问集群资源。通过这种方式集群外部prometheus也能自动发现k8s集群服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
三、集成Prometheus配置
1 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
|
注意:bearer_token_file: /prometheus/data/k8s_token
这里的token为上面生成的token信息,请根据目录进行配置即可
然后重启prometheus
如果是容器部署的prometheus,需要考虑映射token,可docker cp到/prometheus/data/ 即可
即可
1 |
|
3、进入prometheus界面,查看相关指标
默认情况下 prometheus url: http://IP:9090
4、集成grafana
导入grafana JSON ID, 747