一、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支持多种服务发现,目前已经支持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定时读取文件若发生变化则加载新目标 |
[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】
bash
#创建一个json格式的服务发现文件
mkdir -p /usr/local/prometheus-3.5.0/targets
cd /usr/local/prometheus-3.5.0/targets
vi dev-server.json
#【dev-server.json】文件的完整内容如下:
[
{
"targets": ["192.168.1.9:9100","192.168.1.37:9100","192.168.1.39:9100"],
"labels": {
"env": "test"
"app": "dev-server"
}
}
]
2.2、或可创建.yml格式的服务发现文件
或者可以在【/usr/local/prometheus-3.5.0/targets】路径下创建一个yaml格式的服务发现文件【dev-server.yml】(注意:若内容相同,则.json与.yml格式的文件只需创建任意一种格式的文件即可,不用两个都创建)。
bash
#创建一个yaml格式的服务发现文件
mkdir -p /usr/local/prometheus-3.5.0/targets
cd /usr/local/prometheus-3.5.0/targets
vi dev-server.yml
#【dev-server.yml】文件的完整内容:
- targets:
- "192.168.1.9:9100"
- "192.168.1.37:9100"
- "192.168.1.39:9100"
labels:
env: test
app: "dev-server"
说明:
《1》.yaml 和 .yml 是 YAML 文件的两种扩展名,语法、功能完全一致,仅为命名习惯差异。
《2》.yaml 是官方推荐格式,.yml 是简写形式(兼容老式文件系统),在 Prometheus 中均可正常使用。
《3》实际项目中建议统一扩展名,优先选择 .yml(简洁且符合行业通用习惯)。


2.3、prometheus配置文件新增基于文件服务发现的配置
在prometheus.yml配置文件中新增文件的服务发现配置
bash
#在prometheus.yml配置文件中新增文件的服务发现配置
#1-进入prometheus.yml文件路径并编辑
cd /usr/local/prometheus-3.5.0/
vi prometheus.yml
#2-【prometheus.yml】文件末尾的【scrape_configs:】下新增基于文件发现的配置
- job_name: "node_service_discovery"
file_sd_configs:
- files:
- targets/*.json
refresh_interval: 60s
- files:
- targets/*.yml
refresh_interval: 60s
#3-#验证修改后的prometheus.yml文件的语法是否正确(结果显示SUCCESS则表示正确)
./promtool check config prometheus.yml
#验证prometheus.yml文件中的语法正确后热重载让配置生效
curl -XPOST localhost:9090/-/reload
说明:
《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常用参数 | 说明 |
| 1 | source_labels | 源标签,没有经过relabel处理之前的名字 |
| 2 | target_labels | 通过action处理之后的新标签名字 |
| 3 | regex | 正则表达式,匹配源标签 |
| 4 | replacement | 通过分组替换后标签(target_label)对应的值 |
| 5 | action | 执行的动作 支持replace、drop、keep、labelmap、labeldrop、labelkeep、hashmod |
[relabel_configs的常用参数]
|--------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| 序号 | 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 标签进行过滤,会移除不匹配过滤条件的所有标签 |
[action中每个relabel_action参数的含义]
3.2.1、示例一:给target增加标签
如:给job_name为prometheus新增标签【env】【hostname】内容:
bash
#给target增加标签
cd /usr/local/prometheus-3.5.0/
vi prometheus.yml
#示例:给job_name为prometheus新增标签【env】【__hostname__】内容:
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: "prometheus"
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ["localhost:9090",'192.168.1.39:9100','192.168.1.36:9100','192.168.1.37:9100',"192.168.1.25:9100"]
# The label name is added as a label `label_name=<label_value>` to any timeseries scraped from this config.
labels:
app: "prometheus"
env: "cktest"
__hostname__: "cklocalhost"
#验证修改后的prometheus.yml文件的语法是否正确(结果显示SUCCESS则表示正确)
./promtool check config prometheus.yml
#验证prometheus.yml文件中的语法正确后热重载让配置生效
curl -XPOST localhost:9090/-/reload




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




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

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



