Relabelingrelabeling是配置Prometheusmeta信息的方式。它是Prometheus中转换和过滤标签对象的核心。在本文中,我们将了解Relabeling规则的工作原理以及它们在不同场景中的应用。概述Prometheus发现、抓取和处理不同类型的标签对象。根据标签值来操作或过滤这些对象是非常有用的,例如:只监视某些带有特定服务发现注释的目标,通常用于服务发现。该请求添加一个HTTP查询参数以仅存储从指定目标抽取的样本子集将获取的序列的两个标签值合并为一个标签重新标记被实现为我们可以在Prometheus的配置中应用的一系列转换步骤files要过滤或修改标记对象,我们可以将Relabeling操作应用于以下类型的标记对象:发现的爬取目标(relabel_configs)爬取的单个样本(metric_relabel_configs)发送到Alertmanager的警报(alert_relabel_configs)写入远程存储的样本(write_relabel_configs)全部这些重新标记的配置块中有一部分是相同类型的relabel_config,并且每个配置块都包含一个规则列表,这些规则依次应用于每个标记的对象。例如,重新标记规则可以根据正则表达式的匹配保留或丢弃一个对象,它可以修改它的标签,或者它可以将整个标签集映射到另一组标签。一旦重新标记步骤决定丢弃标记的对象,将不会对该对象执行进一步的重新标记步骤,并将其从输出列表中删除。隐藏标签和元数据以双下划线__开头的标签是特殊标签,重新标记后将被删除。被标注对象的来源最初可以附加这些隐藏标签以提供关于被标注对象的附加元数据,并且这些特殊标签可用于在重新标注阶段修改对象的标签。对于抓取指标,有一些隐藏的标签可以用来控制目标应该如何抓取。__address__:包含应抓取的目标的地址。它最初是由服务发现机制默认提供的:,如果实例标签instance在这之前没有明确设置为其他值,在relabeling之后,Prometheus会将实例标签设置为__address__的值。__scheme__:爬取目标的请求方式,包括http和https,默认为http。__metrics_path__:表示用于收集指标的HTTP路径,默认为/metrics。__param_:包含HTTP查询参数名称及其值。上面的所有这些标签都可以使用重新标记规则进行设置或覆盖,从而允许对抓取目标进行自定义抓取行为。此外,服务发现机制还可以提供一组以__meta_开头的标签,其中包含有关目标的特定发现元数据。例如,当在Kubernetes集群中发现Pod时,Kubernetes服务发现引擎会为每个Pod目标提供一个包含被发现的Pod名称的__meta_kubernetes_pod_name标签,以及一个指示Pod是否处于就绪状态的__meta_kubernetes_pod_ready标签,关于服务发现生成的meta标签,请参考官方文档https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config了解更多。如果一个relabeling步骤需要保存一个值到一个临时标签中(用于后续步骤中的处理),那么我们可以使用__tmp标签名称前缀来标记,用__tmp打开的标签不会被Prometheus本身使用。重新标记规则重新标记规则主要由以下配置属性组成,但只有这些字段的子集用于每种类型的操作。action:要执行的relabeling动作,可选值包括replace、keep、drop、hashmod、labelmap、labeldrop或labelkeep,默认值为replace。separator:分隔符,用于在源标签source_labels连接时分隔它们的字符串,默认为;。source_labels:源标签,使用配置的分隔符连接的标签名称列表,并与提供的正则表达式匹配。target_label:目标标签,当使用replace或hashmod动作时,应该被覆盖的标签名称。regex:用于匹配串联源标签的正则表达式,默认为(.*),匹配任何源标签。modulus:模数,级联源标签哈希值的模数,主要用于Prometheus水平分片。replacement:替换字符串,写在目标标签上,用于替换relabeling动作,可以参考regex捕获的正则表达式捕获组。设置或替换标签值Relabeling的一个常见操作是设置或覆盖标签的值。我们可以通过替换操作来做到这一点。如果未指定操作字段,则默认为替换。replaceaction的规则配置如下:action:replacesource_labels:[]separator:#Defaultis';'regex:#Defaultis'(.*)'(matchanyvalue))replacement:#默认为'$1'(使用第一个捕获组作为替换)target_label:操作执行按照顺序执行以下步骤:使用提供的分隔符分隔符连接source_labels中的标签列表值测试regex中的正则表达式是否与上一步连接的字符串匹配。如果不匹配,则跳到下一个重新标记规则而不替换任何内容。如果正则表达式匹配,则提取正则表达式捕获组中的值并将替换字符串中对这些组的引用(2,...)替换为它们的值。被正则表达式替换的替换字符串被存储为target_label标签的新值。让我们简单看一下替换操作的示例。.设置固定标签值的最简单替换示例是将标签设置为固定值。比如你可以设置env标签为production:action:replacereplacement:productiontarget_label:env这里我们没有设置rule的大部分属性。这是因为这里的大部分默认值已经可以满足需求了。这里将替换后的字符串production作为target_label标签env的新值进行存储,即env标签的值将设置为production。替换抓取任务端口另一个稍微复杂一点的例子是重写一个抓取任务实例的端口,我们可以用固定的80端口替换__address__标签的端口:action:replacesource_labels:[__address__]regex:([^:]+)(?::\d+)?#第一个捕获组匹配主机,第二个捕获组匹配端口。replacement:"$1:80"target_label:__address__这里我们将源标签替换为__address__,然后通过正则表达式匹配([^:]+)(?::\d+)?,这里有两个捕获组,第一个匹配的是host(,第二个匹配的是端口2),所以替换字符串中我们保留第一个捕获组$1,然后把端口改成80,这样__address__的实例就把端口改成80端口,然后重写__address__目标标签。保留或丢弃对象Relabeling的另一个常见用例是过滤标记的对象。keepordrop两个动作都可以完成。使用这两个操作可以帮助我们完成以下操作:服务发现的哪些目标应该从目标中抓取哪些指定的序列样本,或者发送到远程存储,哪些告警发送到Alertmanager一个keepaction的配置规则如下如下:action:keepsource_labels:[]separator:#默认为';'regex:#默认为'(.*)'(匹配任意值)keep操作也按顺序执行以下步骤:使用分隔符分隔符连接source_labels中列出的标签值来测试是否regex中的正则表达式匹配上一步中的连接字符串?否则,该对象将从最终输出列表中删除。如果匹配,则保留该对象。drop操作与keep类似,只是它删除一个对象而不是保留它。另请查看接下来的保留和删除示例。只抓取带有注释的目标在服务发现过程中,我们可能只想抓取带有特定元数据标签的目标。例如,下面的配置允许我们在Kubernetes中只抓取注解example.io/should_be_scraped=true的目标。action:keepsource_labels:[__meta_kubernetes_service_annotation_example_io_should_be_scraped]regex:true在Kubernetes服务发现机制下,标签和注解会作为元信息输出到Prometheus。这些元信息都包含__meta_前缀。这里我们的配置是保留带有example.io/should_be_scraped标签的注释,目标值为true。只存储特定的指标当使用metric_relabel_configs来控制如何爬取目标时,我们可以使用以下规则只存储名称以api_或http_开头的指标。action:keepsource_labels:[__name__]regex:"(api_|http_).*"标签映射有时我们可能希望将源标签的值映射到一组新标签。这时候我们可以使用labelmap动作。labelmap最常见的使用场景是从服务发现中获取一组隐藏的或临时的元数据标签,并将其映射到新的目标标签上。labelmapaction的配置规则如下:action:labelmapregex:#默认为'(.*)'replacement:#默认为'$1'与之前的一些action不同,labelmap是针对标签名称而不是标签值被重新匹配和操作。labelmap按顺序执行以下步骤:将regex中的正则表达式与所有标签名称匹配将匹配的标签名称的任何匹配值复制到由替换字符串确定的新标签名称让我们看一个使用labelmap的Kubernetes映射服务标签示例.在使用基于Kubernetes的服务发现来发现pod端点时,我们可能希望每个端点的最终目标标签也包含KubernetesService标签,这样可以更好地区分端点数据。Kubernetes服务发现机制会将这些标签添加到Prometheus中。标签名称的格式为__meta_kubernetes_service_label_。我们可以提取其中的一些元数据标签,将对应的标签值映射到上面一组以k8s_为前缀的新标签名,如下图:action:labelmapregex:__meta_kubernetes_service_label_(.+)replacement:"k8s_$1"通过上面labelmap操作,匹配regex正则表达式中的标签名,然后将标签名对应的值复制到k8s_$1的新标签中,$1为匹配标签名的捕获组。保留或删除标签有时我们也需要保留或删除一些标签。例如,一些目标在时间序列上提供了许多额外的标签。这些标签用处不大。这时候我们可以使用labelkeep和labeldrop。操作,使用这两个操作来选择性地保留或删除一些标签。labelkeep的配置规则如下:action:labelkeepregex:#默认为'(.*)',labelkeep按顺序执行以下步骤:首先,将regex中的正则表达式与所有标签名称进行匹配,并且只keep那些匹配的标签labeldrop和labelkeep类似,只是它删除那些匹配正则表达式的标签而不是保留它们。让我们看一个简单的labelkeep/labeldrop操作示例。从警报中删除HA副本标签当为HA运行两个相同的Prometheus时,通常两个服务器都配置有一个外部标签(通过全局配置选项external_labels)指示它们代表哪个副本,例如:副本:A和副本:B,之前从两个副本发送警报到同一个Alertmanager实例,Prometheus需要删除副本标签,这样Alertmanager就不会把收到的警报当作不同的警报,否则我们可能会收到两个相同的警报通知。这时候我们可以使用labeldrop来实现这个操作。配置规则action:labeldropregex:replica很简单,就是匹配replica的标签,然后执行labeldrop的动作删除标签。删除指标中不必要的标签有时我们抓取的指标会在每个时间序列上附加一些额外的标签。这些标签对我们来说用处不大,会增加Prometheus的存储压力,所以我们可以想办法去掉多余的不需要的标签。比如现在我们要删除一个以info_开头的标签,可以使用如下配置规则来实现。action:labeldropregex:info_.*也只是配置一个要删除的目标标签的正则表达式。只要匹配到label,就会执行labeldrop操作删除label。标签哈希和分片在某些场景下,我们可能需要运行多个几乎相同的Prometheus副本进行横向扩展,每个副本只抓取目标的一部分,这样可以减轻Prometheus的压力,此时hashmod操作有助于我们的分片目标上的操作。hashmod的配置规则如下:action:hashmodsource_labels:[]modulus:target_label:该操作依次执行以下步骤:首先,使用分隔符将source的values拼接起来labelsetsource_labels计算拼接字符串的Hash将modulus中提供的模数应用到hash值,限制hash值在0和modulus-1之间将上一步的模值存储在target_label中targetlabel使用的hashmod的主要场景是通过首先根据每个目标的一个或多个标签计算一个基于散列的模数,然后只保留该目标为模值来对一个服务的整体目标进行分片,从而实现Prometheus的水平扩展。例如,为了根据实例标签对目标进行分片,只保留分片2的实例,我们可以结合hashmod和keep。-action:hashmodsource_labels:[instance]modulus:10target_label:__tmp_hashmod-action:keepsource_labels:[__tmp_hashmod]regex:2首先将实例标签通过hashmod运算进行哈希处理,取模值存放在临时标签__tmp_hashmod中。然后通过第二次keep操作,只保留分片数为2的指标,从而达到分片的目的。至此我们基本了解了relabeling的使用,接下来我们可以了解一下Prometheus中服务发现的使用。