写点什么

Prometheus 监控神器 - 自动发现篇

作者:乌龟哥哥
  • 2023-04-29
    河北
  • 本文字数:4164 字

    阅读完需:约 14 分钟

通过服务发现的方式,我们可以在不重启 Prometheus 服务的情况下动态的发现需要监控的 Target 实例信息。



如上图所示,对于线上环境我们可能会划分为:dev, stage, prod 不同的集群。每一个集群运行多个主机节点,每个服务器节点上运行一个 Node Exporter 实例。Node Exporter 实例会自动注册到 Consul 中,而 Prometheus 则根据 Consul 返回的 Node Exporter 实例信息动态的维护 Target 列表,从而向这些 Target 轮询监控数据。


然而,如果我们可能还需要:


  • 按照不同的环境 dev, stage, prod 聚合监控数据?

  • 对于研发团队而言,我可能只关心 dev 环境的监控数据,如何处理?

  • 如果为每一个团队单独搭建一个 Prometheus Server。那么如何让不同团队的 Prometheus Server 采集不同的环境监控数据?


面对以上这些场景下的需求时,我们实际上是希望 Prometheus Server 能够按照某些规则(比如标签)从服务发现注册中心返回的 Target 实例中有选择性的采集某些 Exporter 实例的监控数据。


接下来,我们实验如何通过 Prometheus 强大的 Relabel 机制来实现以上这些具体的目标。

Prometheus 的 Relabeling 机制

在 Prometheus 所有的 Target 实例中,都包含一些默认的 Metadata 标签信息。可以通过 Prometheus UI 的 Targets 页面中查看这些实例的 Metadata 标签的内容:



默认情况下,当 Prometheus 加载 Target 实例完成后,这些 Target 时候都会包含一些默认的标签:


  • __address__:当前Target实例的访问地址<host>:<port>

  • __scheme__:采集目标服务访问地址的HTTP Scheme,HTTP或者HTTPS

  • __metrics_path__:采集目标服务访问地址的访问路径

  • __param_<name>:采集任务目标服务的中包含的请求参数


上面这些标签将会告诉 Prometheus 如何从该 Target 实例中获取监控数据。除了这些默认的标签以外,我们还可以为 Target 添加自定义的标签,例如,在“基于文件的服务发现”小节中的示例中,我们通过 JSON 配置文件,为 Target 实例添加了自定义标签 env,如下所示该标签最终也会保存到从该实例采集的样本数据中:


node_cpu{cpu="cpu0",env="prod",instance="localhost:9100",job="node",mode="idle"}
复制代码


一般来说,Target 以作为前置的标签是在系统内部使用的,因此这些标签不会被写入到样本数据中。不过这里有一些例外,例如,我们会发现所有通过 Prometheus 采集的样本数据中都会包含一个名为 instance 的标签,该标签的内容对应到 Target 实例的 address__。 这里实际上是发生了一次标签的重写处理。


这种发生在采集样本数据之前,对 Target 实例的标签进行重写的机制在 Prometheus 被称为 Relabeling。



Prometheus 允许用户在采集任务设置中通过 relabel_configs 来添加自定义的 Relabeling 过程。

使用 replace/labelmap 重写标签

Relabeling 最基本的应用场景就是基于 Target 实例中包含的 metadata 标签,动态的添加或者覆盖标签。例如,通过 Consul 动态发现的服务实例还会包含以下 Metadata 标签信息:


  • __meta_consul_address:consul地址

  • __meta_consul_dc:consul服务所在的数据中心

  • __meta_consulmetadata:服务的metadata

  • __meta_consul_node:consul服务node节点的信息

  • __meta_consul_service_address:服务访问地址

  • __meta_consul_service_id:服务ID

  • __meta_consul_service_port:服务端口

  • __meta_consul_service:服务名称

  • __meta_consul_tags:服务包含的标签信息


在默认情况下,从 Node Exporter 实例采集上来的样本数据如下所示:


node_cpu{cpu="cpu0",instance="localhost:9100",job="node",mode="idle"} 93970.8203125
复制代码


我们希望能有一个额外的标签 dc 可以表示该样本所属的数据中心:


node_cpu{cpu="cpu0",instance="localhost:9100",job="node",mode="idle", dc="dc1"} 93970.8203125
复制代码


在每一个采集任务的配置中可以添加多个 relabel_config 配置,一个最简单的 relabel 配置如下:


scrape_configs:  - job_name: node_exporter    consul_sd_configs:      - server: localhost:8500        services:          - node_exporter    relabel_configs:    - source_labels:  ["__meta_consul_dc"]      target_label: "dc"
复制代码


该采集任务通过 Consul 动态发现 Node Exporter 实例信息作为监控采集目标。在上一小节中,我们知道通过 Consul 动态发现的监控 Target 都会包含一些额外的 Metadata 标签,比如标签__meta_consul_dc 表明了当前实例所在的 Consul 数据中心,因此我们希望从这些实例中采集到的监控样本中也可以包含这样一个标签,例如:


node_cpu{cpu="cpu0",dc="dc1",instance="172.21.0.6:9100",job="consul_sd",mode="guest"}
复制代码


这样可以方便的根据 dc 标签的值,根据不同的数据中心聚合分析各自的数据。


在这个例子中,通过从 Target 实例中获取__meta_consul_dc 的值,并且重写所有从该实例获取的样本中。


完整的 relabel_config 配置如下所示:


# The source labels select values from existing labels. Their content is concatenated# using the configured separator and matched against the configured regular expression# for the replace, keep, and drop actions.[ source_labels: '[' <labelname> [, ...] ']' ]
# Separator placed between concatenated source label values.[ separator: <string> | default = ; ]
# Label to which the resulting value is written in a replace action.# It is mandatory for replace actions. Regex capture groups are available.[ target_label: <labelname> ]
# Regular expression against which the extracted value is matched.[ regex: <regex> | default = (.*) ]
# Modulus to take of the hash of the source label values.[ modulus: <uint64> ]
# Replacement value against which a regex replace is performed if the# regular expression matches. Regex capture groups are available.[ replacement: <string> | default = $1 ]
# Action to perform based on regex matching.[ action: <relabel_action> | default = replace ]
复制代码


其中 action 定义了当前 relabel_config 对 Metadata 标签的处理方式,默认的 action 行为为 replace。 replace 行为会根据 regex 的配置匹配 source_labels 标签的值(多个 source_label 的值会按照 separator 进行拼接),并且将匹配到的值写入到 target_label 当中,如果有多个匹配组,则可以使用{2}确定写入的内容。如果没匹配到任何内容则不对 target_label 进行重新。


repalce 操作允许用户根据 Target 的 Metadata 标签重写或者写入新的标签键值对,在多环境的场景下,可以帮助用户添加与环境相关的特征维度,从而可以更好的对数据进行聚合。


除了使用 replace 以外,还可以定义 action 的配置为 labelmap。与 replace 不同的是,labelmap 会根据 regex 的定义去匹配 Target 实例所有标签的名称,并且以匹配到的内容为新的标签名称,其值作为新标签的值。


例如,在监控 Kubernetes 下所有的主机节点时,为将这些节点上定义的标签写入到样本中时,可以使用如下 relabel_config 配置:


- job_name: 'kubernetes-nodes'  kubernetes_sd_configs:  - role: node  relabel_configs:  - action: labelmap    regex: __meta_kubernetes_node_label_(.+)
复制代码


而使用 labelkeep 或者 labeldrop 则可以对 Target 标签进行过滤,仅保留符合过滤条件的标签,例如:


relabel_configs:  - regex: label_should_drop_(.+)    action: labeldrop
复制代码


该配置会使用 regex 匹配当前 Target 实例的所有标签,并将符合 regex 规则的标签从 Target 实例中移除。labelkeep 正好相反,会移除那些不匹配 regex 定义的所有标签。

使用 keep/drop 过滤 Target 实例

在上一部分中我们介绍了 Prometheus 的 Relabeling 机制,并且使用了 replace/labelmap/labelkeep/labeldrop 对标签进行管理。而本节开头还提到过第二个问题,使用中心化的服务发现注册中心时,所有环境的 Exporter 实例都会注册到该服务发现注册中心中。而不同职能(开发、测试、运维)的人员可能只关心其中一部分的监控数据,他们可能各自部署的自己的 Prometheus Server 用于监控自己关心的指标数据,如果让这些 Prometheus Server 采集所有环境中的所有 Exporter 数据显然会存在大量的资源浪费。如何让这些不同的 Prometheus Server 采集各自关心的内容?答案还是 Relabeling,relabel_config 的 action 除了默认的 replace 以外,还支持 keep/drop 行为。例如,如果我们只希望采集数据中心 dc1 中的 Node Exporter 实例的样本数据,那么可以使用如下配置:


scrape_configs:  - job_name: node_exporter    consul_sd_configs:      - server: localhost:8500        services:          - node_exporter    relabel_configs:    - source_labels:  ["__meta_consul_dc"]      regex: "dc1"      action: keep
复制代码


当 action 设置为 keep 时,Prometheus 会丢弃 source_labels 的值中没有匹配到 regex 正则表达式内容的 Target 实例,而当 action 设置为 drop 时,则会丢弃那些 source_labels 的值匹配到 regex 正则表达式内容的 Target 实例。可以简单理解为 keep 用于选择,而 drop 用于排除。

使用 hashmod 计算 source_labels 的 Hash 值

当 relabel_config 设置为 hashmod 时,Prometheus 会根据 modulus 的值作为系数,计算 source_labels 值的 hash 值。例如:


scrape_configs- job_name: 'file_ds'  relabel_configs:    - source_labels: [__address__]      modulus:       4      target_label:  tmp_hash      action:        hashmod  file_sd_configs:  - files:    - targets.json
复制代码


根据当前 Target 实例 address 的值以 4 作为系数,这样每个 Target 实例都会包含一个新的标签 tmp_hash,并且该值的范围在 1~4 之间,查看 Target 实例的标签信息,可以看到如下的结果,每一个 Target 实例都包含了一个新的 tmp_hash 值:


利用 Hashmod 的能力在 Target 实例级别实现对采集任务的功能分区的:


scrape_configs:  - job_name: some_job    relabel_configs:    - source_labels: [__address__]      modulus:       4      target_label:  __tmp_hash      action:        hashmod    - source_labels: [__tmp_hash]      regex:         ^1$      action:        keep
复制代码


这里需要注意的是,如果 relabel 的操作只是为了产生一个临时变量,以作为下一个 relabel 操作的输入,那么我们可以使用 __tmp 作为标签名的前缀,通过该前缀定义的标签就不会写入到 Target 或者采集到的样本的标签中。

发布于: 刚刚阅读数: 3
用户头像

乌龟哥哥

关注

正在努力寻找offer的大四小菜鸟 2021-03-16 加入

擅长 Hbuilder、VS Code、MyEclipse、AppServ、PS 等软件的安装与卸载 精通 Html、CSS、JavaScript、jQuery、Java 等单词的拼写 熟悉 Windows、Linux、 等系统的开关机 看–时间过得多快,不说了,去搬砖了

评论

发布
暂无评论
Prometheus监控神器-自动发现篇_三周年连更_乌龟哥哥_InfoQ写作社区