一、prometheus的服务发现机制
1.1、prometheus的服务发现机制概述
prometheus是基于拉(pull)模式抓取监控数据,首先要能够发现需要监控的目标对象target,那么prometheus如何获监控目标呢?有两种方式【静态手动配置】与【动态服务发现配置】:
《1》对于小型的系统环境来说,通过static_configs静态指定各Target便能解决问题,这就是最简单的静态手动配置。
《2》prometheus最开始设计是一个面向云原生应用程序的,云原生、容器场景下按需的资源使用方式,对于监控系统而言就意味着没有一个固定的监控目标,所有的监控对象(基础设施、应用、服务)都在动态的变化。因此,对于有较强动态性的云环境来说,静态配置显然难以适用,于是就出现了动态服务发现机制。
为了适应【静态】与【动态】发现机制,prometheus引入了一个中间代理人(服务注册中心),这个代理人掌握着当前所有监控目标的访问信息,prometheus只需要向这个代理人询问有哪些监控目标即可,这种模式被称为服务发现(service discovery)。SD模块专门负责去发现需要监控的target信息,prometheus则从SD模块订阅该信息,有target信息就会推送给prometheus,然后prometheus拿到target信息后通过pull http协议去拉取监控指标数据。如下图所示:

1.2、prometheus支持多种服务发现
prometheus支持多种服务发现
| prometheus支持多种服务发现,目前已经支持20多种服务发现协议,如下是常用的5种: | ||
|---|---|---|
| 序号 | prometheus常用的服务发现协议 | 说明 |
| 1 | kubernetes_sd_configs | kubernetes服务发现 让prometheus动态发现kubernetes中被监控的目标 |
| 2 | static_configs | 静态服务发现 基于prometheus配置文件指定监控目标 |
| 3 | dns_sd_configs | DNS服务发现监控目标 |
| 4 | consul_sd_configs | Consul服务发现 基于consul服务动态发现监控目标 |
| 5 | file_sd_configs | 文件服务发现 prometheus定时读取文件若发生变化则加载新目标 |
1.3、静态服务发现
静态服务发现机制(是直接将监控目标写死在prometheus.yml配置文件中)虽然配置简单,但是若要新增、修改、删除监控节点时,需要每次都去修改配置文件,然后再通知prometheus重载让配置生效,这样操作就十分麻烦,且有可能会对已有的监控内容造成影响;因此就出现了动态服务发现。
【静态服务发现更适合小型的系统环境】。
二、prometheus的动态服务发现——基于文件的服务发现
通过定义一组资源“子”配置文件,yaml格式文件里面只存储需要采集的targets信息,此种方式可以被prometheus实时动态获取,而不需要重启prometheus服务。
2.1、可创建.json格式的服务发现文件
在【/usr/local/prometheus-3.5.0/targets】路径下创建一个json格式的服务发现文件【dev-server.json】
1#创建一个json格式的服务发现文件 2mkdir -p /usr/local/prometheus-3.5.0/targets 3cd /usr/local/prometheus-3.5.0/targets 4vi dev-server.json 5 6#【dev-server.json】文件的完整内容如下: 7[ 8 { 9 "targets": ["192.168.1.9:9100","192.168.1.37:9100","192.168.1.39:9100"], 10 "labels": { 11 "env": "test" 12 "app": "dev-server" 13 } 14 } 15]
2.2、或可创建.yml格式的服务发现文件
或者可以在【/usr/local/prometheus-3.5.0/targets】路径下创建一个yaml格式的服务发现文件【dev-server.yml】(注意:若内容相同,则.json与.yml格式的文件只需创建任意一种格式的文件即可,不用两个都创建)。
1#创建一个yaml格式的服务发现文件 2mkdir -p /usr/local/prometheus-3.5.0/targets 3cd /usr/local/prometheus-3.5.0/targets 4vi dev-server.yml 5 6#【dev-server.yml】文件的完整内容: 7- targets: 8 - "192.168.1.9:9100" 9 - "192.168.1.37:9100" 10 - "192.168.1.39:9100" 11 labels: 12 env: test 13 app: "dev-server"
说明:
《1》.yaml 和 .yml 是 YAML 文件的两种扩展名,语法、功能完全一致,仅为命名习惯差异。
《2》.yaml 是官方推荐格式,.yml 是简写形式(兼容老式文件系统),在 Prometheus 中均可正常使用。
《3》实际项目中建议统一扩展名,优先选择 .yml(简洁且符合行业通用习惯)。


2.3、prometheus配置文件新增基于文件服务发现的配置
在prometheus.yml配置文件中新增文件的服务发现配置
1#在prometheus.yml配置文件中新增文件的服务发现配置 2 3#1-进入prometheus.yml文件路径并编辑 4cd /usr/local/prometheus-3.5.0/ 5vi prometheus.yml 6 7#2-【prometheus.yml】文件末尾的【scrape_configs:】下新增基于文件发现的配置 8 - job_name: "node_service_discovery" 9 file_sd_configs: 10 - files: 11 - targets/*.json 12 refresh_interval: 60s 13 - files: 14 - targets/*.yml 15 refresh_interval: 60s 16 17#3-#验证修改后的prometheus.yml文件的语法是否正确(结果显示SUCCESS则表示正确) 18./promtool check config prometheus.yml 19 20#验证prometheus.yml文件中的语法正确后热重载让配置生效 21curl -XPOST localhost:9090/-/reload 22
说明:
《1》【file_sd_configs】是指定prometheus基于文件的服务发现配置;
《2》【files】是自定义的和prometheus程序同级目录的targets目录,要被自动加载的所有.json与.yml格式文件;也可以单独指定某一个json格式文件。
《3》【refresh_interval】是自定义刷新间隔,这里指定为60秒。

**注意:**在编写.json或.yml文件后,我们到prometheus的web界面【ip:9090】的status-->Target health查看若等待配置的时间间隔后还是没有显示,则需要查看日志【tailf -f /var/log/messages】即可确定错误消息;像这种情况一般都是由于配置的格式不对导致的。
三、prometheus中的标签重写
3.1、prometheus中标签的概念
在prometheus所有的Target监控实例中,都包含一些默认的Metadata标签信息。可以通过prometheus的Web UI界面中的status-->Target health界面中查看到这些实例的元数据标签内容,默认情况下,当prometheus加载Target实例完成后,这些Target都会包含一些默认的标签:
《1》【__address__】当前Target实例的访问地址<host>:<port>;
《2》【__scheme__】采集目标服务访问地址的HTTP Scheme,HTTP或HTTPS;
《3》【__metrics_path__】采集目标服务访问地址的访问路径;
《4》【__param_<name>__】采集任务目标服务中包含的请求参数。
一般来说,Target以两个下划线开头与结尾(__)的标签是在系统内部使用的,因此这些标签不会被写入到样本数据中。不过这里有一些例外,比如:指标上的instance标签的默认值就来自于_address__标签的值。这里实际上是发生了一次标签的重写处理。
这种发生在采集样本数据之前,对Target实例的标签进行重写的机制在Prometheus被称为Relabeling。Prometheus允许用户在采集任务中设置通过relabel_configs来添加自定义的Relabeling过程。
如下图所示:

3.2、relabel_configs的使用
relabel_configs的常用参数
| 序号 | relabel_configs常用参数 | 说明 |
|---|---|---|
| 1 | source_labels | 源标签,没有经过relabel处理之前的名字 |
| 2 | target_labels | 通过action处理之后的新标签名字 |
| 3 | regex | 正则表达式,匹配源标签 |
| 4 | replacement | 通过分组替换后标签(target_label)对应的值 |
| 5 | action | 执行的动作 支持replace、drop、keep、labelmap、labeldrop、labelkeep、hashmod |
action中每个relabel_action参数的含义
| 序号 | relabel_action参数 | 说明 |
|---|---|---|
| 1 | replace | 根据 regex 的配置,匹配 source_labels 标签的值,并且将匹配到的值写入到 target_label 当中,如果有多个匹配组,则可以使用 ${1}, ${2} 确定写入的内容。如果没匹配到任何内容,则不对 target_label 进行重新, 默认为 replace。 |
| 2 | keep | 丢弃 source_labels 的值中没有匹配到 regex 正则表达式内容的 Target 实例 |
| 3 | drop | 丢弃 source_labels 的值中匹配到 regex 正则表达式内容的 Target 实例 |
| 4 | hashmod | 将 target_label 设置为关联的 source_label 的哈希模块 |
| 5 | labelmap | 根据 regex 去匹配 Target 实例所有标签的名称(注意是名称),并且将捕获到的内容作为新的标签名称,regex 匹配到标签的的值,作为新标签的值 |
| 6 | labeldrop | 对 Target 标签进行过滤,会移除匹配过滤条件的所有标签 |
| 7 | labelkeep | 对 Target 标签进行过滤,会移除不匹配过滤条件的所有标签 |
3.2.1、示例一:给target增加标签
如:给job_name为prometheus新增标签【env】【__hostname__】内容:
1#给target增加标签 2 3cd /usr/local/prometheus-3.5.0/ 4vi prometheus.yml 5 6#示例:给job_name为prometheus新增标签【env】【__hostname__】内容: 7scrape_configs: 8 # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. 9 - job_name: "prometheus" 10 11 # metrics_path defaults to '/metrics' 12 # scheme defaults to 'http'. 13 14 static_configs: 15 - targets: ["localhost:9090",'192.168.1.39:9100','192.168.1.36:9100','192.168.1.37:9100',"192.168.1.25:9100"] 16 # The label name is added as a label `label_name=<label_value>` to any timeseries scraped from this config. 17 labels: 18 app: "prometheus" 19 env: "cktest" 20 __hostname__: "cklocalhost" 21 22 23#验证修改后的prometheus.yml文件的语法是否正确(结果显示SUCCESS则表示正确) 24./promtool check config prometheus.yml 25 26#验证prometheus.yml文件中的语法正确后热重载让配置生效 27curl -XPOST localhost:9090/-/reload




**注意:**内部标签默认是不显示的,只有把鼠标点击下标箭头展开才会显示。同时,要注意双下划线(__)开头与结尾的标签是不会写到metrics指标里面的,因为这属于系统内置标签。env这种没有__作为前缀的,是可以写到metrics指标中的。
3.2.2、示例二:将target的初始标签里面的值替换到新的标签中
1#将target的初始标签里面的值替换到新标签中 2 3cd /usr/local/prometheus-3.5.0/ 4vi prometheus.yml 5 6#示例二:将初始的【__address__】值替换到新标签addr中;初始的【__metrics_path__】的值替换到新标签metrics_path中 7scrape_configs: 8 # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. 9 - job_name: "prometheus" 10 11 # metrics_path defaults to '/metrics' 12 # scheme defaults to 'http'. 13 14 static_configs: 15 - targets: ["localhost:9090",'192.168.1.39:9100','192.168.1.36:9100','192.168.1.37:9100',"192.168.1.25:9100"] 16 # The label name is added as a label `label_name=<label_value>` to any timeseries scraped from this config. 17 labels: 18 app: "prometheus" 19 relabel_configs: 20 - source_labels: ["__address__"] 21 target_label: "addr" 22 - source_labels: ["__metrics_path__"] 23 target_label: "metrics_path" 24 25 26#验证修改后的prometheus.yml文件的语法是否正确(结果显示SUCCESS则表示正确) 27./promtool check config prometheus.yml 28 29#验证prometheus.yml文件中的语法正确后热重载让配置生效 30curl -XPOST localhost:9090/-/reload




1#将target的初始标签里面的值替换到新标签中 2 3cd /usr/local/prometheus-3.5.0/ 4vi prometheus.yml 5 6#示例二:将初始的【__address__】值替换到新标签addr中,且通过正则以冒号分割为两个部分,将addr的值修改为只取正则分割后的第一个部分;初始的【__metrics_path__】的值替换到新标签 7 8scrape_configs: 9 # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. 10 - job_name: "prometheus" 11 12 # metrics_path defaults to '/metrics' 13 # scheme defaults to 'http'. 14 15 static_configs: 16 - targets: ["localhost:9090",'192.168.1.39:9100','192.168.1.36:9100','192.168.1.37:9100',"192.168.1.25:9100"] 17 # The label name is added as a label `label_name=<label_value>` to any timeseries scraped from this config. 18 labels: 19 app: "prometheus" 20 relabel_configs: 21 - source_labels: ["__address__"] 22 target_label: "addr" 23 regex: "(.*):(.*)" 24 replacement: $1 25 - source_labels: ["__metrics_path__"] 26 target_label: "metrics_path" 27 28 29#验证修改后的prometheus.yml文件的语法是否正确(结果显示SUCCESS则表示正确) 30./promtool check config prometheus.yml 31 32#验证prometheus.yml文件中的语法正确后热重载让配置生效 33curl -XPOST localhost:9090/-/reload

3.2.3、示例三:使用labelmap标签名替换
【labelmap】 根据 regex 去匹配 Target 实例所有标签的名称(注意是名称),并且将捕获到的内容作为为新的标签名称,regex 匹配到标签的的值作为新标签的值.当然这个新的标签也会加到样本数据中。
1#使用labelmap标签名替换 2 3cd /usr/local/prometheus-3.5.0/ 4vi prometheus.yml 5 6#示例:首先使用正则表达式进行匹配,然后使用labelmap对正则表达式匹配到的标签名作为新的标签,新标签的值为原标签对应的值 7 8scrape_configs: 9 # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. 10 - job_name: "prometheus" 11 12 # metrics_path defaults to '/metrics' 13 # scheme defaults to 'http'. 14 15 static_configs: 16 - targets: ["localhost:9090",'192.168.1.39:9100','192.168.1.36:9100','192.168.1.37:9100',"192.168.1.25:9100"] 17 # The label name is added as a label `label_name=<label_value>` to any timeseries scraped from this config. 18 labels: 19 app: "prometheus" 20 relabel_configs: 21 - source_labels: ["__address__"] 22 target_label: "addr" 23 regex: "(.*):(.*)" 24 replacement: $1 25 - source_labels: ["__metrics_path__"] 26 regex: __metrics_(.+)__ 27 action: labelmap 28 - regex: __scrape_(.+)__ 29 action: labelmap 30 31 32#验证修改后的prometheus.yml文件的语法是否正确(结果显示SUCCESS则表示正确) 33./promtool check config prometheus.yml 34 35#验证prometheus.yml文件中的语法正确后热重载让配置生效 36curl -XPOST localhost:9090/-/reload




《Prometheus+Grafana构建云原生分布式监控系统(十)_prometheus的服务发现机制(一)》 是转载文章,点击查看原文。
