4 Relabeling
4.1 为何需要Relabel
通过前⾯的演示,我们知道Prometheus连接consul,就能⾃动地从Consul服务中获取已注册的实例信息,并对这些实例进⾏监控。后续Prometheus还会周期性的从Consul中获取最新的实例信息,已便能,动态的更新监控的⽬标列表。
但对于线上环境,我们通常将对服务器集群分成不同的环境,⽐如⽣产环境(prod)和测试环境(test)。这种划分就带来了⼏个额外的需求:
1、需要确保从每个实例抓取的监控指标都能够清晰地表明它所属的环境。这就需要在指标的标签中添加env=prod或env=test来实现,只有这样,我们才能对不同的环境进⾏分析
2、研发团队通常只关注测试环境的实例。因此我们需要⼀种⽅式来过滤实例,只将测试环境的实例提供给研发团队
3、如果我们为每个团队配置了独⽴的Prometheus服务器,我们就需要确保每个服务器只收集与该团队相关环境的监控实例。这意味着,我们需要在服务发现过程中进⾏配置,以便不同的Prometheus抓取不同环境的实例。
⾯对以上这些场景的需求,我们就希望Prometheus 能够根据特定的(规则)来筛选⽬标实例、或者是给⽬标实例添加不同维度的标签。具体来说,我们需要在抓取⽬标实例的指标之前,为⽬标实例增加“标签”来识别不同的环境。此外,我们还可以只抓取那些能匹配到“特定标签”的实例,⽽那些没有匹配到特定标签的实例则直接排除掉,不进⾏抓取。为了满⾜这种需求,Prometheus设计了⼀个强⼤的特性,叫标签重写,也被称为Relabel。
4.2 Relabel⼯作逻辑
relabel它可以在抓取⽬标实例数据之前,可以对⽬标实例的标签进⾏“灵活的改写”。借助Relabel,⽤户就可以⾃⾏定义复杂的“标签选择逻辑”,从⽽精准的控制哪些实例应当被监控,哪些实例应当被排除。例如,我们可以设置规则,仅抓取带有env=prod标签的⽬标实例数据,⽽那些不含此标签的实例则忽略掉 。
在Prometheus中,每个被监控的⽬标实例都有⼀组默认的元数据标签(Metadata),这些标签详细记录了⽬标实例的⼀些基本信息
- __address__ :记录了当前被监控⽬标实例的⽹络地址,通常由主机名和端⼝号。Prometheus抓取该⽬标的指标时会使⽤这个地址。
- __scheme__ :记录了抓取⽬标实例指标时应使⽤的HTTP协议类型, 通常是http或https。
- __metrics_path__ :记录了Prometheus抓取指标数据时会通过⽬标实例的那个URI路径获取指标数据。默认路径通常是/metrics。
- __param_<name> : 这是⼀种特殊的标签格式,⽤于在抓取时传递给⽬标服务的特定HTTP请求参数。<name>是请求参数的名称。
这些以__(双下划线) 开头的,都属于特殊标签,它们主要⽤于内部处理,通常不会出现在采集的指标标签中。不过,默认的Prometheus会为采集到的每⼀个实例⾃动添加⼀个 instance 标签,⽽这个instance 标签的值,其实就是从⽬标实例的内部__address__ 标签那⾥继承来的。这其实是⼀个标签重写的过程,也就是在数据采集之前,已经对⽬标实例的内部标签进⾏了⼀次Relabel操作。(Relabel后会将所有__开头的标签从标签集中删除。)
因此,Relabel功能提供了强⼤的标签定制能⼒,它允许我们对默认提供的元数据标签进⾏定制。我们可以更改标签、增加新的标签,或者保留那些满⾜特定条件标签的实例。从⽽使监控的⽬标实例更符合我们的具体需求。
4.3 Relabel配置示例
在每个relabel_configs 规则都包含了如下⼏个关键参数,它们共同决定了如何处理标签。以下是⼀个relabel_configs 的配置示例,它展示了如何提取源标签,进⾏匹配,并根据匹配结果决定保留还是丢弃⽬标:
scrape_configs:
- job_name: 'my_job'
# ... 其他配置 ...
relabel_configs:
# 规则 1: 重写实例标签的值
- source_labels: [__address__] # 使用 __address__ 作为源标签,它通常包含目标的 IP 地址和端口
regex: "(.*):10250" # 正则表达式匹配以 :10250 结尾的地址
replacement: "${1}:9100" # 将匹配到的地址的端口替换为 9100
action: replace # 动作,替换
target_label: instance # 替换后的地址赋值到 instance 标签
# 规则 2: 保留特定端口的目标实例
- source_labels: [__address__] # 同样使用 __address__ 作为源标签
regex: "(.*):80" # 正则表达式匹配以 :80 结尾的地址
action: "keep" # 如果地址匹配此正则,则保留该实例(不丢弃)
# 规则 3: 丢弃特定端口的目标实例
- source_labels: [__address__] # 再次使用 __address__ 作为源标签
regex: "(.*):8080" # 正则表达式匹配以 :8080 结尾的地址
action: "drop"
relabel_configs的配置语法
# 这是一个标签列表,其值将被用于后续的重标记操作。可以从原始目标的标签中选择一个或多个标签作为源。
[ source_labels: '[' <labelname> [, ...] ']' ]
# 当有多个 source_labels 时,这个参数定义了如何将它们的值合并在一起。如果没有指定,默认分隔符为分号(;)
[ separator: <string> | default = ; ]
# 正则表达式,用于匹配 source_labels 的值。如果没有指定,默认情况匹配任何字符串,即(.*)。
[ regex: <regex> | default = (.*) ]
# 如果正则表达式匹配成功,将通过replacement提取对应匹配的值。 如果没有指定,默认替换值为$1,即匹配到的整个字符串。
[ replacement: <string> | default = $1 ]
# 这定义了如果 regex 成功匹配,应该执⾏什么操作。操作可以是替换 (replace)、保留 (keep)、丢弃 (drop) 等。如果没有指定,默认操作是 replace。
[ action: <relabel_action> | default = replace ]
# 当执⾏替换操作时,这个参数定义了应该将对应的值写⼊到哪个标签中(可以是diy的一个名称)
[ target_label: <labelname> ]
relabel_action字段⽤于定义重新标记的⾏为,其可⽤取值如下:
- ⾸先拼接 source_labels 中指定的所有标签的值。
- 然后使⽤ regex 字段提供的正则表达式,对这个拼接后的字符串进⾏匹配。
- 如果匹配成功,就将regex匹配的结果,通过“后向引⽤”的⽅式赋予给 replacement
- 最后将replacement中保存的值,赋予给target_label 指定的标签。(可以对原有标签的覆盖,也可以是新创建的标签)
- keep、drop:⽤于删除或保留实例。
- keep:检查 source_labels 指定的标签,对应的值是否与 regex 匹配。当它们匹配时,这个⽬标实例才会被保留。
- drop:检查 source_labels 指定的标签,对应的值是否与 regex 匹配,当它们匹配时,这个⽬标实例才会被删除。
创建或删除标签
- labelmap:将regex对所有的标签名进⾏匹配判定,⽽后将匹配到的标签的值赋给replacement字段指定的标签名之上;通常⽤于取出匹配的标签名的⼀部分⽣成新标签;
- labeldrop:将regex对所有的标签名进⾏匹配判定,能够匹配到的标签将从该target的标签集中删除;
- labelkeep:将regex对所有的标签名进⾏匹配判定,不能匹配到的标签将从该target的标签集中删除;
注意:要确保在labeldrop或labelkeep操作后,余下的标签集依然能惟⼀标识该指标
5 Relabel实践案例
Prometheus 从 Consul 中发现端点时,它会获取每个服务实例的元数据标签。以下是⼀些由 Consul 服务发现,提供的元数据标签示例及其⽤途:
原标签 | 标签用途 |
__meta_consul_address Consul | 服务的地址。可以用来添加一个标签,指明服务的地址。 |
__meta_consul_dc | 表示服务所在的数据中心。这可以用来创建一个标签,以区分不同数据中心的指标。 |
__meta_consul_node | 服务所在的 Consul 节点信息。可以用于标识服务属于哪个节点。 |
__meta_consul_service_address | 服务的访问地址。 |
__meta_consul_service_id | 服务的唯一 ID。这个标签可以用来唯一标识服务实例。 |
__meta_consul_service_port | 服务的端⼝。 |
__meta_consul_service | 服务的名称。这个标签可以用来显示服务的友好名称。 |
__meta_consul_tags | 服务的标签信息。这些标签可以用来添加额外的上下文信息,比如环境、版本号等。 |
5.1 标签值替换replace
场景1
对 Consul 注册的服务实例添加不同维度的标签。具体来说,
1、从服务实例的 __meta_consul_tags 中提取地域信息,然后将对应的值赋予给 region 标签。
2、从服务实例的 __meta_consul_tags 中提取环境信息,然后将对应的值赋予给 env标签。
这样做有助于后续的指标分类,还能便于我们基于环境(如⽣产环境、测试环境)进⾏服务实例的筛选
2、配置Prometheus
- job_name: "consul_nodes"
consul_sd_configs:
- server: "192.168.137.131:8500"
#services: ["node_exporter"] # 限定仅从Consul的node_exporter这个Service发现实例信息(可不配置)
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: ',(.*),(.*),'
replacement: ${1}
target_label: region
- source_labels: [__meta_consul_tags]
regex: ',(.*),(.*),'
replacement: ${2}
target_label: env
3、验证结果
4、通过指标查询 ,会发现在每个指标上都附着了对应的标签
场景2
将三个不同的源标签(例如协议、服务地址、端⼝)合并成⼀个endpoint 标签。我们将按照特定的顺序将这些值串联起来,然后使⽤正则表达式匹配这个合并后的字符串。通过使⽤replacement 捕获匹配的结果,我们会对这个结果进⾏格式化处理,然后将其作为新的 endpoint 标签的值。
1、配置Prometheus
- source_labels: [__scheme__,__address__,__metrics_path__]
regex: '(http|https)(.*)'
separator: ""
replacement: ${1}://${2}
target_label: endpoints
2、检查结果
5.2 保留实例keep
场景1
保留从 Consul 服务中获取的所有实例,但端⼝是 9100 的节点。
1、编辑Prometheus配置⽂件
#仅保留端口为9100的节点
- source_labels: [__address__]
regex: '(.*):9100'
action: keep
2、验证结果
Consul自身报错节点给屏蔽了
场景2
添加⼀个新的 consul_node_prod 的Job,并配置 Prometheus只抓取那些在 __meta_consul_tags 标签中被标记为prod 的服务实例。并丢弃其他所有⾮Prod的实例。这样运维团队就可以专注于监控⽣产环境的指标数据。
1、修改Prometheus配置⽂件
- job_name: "consul_nodes_prod"
consul_sd_configs:
- server: "192.168.137.131:8500"
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: ',(.*),(.*),'
replacement: ${2}
target_label: env
- source_labels: [env]
regex: 'prod'
action: keep
2、验证结果
5.3 删除实例drop
场景1
将consul服务中注册的8300端⼝的实例,直接丢弃掉。
1、配置Prometheus,匹配源标签 __address__ ,将节点为8300的直接丢弃;
- source_labels: [__address__]
regex: '(.*):8300'
action: drop
2、验证结果
场景2
添加⼀个新的 consul_node_test 的Job,并配置 Prometheus只抓取那些在 __meta_consul_tags 标签中被标记为test 的服务实例。并丢弃其他所有⾮test的实例。这样研发团队就可以专注于监控test环境实例的指标数据
1、编辑Prometheus配置⽂件
- job_name: "consul_nodes_test"
consul_sd_configs:
- server: "192.168.137.131:8500"
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: ',(.*),(.*),'
replacement: ${2}
target_label: env
- source_labels: [env]
regex: 'prod'
action: drop
- source_labels: [__address__]
regex: '(.*):8300'
action: drop
#使用drop不如使用keep方便
2、检查结果
5.4 标签值映射labelmap
场景1
⽤regex正则表达式,对所有实例的标签进⾏匹配,匹配成功的标签将重命名,新标签名称由匹配到标签名,加上⼀个后缀 _name 构成,⽽“标签值”保持不变。
1、编辑Prometheus配置
- job_name: "consul_nodes_prod"
consul_sd_configs:
- server: "192.168.137.131:8500"
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: ',(.*),(.*),'
replacement: ${2}
target_label: env
- source_labels: [env]
regex: 'prod'
action: keep
- regex: "(job|env)"
replacement: "${1}_prod"
action: labelmap
2、验证结果
场景2
在使⽤Consul服务发现时,将所有以 __meta_consul_service_ 为前缀的标签提取出来,并⽣成新的标签, 但“标签值”任然不变
1、编辑Prometheus配置
- job_name: "consul_nodes_prod"
consul_sd_configs:
- server: "192.168.137.131:8500"
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: ',(.*),(.*),'
replacement: ${2}
target_label: env
- source_labels: [env]
regex: 'prod'
action: keep
- regex: "(job|env)"
replacement: "${1}_prod"
action: labelmap
- regex: "__meta_consul_service_(.*)"
replacement: "consul_${1}"
action: labelmap
2、验证结果