【30天精通Prometheus:一站式监控实战指南】第21天:深入解析PromQL(Prometheus Query Language)的高级用法,解锁监控数据的无限可能,释放监控数据潜能

亲爱的读者们👋

  欢迎加入【30天精通Prometheus】专栏!📚 在这里,我们将探索Prometheus的强大功能,并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。🚀

  Prometheus是云原生和DevOps的核心监控工具,我们将从基础概念开始,逐步涵盖配置、查询、告警和可视化。💪

  在接下来的30天里,我们将解锁Prometheus的实战技巧,通过案例和分享,助你深入理解其工作原理。📆

  目标:30天后,你将熟练掌握Prometheus,为未来的项目挑战做好准备!💯

  这是一段精彩旅程,期待你的加入!🎉


一、引言 🚀

1.1 PromQL基础 📚

定义
  PromQL(Prometheus Query Language)是Prometheus监控系统内置的一种查询语言,专为Prometheus监控系统设计,用于对收集的时间序列数据进行高效、灵活的查询和分析。

功能
  数据查询:PromQL允许用户通过标签选择器来过滤时间序列,查询特定的监控数据。

  数据聚合:PromQL支持丰富的聚合操作,如求和、平均值、最小值、最大值等,便于用户对时间序列数据进行汇总和分析。

  内置函数:PromQL内置了多种函数,如rate()用于计算增长率,topk()用于查询最大值的前k个等,这些函数进一步增强了PromQL的查询能力。

  简洁性:PromQL的设计哲学在于提供简洁而强大的语法,使用户能够编写精确的查询来检索所需的数据。

应用场景
  实时监控:PromQL可用于实时监控各种系统指标,如CPU使用率、内存占用、网络流量等,帮助用户快速发现系统异常。

  性能分析:通过PromQL,用户可以分析系统或应用的性能瓶颈,例如通过查询HTTP请求的增长率来评估系统的负载情况。

  告警策略:PromQL可以用于构建复杂的告警策略,当监控指标达到特定阈值时,触发告警通知,以便及时应对潜在问题。

  数据可视化:结合Grafana等可视化工具,PromQL查询结果可以以图表形式展示,帮助用户更直观地理解监控数据。

1.2 PromQL高级用法的必要性 🔍

1.2.1 PromQL高级用法的功能和特点

  PromQL高级用法包含一系列复杂查询和计算功能,如聚合查询、范围查询、多标签选择器、算术运算符、逻辑运算符以及时间序列函数等。这些功能允许对时间序列数据进行精确的选择、过滤、计算和可视化。

  • 聚合查询:通过sum、avg、min、max等函数,可以快速计算出监控数据的统计信息,如总和、平均值等。
  • 范围查询:通过[time]选择器,可以选择特定时间范围内的数据进行分析。
  • 多标签选择器:允许用户根据多个标签值筛选指标数据,提高查询的灵活性和准确性。
  • 算术运算符和逻辑运算符:支持对指标数据进行复杂的计算和条件筛选。
  • 时间序列函数:如rate、irate等,用于计算时间序列数据的增长率等。

1.2.2 如何使用PromQL高级用法提高查询性能

  PromQL高级用法通过精确的数据选择、计算和过滤,可以显著提高查询性能。例如,通过多标签选择器快速定位到关心的数据子集,避免了对大量无关数据的扫描。同时,通过聚合函数和算术运算符,可以在查询时直接计算出所需的结果,减少了后续的数据处理负担。

1.2.3 PromQL高级用法在哪些场景下更为适用

  • 复杂的监控数据分析:当需要对监控数据进行复杂的计算、聚合和筛选时,PromQL高级用法提供了强大的支持。
  • 性能调优和故障排查:通过对系统性能指标进行精确的分析和比较,可以快速定位性能瓶颈和故障点。
  • 自定义监控图表和告警规则:利用PromQL高级用法,可以编写出更加精确和灵活的监控图表和告警规则,满足特定的业务需求。

1.2.4 PromQL高级用法可能带来的性能影响

  虽然PromQL高级用法可以提高查询性能,但在某些情况下也可能带来一定的性能影响。例如,当查询语句非常复杂时,可能会增加Prometheus服务器的计算负担,导致查询响应时间增加。此外,如果查询的数据量非常大,也可能会导致内存和CPU资源的消耗增加。因此,在使用PromQL高级用法时,需要根据实际情况进行权衡和优化,避免过度复杂的查询语句和过大的数据量。

例子和解释

  • 聚合查询:例如,计算某个服务在过去5分钟内的平均请求响应时间,可以使用avg(http_requests_latency_seconds{service=“my-service”}[5m])。这个查询语句通过聚合函数avg和时间范围选择器[5m],快速计算出所需的结果。
  • 范围查询:如果需要查看某个服务在过去1小时内的请求总量,可以使用sum(http_requests_total{service=“my-service”}[1h])。这个查询语句通过时间范围选择器[1h]选择了过去1小时内的数据,并通过聚合函数sum计算出了请求总量。
  • 逻辑运算符:例如,要查找状态码为200且来自特定实例的请求数据,可以使用http_requests_total{status=“200”, instance=“localhost:9090”}。这个查询语句通过逻辑运算符(实际上是标签选择器)将两个条件组合在一起,实现了精确的数据选择。

二、PromQL高级用法概览 📈

2.1 高级选择器 🏷️

2.1.1 标签选择器的高级技巧 🔮

  PromQL(Prometheus Query Language)的标签选择器是其查询功能的核心部分,它允许用户根据标签值来过滤和选择指标数据。以下是一些关于标签选择器的高级技巧,包括设计、使用方法和优化建议。

语法
  匹配器主要是⽤于标签过滤,⽬前⽀持如下4种格式
    =: 精确的匹配给定的标签值
    !=: 不匹配给定的标签值
    =~: 正则表达式匹配给定的标签值
    !~: 不匹配正则表格式给定的标签值

标签组合

  • 查询http_requests_total指标,并且只关心environment为production和service为backend的数据
http_requests_total{environment="production", service="backend"}
  • 查询指标名称up中标签job等于prometheus的时间序列数据
up{job=“prometheus”}

标签通配符

  • PromQL支持使用=和!来执行基于正则表达式的匹配。例如,要查找所有以api开头的service标签
http_requests_total{service=~"api.*"}

2.1.2 正则表达式在标签选择器中的应用 🔍📝

  在PromQL中,正则表达式允许用户根据更复杂的模式来匹配标签值,而不仅仅是简单的等于或不等于。正则表达式的应用原理在于通过定义一系列字符和特殊符号的组合,来构建出一个能够描述文本模式的“模板”。当PromQL在处理标签选择器时,它会将正则表达式与实际的标签值进行匹配,以筛选出符合该模式的标签值。
  注意:在PromQL中,正则表达式通常使用~(匹配)和!~(不匹配)操作符来与标签值进行匹配。正则表达式的语法遵循标准的正则表达式规则,但具体的支持情况可能因Prometheus的版本和配置而有所不同。因此,在使用正则表达式时,最好查阅相关文档以确保正确的语法和用法。

正则表达式在PromQL标签选择器中的应用场景非常广泛,以下是一些常见的例子:

模糊匹配

  • 当你不确定标签值的完整内容时,可以使用正则表达式进行模糊匹配。例如,你可以使用正则表达式.*api.*来匹配所有包含“api”的service标签值。
http_requests_total{service=~".*api.*"}

范围匹配

  • 有时需要根据标签值的范围来筛选数据。例如,假设你有一个表示版本号的version标签,你可以使用正则表达式v[0-9]+.[0-9]+来匹配所有形如vX.Y的版本号。
my_metric{version=~"v[0-9]+\.[0-9]+"}

排除模式

  • 使用正则表达式的否定模式(即在模式前加!),你可以排除符合特定模式的标签值。例如,要排除所有以“test”开头的environment标签值。
my_metric{environment!~"^test.*"}

2.2 操作符与函数 🔧

2.2.1 算术操作符的深入解析 🧮

  PromQL(Prometheus Query Language)的算术操作符是用于在Prometheus中对时间序列数据进行数学运算的重要工具。这些操作符允许用户执行加法、减法、乘法、除法等基本的数学运算,从而更灵活地处理和查询监控数据。下面我们将从语法、功能和使用场景等方面对PromQL的算术操作符进行详细解析。

语法
  PromQL中的算术操作符主要包括以下几种
    加法:+
    减法:-
    乘法:*
    除法:/

功能
  算术操作符的功能是执行基本的数学运算。这些运算可以应用于单个时间序列,也可以应用于多个时间序列之间的组合。通过算术操作符,用户可以计算时间序列的总和、差异、乘积、比率等,从而得到更丰富的监控指标。

使用场景
1. 单个时间序列的运算
  假设我们有一个名为cpu_usage的时间序列,它记录了CPU的使用率。我们可以使用算术操作符来对这个时间序列进行运算,例如:

  • 计算过去5分钟的CPU使用率平均值:avg_over_time(cpu_usage[5m])
  • 将CPU使用率转换为百分比(假设原始数据是0-1的小数):cpu_usage * 100

2. 多个时间序列的运算
  假设我们还有两个时间序列:memory_usage(内存使用率)和disk_usage(磁盘使用率)。我们可以使用算术操作符将它们组合起来,进行更复杂的运算:

  • 计算内存和磁盘的总使用率(假设它们都是0-1的小数):memory_usage + disk_usage
  • 计算内存使用率与磁盘使用率的比率:memory_usage / disk_usage(注意:当分母为零时,这个查询会返回NaN)

3. 运算结果的聚合
  除了对单个或多个时间序列进行运算外,我们还可以对运算结果进行聚合。例如,我们可以使用sum函数来计算多个实例或服务的总CPU使用率:

  • 计算所有服务的总CPU使用率:sum(cpu_usage)
  • 计算过去5分钟内所有服务的平均CPU使用率:avg_over_time(sum(cpu_usage)[5m])

2.2.2 逻辑操作符与比较操作符的灵活使用 🔬

  PromQL中的逻辑操作符和比较操作符在查询和过滤时间序列数据时起着关键作用。这些操作符允许根据特定的条件对数据进行筛选和组合,以获取所需的信息。

1.逻辑操作符:PromQL支持AND、OR和UNLESS(类似于NOT)等逻辑操作符,用于组合多个查询条件。这些操作符允许用户根据多个条件同时或选择性地筛选数据。

  • AND:表示两个条件都必须满足。
  • OR:表示两个条件中至少有一个满足。
  • UNLESS:表示第一个条件满足但第二个条件不满足的情况。

2.比较操作符:PromQL支持的比较操作符包括如下内容,这些操作符允许用户对时间序列的值进行比较,以筛选出满足特定条件的数据。

  • ==(等于):选择CPU使用率等于50%的所有时间序列

  注意:直接使用==进行精确匹配可能不太常见,因为时间序列数据通常是浮点数,并且包含多个数据点。更常见的做法是使用范围比较或结合其他操作符和函数。

cpu_usage_percent == 50
  • !=(不等于):选择CPU使用率不等于100%的所有时间序列
cpu_usage_percent != 100
  • >(大于):选择过去5分钟内网络流量大于100MB的所有时间序列
network_traffic_bytes[5m] > 100 * 1024 * 1024
  • <(小于):选择CPU使用率小于20%的所有时间序列
cpu_usage_percent < 20
  • >=(大于等于):选择内存使用量大于或等于80%的所有时间序列
memory_usage_percent >= 80
  • <=(小于等于):选择磁盘剩余空间小于或等于20GB的所有时间序列
disk_free_space_bytes <= 20 * 1024 * 1024 * 1024

2.2.3 聚合函数的高级应用(如sum, avg, min, max, stddev等) 📊

  • sum (求和):计算过去5分钟内所有HTTP请求的总数
sum(http_requests_total[5m])
  • min (最⼩值):查找过去1小时内CPU使用率的最低值
min(cpu_usage_percent[1h])
  • max (最⼤值):找到过去10分钟内磁盘使用率的最高值
max(disk_usage_percent[10m])
  • avg (平均值):最近5分钟内所有job标签为server服务器的平均CPU使用率
avg(cpu_usage_percent{job="servers"}[5m])
  • stddev (标准差):评估过去一天内网络延迟的稳定性
stddev(network_latency_seconds[1d])
  • count (计数):统计过去24小时内有多少次HTTP请求
count(http_requests_total[24h])
  • count_values (对 value 进⾏计数):统计HTTP响应状态码200、404和500的出现次数
count_values("status_code", http_requests_total{code=~"200|404|500"})
  • bottomk (样本值最⼩的 k 个元素):找出过去24小时内CPU使用率最低的5个实例
bottomk(5, cpu_usage_percent[24h])
  • topk (样本值最⼤的k个元素):找到过去一周内网络流量最高的10个服务器
topk(10, network_traffic_bytes{job="servers"}[1w])
  • quantile (分布统计):计算过去1小时内延迟的95%分位数
histogram_quantile(0.95, sum(rate(http_request_duration_bucket[1h])))

三、PromQL高级查询技术 🔍📊

3.1 子查询 👶

3.1.1 子查询的概念与用途 💡

  PromQL中的子查询,类似于其他查询语言中的嵌套查询,允许你在一个查询内部嵌套另一个查询。这种嵌套结构使得查询更加灵活和强大,允许你基于其他查询的结果来进一步筛选、计算或聚合数据。

特点

  • 嵌套性:子查询可以嵌套在其他查询中,形成多层次的查询结构。
  • 灵活性:子查询可以灵活地应用于各种查询场景,包括过滤、计算、分组等。
  • 可读性:通过合理的子查询使用,可以提高查询语句的可读性和可维护性。

应用场景

  • 过滤:通过子查询,可以对时序数据进行复杂的过滤操作,如基于其他时序数据的值来过滤当前时序数据。
  • 计算:子查询可以用于计算中间结果,这些结果可以作为外部查询的输入或用于进一步的计算。
  • 分组:在需要对时序数据进行分组查询时,子查询可以用于生成分组依据或进行分组内的计算。

3.1.2 如何在PromQL中使用子查询 🔧

  • 示例1:基于子查询的过滤。假设我们想要查询在过去5分钟内,CPU使用率超过80%的主机。
instances(irate(cpu_usage_total[5m]) > 0.8)
  • 示例2:子查询用于中间计算。假设我们想要计算每个主机的CPU使用率的增长率,并筛选出增长率超过10%的主机。
increase(cpu_usage[1h]) / increase(up[1h]) > 0.1
  • 示例3:子查询用于分组和聚合。假设我们想要按照数据中心的名称对CPU使用率进行聚合,并计算每个数据中心的平均CPU使用率。
avg by(datacenter) (avg_over_time(cpu_usage[5m]))

3.2 区间向量与即时向量 ⏱️

3.2.1 区间向量与即时向量的定义 📅

即时向量 (Instant Vector)
定义:在给定时间点上收集的指标值。即时向量是Prometheus查询语言(PromQL)的基本单位,用于执行即时的、点状的查询。

性质

  • 每个数据点都包含一个时间戳(查询必带条件,表示该数据点的采集时间)。
  • 每个数据点也包含一组标签,用于标识所选取的指标。
  • 只返回给定时间点上的数据,而不是时间范围内的数据。

应用场景:适用于需要查询单个时间点上的指标值的情况。

区间向量 (Range Vector)
定义:一组时间序列,每个时间序列包含一段时间范围内的样本数据。

性质

  • 可以选择过去一段时间的采样值。
  • 时间范围通过时间范围选择器 [ ] 进行定义,支持多种时间单位(s - 秒, m - 分钟, h - 小时, d - 天, w - 周, y - 年)。
  • 返回的数据是一段时间内的多个采样值。

应用场景:适用于需要查询一段时间内指标值的变化情况,如绘制时间序列图、计算速率等。

3.2.2 区间向量与即时向量的区别 📅

数据内容

  • 即时向量:只包含单个时间点上的数据。
  • 区间向量:包含一段时间内的多个数据点。

查询目的

  • 即时向量:主要用于查询单个时间点上的指标值。
  • 区间向量:用于分析一段时间内指标值的变化情况,如趋势分析、告警规则等。

结果展示

  • 即时向量:可以直接绘制成点图,展示单个时间点的值。
  • 区间向量:可以绘制成线图,展示一段时间内指标值的变化趋势。

3.2.3 区间向量与即时向量的示例

  • 即时向量查询示例:查询当前时间点的node_memory_MemFree_bytes指标值
node_memory_MemFree_bytes
  • 区间向量查询示例:查询过去5分钟内node_memory_MemFree_bytes指标值的变化情况
node_memory_MemFree_bytes[5m]

3.2.4 使用区间向量进行时间序列分析 📈

  • 1.查询一段时间内的指标值:使用区间向量可以轻松地查询某个指标在过去一段时间内的值。例如,要查询node_cpu_seconds_total指标在过去5分钟内的数据,你可以使用以下查询:
rate(node_cpu_seconds_total[1m])
  • 2.计算速率(Rate):通过结合使用rate()函数和区间向量,你可以计算时间序列的速率。这在分析如CPU使用率、网络流量等随时间变化的指标时非常有用。例如,要计算node_cpu_seconds_total指标在过去1分钟内的平均变化速率,你可以使用以下查询:
rate(node_cpu_seconds_total[1m])
  • 3.绘制时间序列图:结合Grafana等可视化工具,你可以使用PromQL的区间向量查询来绘制时间序列图。这有助于直观地展示指标值随时间的变化趋势。
  • 4.告警:在Prometheus告警规则中,你也可以使用区间向量来定义触发告警的条件。例如,你可以设置一个告警规则,当某个指标在过去5分钟内的平均值超过某个阈值时触发告警。
  • 5.与其他函数结合使用:PromQL提供了许多内置函数,如sum(), avg(), max(), min()等,这些函数可以与区间向量结合使用,以执行更复杂的计算和分析。例如,你可以使用avg_over_time()函数来计算一个时间序列在特定时间范围内的平均值。

3.3 向量匹配 🔄

3.3.1 一对一、多对一、一对多匹配 🔄

  一对一匹配是指从操作符两边的表达式获取的即时向量(Instant Vector)中,依次比较并找到唯一匹配(即标签完全一致)的样本值。如果找不到匹配项,那么该值将不会出现在结果中。

# 计算HTTP GET请求的错误率(即500错误与总请求的比率)
(method_code:http_errors:rate5m{method="get", code="500"} / method:http_requests:rate5m{method="get"})

  多对一匹配通常用于一个向量中的多个元素需要与另一个向量中的一个元素进行匹配的情况。这通常通过使用group_left或group_right修饰符来实现。

# 查询每个apiserver实例是否与其对应的node-exporter实例都处于活动状态
up{job="apiserver"} * on(instance) group_left(job) up{job="node-exporter"}

3.3.2 分组匹配与标签匹配 🏷️🔄

  标签匹配:在PromQL中,标签匹配是指根据指标的标签来过滤数据。每个时间序列都由一个指标名称和一组标签唯一确定,标签匹配允许用户根据特定的标签值来查询时间序列。例如,可以使用node_load1{zone=“sh”}来查询所有上海区域(zone=“sh”)的node_load1指标。

node_load1{zone="sh"}

  分组匹配:虽然PromQL本身没有明确的“分组匹配”语法,但通过对查询结果的聚合操作(如sum、avg等),可以实现类似分组的效果。例如,可以使用sum(node_load1) by (zone)来按区域分组并计算每个区域的负载总和。

sum(node_load1) by (zone)

四、实战案例与演练 🔥🚀

4.1 案例一:利用PromQL进行服务器性能监控 💻

4.1.1 监控CPU、内存、磁盘等关键指标 🔬

  在服务器性能监控中,对CPU、内存和磁盘等关键指标的监控至关重要。利用Prometheus和PromQL,我们可以轻松地查询和监控这些指标。
  对于CPU使用率,我们可以使用node_cpu_seconds_total指标,通过PromQL计算出CPU的使用率。例如,以下查询可以计算最近5分钟的CPU平均使用率:

100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

  对于内存使用情况,我们可以使用node_memory_MemTotal_bytes和node_memory_MemFree_bytes等指标来监控总内存和可用内存,并通过PromQL计算出内存使用率:

(node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / node_memory_MemTotal_bytes * 100

  磁盘使用情况可以通过node_filesystem_size_bytes和node_filesystem_free_bytes等指标来监控,以下是一个计算磁盘使用率的示例查询:

(node_filesystem_size_bytes - node_filesystem_free_bytes) / node_filesystem_size_bytes * 100

4.1.2 基于PromQL自定义告警规则与数据可视化 🔔📈

# 服务器资源告警策略
groups:
  - name: host status  #报警规则组的名字
    rules:
      - alert: host is down  # 检测job的状态,持续1分钟metrices不能访问会发给altermanager进行报警
        expr: up{exporter="node_exporter"} == 0
        for: 5m   # 持续时间 , 表示持续5分钟获取不到信息,则触发报警
        labels:
          level: 严重  # 告警级别,自定义的标签
          exporter: node_exporter
        annotations:
          exporter: "{{ $labels.exporter }}"
          resourcepoolname: "{{ $labels.resource_pool_name }}"
          second_collection_center: "{{ $labels.second_collection_center }}"
          module: "{{ $labels.module }}"
          description: "host is down!"     # 自定义具体描述

      - alert: disk usage > 90%
        expr: 100-(node_filesystem_free_bytes{fstype=~"ext4|xfs",mountpoint="/"}/node_filesystem_size_bytes {fstype=~"ext4|xfs",mountpoint="/"}*100) > 90
        for: 15m # 告警持续时间,超过这个时间才会发送给alertmanager
        labels:
          level: 警告
          exporter: node_exporter
        annotations:
          exporter: "{{ $labels.exporter }}"
          resourcepoolname: "{{ $labels.resource_pool_name }}"
          second_collection_center: "{{ $labels.second_collection_center }}"
          module: "{{ $labels.module }}"
          description: "disk usage > 90%."

4.2 案例二:微服务架构下的监控实践 🌐

4.2.1 监控服务调用、响应时间等微服务相关指标 ⚡

  在微服务架构中,监控服务调用次数、响应时间和错误率等关键指标对于确保系统的稳定性和性能至关重要。我们可以使用Prometheus来收集这些指标,并通过PromQL进行查询和分析。
  例如,假设我们有一个记录服务调用次数的指标http_requests_total,以下是一个查询服务调用次数的示例:

sum(rate(http_requests_total[5m])) by (service)

  对于响应时间,我们可以使用http_request_duration_seconds等指标来监控。以下是一个计算平均响应时间的示例查询:

avg(http_request_duration_seconds_sum / http_request_duration_seconds_count) by (service)

4.2.2 使用PromQL构建服务链路监控 🔗🔍

  在微服务架构中,服务之间的调用关系可能非常复杂。为了监控整个服务链路,我们可以使用PromQL结合trace ID或其他相关信息来追踪请求在各个服务之间的流转情况。

  例如,如果每个服务在调用其他服务时都生成了一个唯一的trace ID,并且这个ID在整个调用链中保持不变,那么我们就可以使用这个ID来查询和追踪整个调用链的情况。当然,这通常需要结合日志收集和分析系统(如ELK Stack)来实现更详细的服务链路监控和故障排查。

  在Prometheus中,我们可以通过监控各个服务的入口和出口调用情况,以及结合标签信息(如服务名、方法名等),来构建一个简单的服务链路视图。这有助于我们快速定位性能瓶颈和故障点,从而提高系统的稳定性和性能。

相关资料下载地址📚

  • 33
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

强弟儿insights

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值