Prometheus对标签的操作(五)
http://blog.51niux.com/?id=253 #紧接上文,觉得合一起博文有点长再开一篇。这篇承上启下主要为k8s容器监控做理论准备。
一、Prometheus配置文件官网翻译(可直接忽略)
1.1 官网配置文件介绍
<static_config>
static_config允许指定目标列表和目标的通用标签集。 这是在抓取配置中指定静态目标的规范方法。
#静态配置指定的目标。 targets: [ - '<host>' ] #分配给从目标中抓取的所有指标的标签。 labels: [ <labelname>: <labelvalue> ... ]
<relabel_config>
重新标记是功能强大的工具,可在scraped目标之前动态重写目标的标签集。 每个scraped配置可以配置多个重新标记步骤。 它们按照在配置文件中出现的顺序应用于每个目标的标签集。
最初,除了配置的每个目标标签外,目标的作业标签还设置为相应的抓取配置的job_name值。 __address__标签设置为目标的<host>:<port>地址。 重新标记后,如果在重新标记期间未设置实例标签,则默认情况下将其设置为__address__的值。 __scheme__和__metrics_path__标签分别设置为目标的方案和指标路径。__param_<name>标签设置为第一个传递的URL参数称为<name>的值。
在重新标记阶段,可能会加上以__meta_开头的其他标签。 它们由提供目标的服务发现机制设置,并且在机制之间有所不同。目标重新标记完成后,将从__ will的标签将从标签集中删除。如果重新标记步骤仅需要临时存储标签值(作为后续重新标记步骤的输入),请使用__tmp标签名称前缀。 保证该前缀不会被Prometheus自己使用。
#source标签从现有标签中选择值。 它们的内容使用配置的分隔符连接起来,并与配置的正则表达式匹配,以进行替换,保留和放置操作。 [ source_labels: '[' <labelname> [, ...] ']' ] #在连接的source标签值之间放置分隔符。 [ separator: <string> | default = ; ] #在替换操作中将结果值写入的标签。在替换操作中将结果值写入的标签。 [ target_label: <labelname> ] #与提取的值匹配的正则表达式。 [ regex: <regex> | default = (.*) ] #源标签值哈希值的取模。 [ modulus: <uint64> ] #如果正则表达式匹配,则执行正则表达式替换的替换值。 正则表达式捕获组可用。 [ replacement: <string> | default = $1 ] #基于正则表达式匹配执行的操作。 [ action: <relabel_action> | default = replace ]
<regex>是任何有效的RE2正则表达式。这是必需的replace, keep, drop, labelmap,labeldrop and labelkeep行动。 正则表达式固定在两端。 要取消锚定正则表达式,请使用.*<regex>.*。<relabel_action>确定要执行的重新标记操作:
replace: 将正则表达式与串联的source_labels匹配。然后,将target_label设置为replace,用替换中的匹配组引用(${1}, ${2}, ...)替换为其值。 如果正则表达式不匹配,则不会进行替换。 keep: 删除其正则表达式与串联的source_labels不匹配的目标。 drop: 删除其正则表达式与串联的source_labels匹配的目标。 hashmod: 将target_label设置为串联的source_labels的哈希的模数。 labelmap: 将正则表达式与所有标签名称匹配。 然后,将匹配标签的值复制到通过替换为它们的值替换的匹配组引用(${1}, ${2}, ...)给出的标签名称。 labeldrop: 将正则表达式与所有标签名称匹配。 任何匹配的标签将从标签集中删除。 labelkeep: 将正则表达式与所有标签名称匹配。 任何不匹配的标签将从标签集中删除。
必须谨慎对待labeldrop和labelkeep,以确保一旦删除标签,度量标准仍会唯一地进行标签。
<metric_relabel_configs>
ingestion前的最后一步是对样品进行公制重新标记。 它具有与目标重新标记相同的配置格式和操作。 指标重新标记不适用于自动生成的时间序列,例如up。这样做的一种用途是将太expensive而无法摄取的时间序列列入黑名单。
<alert_relabel_configs>
警报重新标记将应用于警报,然后再将其发送到Alertmanager。 它具有与目标重新标记相同的配置格式和操作。 警报重新贴标签在外部标签之后应用。一种用途是确保具有不同外部标签的HA对Prometheus服务器对发送相同的警报。
1.2 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添加自定义的标签。
一般来说,Target以__作为前置的标签是在系统内部使用的,因此这些标签不会被写入到样本数据中。不过这里有一些例外,例如,我们会发现所有通过Prometheus采集的样本数据中都会包含一个名为instance的标签,该标签的内容对应到Target实例的__address__
。 这里实际上是发生了一次标签的重写处理。
这种发生在采集样本数据之前,对Target实例的标签进行重写的机制在Prometheus被称为Relabeling。Prometheus允许用户在采集任务设置中通过relabel_configs来添加自定义的Relabeling过程。
1.3 action字段
可以用到的action以及对应所需的字段
动作 | 所需字段 | 介绍 |
---|---|---|
replace | regex source_labels target_label replacement | 根据正则匹配标签的值,替换标签target_label必须 |
keep | regex source_labels | 根据正则匹配标签的值保留数据采集源 |
drop | regex source_labels | 根据正则匹配标签的值剔除数据采集源 |
hashmod | source_labels target_label modulus | hash模式 |
labelmap | regex replacement | 根据正则匹配标签的名称进行映射 |
labeldrop | regex | 根据正则匹配标签的名称剔除标签 |
labelkeep | regex | 根据正则匹配标签的名称保留标签 |
博文来自:www.51niux.com
二、relabel_configs对标签实例操作
2.1 给target增加标签
# vim prometheus.yml
- job_name: 'prometheus' static_configs: - targets: [ 'localhost:9090'] labels: env: 'prod' __hostname__: 'localhost'
# curl -XPOST http://localhost:9090/-/reload
#从上图可以看到已经从原来的标签基础之上又增加了两个标签。要注意的是内部标签默认是不现实的,只有把鼠标移动到Labels那里才会显示。只有在Labels里面显示的标签才会出现在杨蓓数据中,也就是说比如我们的环境分为prod,dev,sandbox之类的,集群太多了区分不过来,我们想针对env这个变量做不同的报警区分,是一个不错的注意。
#要注意__这种开头的是不会写到metrics指标里面的,因为这属于系统内置标签。env这种没有__作为前缀的是可以写到metrics指标中的。
2.2 将target的初始标签里面的值替换到新的标签中
# vim prometheus.yml
- job_name: 'prometheus' static_configs: - targets: [ 'localhost:9090'] relabel_configs: - source_labels: [ '__address__' ] target_label: 'addr' - source_labels: [ '__metrics_path__' ] target_label: 'path'
#上面是一个例子,上面直接替换了两个标签,action那些都有默认值都可以先不加,如果只替换一个标签就不用写两个source_lables了,还有一点要注意,目标标签不能用__标签名__。
# curl -XPOST http://localhost:9090/-/reload
#上图在Service Discovery上面就可以看到替换效果了。
如果要替换成指定值呢?
relabel_configs:
- source_labels: [ '__address__' ]
target_label: 'addr'
replacement: 'localhost'
#上面就是将__address__替换成addr,然后再让addr=localhost
如果要正则匹配替换呢?
relabel_configs:
- source_labels: [ '__address__' ]
target_label: 'addr'
#regex: "(.*):.*" #如果只是取$1,那么这句话跟下面的意思一样
regex: "(.*):(.*)"
replacement: $1
#上面就是将localhost:9090通过正则截图成两段,然后将第一段交给replacement去替换addr的值也就是替换(localhost:9090)。这其实挺好的,比如我们配置targets的时候一般是IP:port的时候,不同的主机可能端口不一样,这时候我们想通过instance去匹配的话还要精确匹配其端口,如果做了正则替换我们就不用关心这个Nodeip的被采集端口是多少了。
#当然也可以使用下面的写法:
relabel_configs:
- action: replace
source_labels: [ '__address__' ]
regex: "(.*):(.*)"
replacement: $1
target_label: 'addr'
2.3 根据标签drop一下
#这里只是打个比方啊不要删哈。比方说我们有的job_name下面有个实例我想暂时想不采集了怎么办呢?
#可以通过graph界面查看一下我们有哪些Job,job也就是prom配置文件的job_name count by (job) ({job=~".+"})
# vim prometheus.yml
relabel_configs: - source_labels: ['instance'] action: drop
或者像下面写法:
relabel_configs: - action: drop source_labels: ['instance']
或者像下面写法:
relabel_configs: - source_labels: ['instance'] regex: "instance" #这里匹配不上,keep是丢弃 source_labels 的值中没有匹配到 regex 正则表达式内容的 Target 实例 action: keep
#这三种都可以,但是意义不大啊,不想采集这些节点了不在tagets那里填写不就好了吗,当然这里重要说的是这个drop,这个drop是把匹配到的标签的target直接将这些数据丢弃掉了,也就是不采集数据了。特别注意当你设置了drop之后,那么这个target在drop期间是没数据,但是不要担心历史数据还是再的,只是你drop的这段时间没有数据了。
博文来自:www.51niux.com
2.4 labelmap标签名替换
relabel_configs: - source_labels: [ '__metrics_path__' ] regex: __metrics_(.+)__ #这相当于将path截取出来作为新的标签名称 action: labelmap
#或者下面的方式
relabel_configs: - regex: __metrics_(.+)__ action: labelmap
#labelmap: 根据 regex 去匹配 Target 实例所有标签的名称(注意是名称),并且将捕获到的内容作为为新的标签名称,regex 匹配到标签的的值作为新标签的值.当然这个新的标签也会加到样本数据中。也就是你可以通过container_cpu_user_seconds_total{path="/metrics"} 进行查询
2.5 根据hashmod来选择采集哪些target
当relabel_config设置为hashmod时,Prometheus会根据modulus的值作为系数,计算source_labels值的hash值。
relabel_configs: - source_labels: [ '__address__' ] modulus: 10 target_label: tmp_hash action: hashmod
#根据当前Target实例__address__
的值以10作为系数,这样每个Target实例都会包含一个新的标签tmp_hash,并且该值的范围在1~10之间.看下图.比如我又三个实例,还是把这个系数搞大一点吧,这样tmp_hash的值不容易重复。
这时候比如我们想把tmp_hash=5这个的实例给drop掉(regex正则貌似对于IP那种正则匹配不好匹配上,通过这种可以屏蔽那个问题):
relabel_configs: - source_labels: [ '__address__' ] modulus: 10 target_label: tmp_hash action: hashmod - source_labels: [ 'tmp_hash' ] regex: "^5$" action: drop
#上面就是将tmp_hash是5的给target给drop掉。重启服务效果就可以看到了哈,这里就不截图了。
下面的写法也是可以的:
relabel_configs: - source_labels: [ '__address__' ] modulus: 10 target_label: tmp_hash action: hashmod - source_labels: [ 'tmp_hash' ] regex: "(^1$|^9$)" action: keep
#解决了吗?还没有结束虽然效果实现了,但是所有的数据里面都有了tmp_hash标签了如下图:
#所以可以首先用tmp_hash这种显示标签获得不同实例的值,然后得到instance对应的hash值之后,可以将tmp_hash改为__tmp_hash__,这样此通过该前缀定义的标签就不会写入到Target或者采集到的样本的标签中。如下面:
relabel_configs: - source_labels: [ '__address__' ] modulus: 10 target_label: __tmp_hash__ action: hashmod - source_labels: [ '__tmp_hash__' ] regex: "(^1$)" action: drop
#当然此例子只是为了演示一下hash_mod的作用。
2.6 labeldrop使用
#此操作并不是修改metric中的标签操作。
relabel_configs: - source_labels: - '__address__' - 'job' separator: _ target_label: test_id - regex: '(job)' action: labeldrop
#separator是分隔符,__address__和job的值就会用_做分割拼接在一起,然后传给test_id这个标签。这时候比如把job标签去掉。这时候再查询发现多了一个test_id标签,并且metrics数据中多了一个test_id的标签并且已经没有job标签了。当然labelkeep就相反了就不举例子了
三、metric_relabel_configs对拉取数据的操作
Prometheus 从数据源拉取数据后,会对原始数据进行编辑;其中 metric_relabel_configs是 Prometheus 在保存数据前的最后一步标签重新编辑(relabel_configs)。哪怕你将 metric_relabel_configs模块放在 job_name模块的最前端,Prometheus 解析编辑文件后,也会将 metric_relabel_configs放在最后。
metric_relabel_configs 模块和 relabel_config 模块很相似。metric_relabel_configs一个很常用的用途:将监控不需要的数据,直接丢掉,不在Prometheus 中保存。
3.1 删除不需要的metric
#还是以cAdvisor采集的数据为例。先介绍__name__ 标签,此标签是标识指标名称的预留标签。
metric_relabel_configs: - source_labels: [ __name__ ] regex: 'container_cpu_cfs_periods_total' action: drop
#如上面我们用不到这个container_cpu_cfs_periods_total,那么我们就可以不采集这个metric来节省空间了,特别强调是metric的名称而不是metric里面那些标签哦。这样你再通过:container_cpu_cfs_periods_total{job="cadvisor"} 已经查询不到数据了。
metric_relabel_configs: - source_labels: [ __name__ ] regex: 'container_cpu_cfs_.*' action: drop
#上面就是将container_cpu_cfs开头的metric全不采集了。
博文来自:www.51niux.com
3.2 修改指标(metric) 中的标签(label)
#比如有些标签是采集程序自己加上去的,我们想把这些各个程序采集的标签名改成统一的标签名也方便我们程序去做判断应该怎么弄呢?
- source_labels: [ 'container_label_io_kubernetes_pod_name' ] regex: (.+) target_label: pod_name replacement: $1 action: replace
#上面就是让metric标签中的container_label_io_kubernetes_pod_name这个标签的值赋给新的标签pod_name,但是不等于,则不会处理此label。再次强调必须是==这种完全匹配关系,不然新增标签是添加不了的,就算使用了separator: ; 如果只是单标签匹配也不会给新标签赋予;这个值,另外新标签也不会出现。
#如果批量多条呢?
- source_labels: [ 'container_label_io_kubernetes_pod_name' ] regex: (.+) target_label: pod_name replacement: $1 action: replace - source_labels: [ 'container_label_io_kubernetes_docker_type' ] regex: (.+) target_label: pod_type replacement: $1 action: replace
# curl -XPOST http://localhost:9090/-/reload
container_cpu_user_seconds_total{job="cadvisor"} #下面查询结果最后的一小部分: pod_name="kubernetes-dashboard-f9bd45cd6-6vk8n",pod_type="container"}
#如果要多条合并呢?
- source_labels: [ 'container_label_io_kubernetes_docker_type','container_label_io_kubernetes_container_name' ] regex: (.+) separator: ; target_label: pod_type replacement: $1 action: replace
#从上图可以看到把docker_type和container_name的值通过;分割合并到了一起。
#如果多条合并并不完全匹配会怎么样呢?
- source_labels: [ 'docker_type','container_name' ] regex: (.+) separator: ; target_label: pod_type replacement: $1 action: replace
下面是语句查询的结果:
pod_name="kubernetes-dashboard-f9bd45cd6-6vk8n",pod_type=";"}
#从上面的结果可以看到直接给了一个;,因为是有值的所以给pod_type标签一个;。
3.3 删除标签
#既然我们已经将metrics里面将老的标签里面的值赋予给了新的标签,那么是不是可以把老的标签去掉了呢?至少让我的prom界面显得简洁一点呢?
首先删除单个标签:
- regex: 'container_label_io_kubernetes_docker_type' action: labeldrop
然后删除多个标签:
- regex: 'container_label_io_kubernetes_docker_type' action: labeldrop - regex: '(container_label_io_kubernetes_container_logpath|container_label_io_kubernetes_container_name)' action: labeldrop
然后我想正则匹配删除标签呢?
- regex: container_label_io_kubernetes_.* action: labeldrop
然后我想多个正则匹配删除多个标签呢?
- regex: '(container_label_io_kubernetes_.*|container_label_annotation_io_kubernetes_.*)' action: labeldrop
#可以看到很多标签都删除消失了。什么时候把这些drop去掉了,再刷这些标签的值就又出现了,当然drop这段时间是没有的。