在 Prometheus 中将实例重新标记为主机名

Posted

技术标签:

【中文标题】在 Prometheus 中将实例重新标记为主机名【英文标题】:Relabel instance to hostname in Prometheus 【发布时间】:2018-09-28 12:48:03 【问题描述】:

我有 Prometheus 从几台机器上的节点导出器抓取指标,配置如下:

scrape_configs:
  - job_name: node_exporter
    static_configs:
      - targets:
        - 1.2.3.4:9100
        - 2.3.4.5:9100
        - 3.4.5.6:9100

在 Grafana 中查看时,这些实例被分配了相当无意义的 IP 地址;相反,我更愿意看到他们的主机名。我认为您应该能够重新标记instance 标签以匹配节点的主机名,所以我尝试使用这样的重新标记规则,但没有任何效果:

relabel_configs:
  - source_labels: ['nodename']
    target_label: 'instance'

我可以手动重新标记每个目标,但这需要将每个主机名硬编码到 Prometheus 中,这不是很好。我看到节点导出器提供了包含主机名的指标node_uname_info,但我如何从那里提取它?

node_uname_infodomainname="(none)",machine="x86_64",nodename="myhostname",release="4.13.0-32-generic",sysname="Linux",version="..." 1

【问题讨论】:

【参考方案1】:

我刚遇到这个问题,解决方案是使用 group_left 来解决这个问题。您不能在请求中使用不存在的值重新标记,您仅限于提供给 prometheus 的不同参数或用于请求的模块中存在的参数(gcp、aws...)。

所以我使用的解决方案是将包含我们想要的内容(主机名)的现有值与来自节点导出器的指标相结合。我们的答案存在于 node_uname_info 指标中,其中包含 nodename 值。

我使用这篇文章的答案作为我请求的模型:https://***.com/a/50357418。

解决办法是这样的:

node_memory_Active * on(instance) group_left(nodename) (node_uname_info)

有了这个,node_memory_Active 指标默认只包含实例和作业作为第三个值节点名,您可以在 grafana 的描述字段中使用。

希望这对其他人有所帮助。

【讨论】:

是查询吗?我应该在普罗米修斯哪里使用它? 是的,这是一个查询【参考方案2】:

我找到了硬编码解决方案:

全球的: scrape_interval: 5s scrape_timeout: 5s 外部标签: 监视器:“普罗米修斯” scrape_configs: - 工作名称:'谢尔比' 静态配置: - 目标: - 10.100.0.01:9100 重新标签配置: - source_labels:[__address__] 正则表达式:'.*' 目标标签:实例 替换:“谢尔比” - 工作名称:'camaro' 静态配置: - 目标: - 10.101.0.02:9100 重新标签配置: - source_labels:[__address__] 正则表达式:'.*' 目标标签:实例 替换:“卡马罗” - 工作名称:'维罗纳' 静态配置: - 目标: - 10.101.0.03:9100 重新标签配置: - source_labels:[__address__] 正则表达式:'.*' 目标标签:实例 替换:“维罗纳”

结果:

node_load15instance="camaro",job="camaro" 0.16 node_load15instance="shelby",job="shelby" 0.4 node_load15instance="verona",job="verona" 0.07

【讨论】:

如果我在一项工作中有很多目标,并且想要为每个目标使用不同的 target_label,该怎么办? 不可能。 groups.google.com/forum/#!topic/prometheus-developers/…【参考方案3】:

另一个答案是使用一些 /etc/hosts 或本地 dns(可能是 dnsmasq)或诸如服务发现之类的东西(由 Consul 或 file_sd),然后像这样删除端口:

relabel_configs:
  - source_labels: ['__address__']
    separator:     ':'
    regex:         '(.*):.*'
    target_label:  'instance'
    replacement:   '$1'

【讨论】:

【参考方案4】:

group_left 不幸的是,与其说是解决方案,不如说是一种有限的解决方法。一个月来,我一直在努力寻找对group_left 的连贯解释,而表达式不是标签。必须在每个简单的表情上加上咒语会很烦人;弄清楚如何使用多个指标构建更复杂的 PromQL 查询完全是另一回事。期望我的任何用户——尤其是那些完全不熟悉 Grafana / PromQL 的用户——每次都编写一个复杂且难以理解的查询也不太友好。

我的第一个刺是这样的:

  - job_name: 'node_exporter'
    scrape_interval: 10s
    static_configs:
      - targets: ['1.2.3.4:9100']
        labels:
          cluster: 'rkv-image01'
          ceph_role: 'mon'
          instance_node: 'rkv1701'

上游不赞成将其视为“反模式”,因为显然人们期望instance 是唯一一个其值在工作中的所有指标中都是唯一的标签。我从来没有遇到过这很重要的情况,但是如果有更好的方法,为什么不呢。有一种想法是出口商应该是“固定的”,但我很犹豫是否要对一个广泛使用的项目进行潜在的破坏性变化的兔子洞。我也不愿意分叉它并且必须与上游保持平行,我没有时间也没有业力。

接下来我尝试了metrics_relabel_configs,但这似乎不想从不同的指标复制标签,即。 node_uname_infonodename -> instance -- 启动时出现语法错误。

接下来我遇到了一些事情,说如果收集器不提供值,Prom 将用 address 的值填充 instance,实际上出于某种原因它似乎为虽然我的node_exporter 没有得到一个。这似乎很奇怪。但我发现真正有效的是简单且如此明显,以至于我什至都没有想过尝试:

  - job_name: 'node_exporter'
    scrape_interval: 10s
    static_configs:
      - targets: ['1.2.3.4:9100']
        labels:
          cluster: 'rkv-image01'
          ceph_role: 'mon'
          instance: 'rkv1701'
...

即,只需在抓取配置中应用目标标签。我正在从能够写出这些目标的数据库转储中进行基于文件的服务发现。

这可能是我的环境没有相关节点的 DNS A 或 PTR 记录的一个因素。是的,我知道,相信我,我也不喜欢,但这是我无法控制的。但这仍然无关紧要,我不知道为什么 node_exporter 根本不提供任何 instance 标签,因为它确实找到了信息指标的主机名(这对我没有任何好处)。

$ curl http://1.2.3.4:9100/metrics | grep instance
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 80082    0 80082    0     0  4383k      0 --:--:-- --:--:-- --:--:-- 4600k

$ curl http://1.2.3.4:9100/metrics | grep rkv1701
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 80085    0 80085    0  node_uname_infodomainname="(none)",machine="x86_64",nodename="rkv1701.myco.com",release="4.17.13-1.el7.elrepo.x86_64",sysname="Linux",version="#1 SMP Mon Aug 6 14:16:00 EDT 2018" 1
   0  9268k      0 --:--:-- --:--:-- --:--:-- 9776k
$

【讨论】:

【参考方案5】:

此解决方案使用所需的标签在抓取时存储数据,无需有趣的 PromQL 查询或硬编码黑客。 它通过用relabel_configs 替换正则表达式刮取数据的标签来做到这一点。

默认情况下,instance 设置为 __address__、which is $host:$port

为了将instance标签设置为$host,可以使用relabel_configs去掉端口:

  - job_name: 'whatever'
    static_configs:
      - targets: [
            'yourhost.lol:9001'
        ]
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        regex: '([^:]+)(:[0-9]+)?'
        replacement: '$1'

但上述内容也会覆盖这样设置的标签,例如file_sd_configs:

[
    
        "targets": ['yourhost.lol:9001'],
        "labels": 
            "instance": 'node42'
        
    
]

如果您想保留这些标签,relabel_configs 可以通过以下方式完成:

  - job_name: 'rolf'
    metrics_path: /metric/rolf
    file_sd_configs:
      - files:
        - rolf_exporter_targets.yml
    relabel_configs:
      - source_labels: [instance]
        target_label: __tmp_instance
        regex: '(.+)'
        replacement: '$1;'
      - source_labels: [__tmp_instance, __address__]
        separator: ''
        target_label: instance
        regex: '([^:;]+)((:[0-9]+)?|;(.*))'
        replacement: '$1'

然后手动设置来自sd_configsinstance 优先,但如果未设置,端口仍会被剥离。

【讨论】:

我不确定这是否有帮助。我的目标配置是通过 IP 地址 (1.2.3.4),而不是主机名 (yourhost.lol)。 它应该适用于主机名和 ips,因为在这两种情况下,替换正则表达式都会在 : 处拆分。我宁愿争辩说,用 promql 解决方案接受的答案不会做任何重新标记,而是保持所有标签不变,只是以不同的方式显示数据。【参考方案6】:

您可以在 prometheus 工作描述中使用类似这样的重新标记规则:

- job_name: node-exporter
....
relabel_configs:
  .....
  # relable the label 'instance' with your pod_node_name 
  - source_labels: [__meta_kubernetes_pod_node_name]
    target_label: instance

在prometheus Service Discovery中你可以先检查你标签的正确名称。标签将以 '....pod_node_name' 结尾

【讨论】:

【参考方案7】:

您不必对其进行硬编码,也不需要连接两个标签。 您可以使用一些分隔符将所有逻辑放在targets 部分中 - 我使用了@,然后使用正则表达式对其进行处理。 请在下面找到来自其他导出器(黑盒)的示例,但同样的逻辑也适用于 node exporter。 在您的情况下,请仅包括以下列表项:

target_label: app_ip target_label: instance
- job_name: 'blackbox'
    metrics_path: '/probe'
    scrape_interval: 15s
    params:
      module: [ http_2xx ]
    static_configs:
      - targets:
        - "1.2.3.4:8080@JupyterHub"
        - "1.2.3.5:9995@Zeppelin"
        - "1.2.3.6:8080@Airflow UI"
    relabel_configs:
      - source_labels: [ __address__ ]
        regex: '(.*)@.*'
        replacement: $1
        target_label: __param_target
      - source_labels: [ __address__ ]
        regex: '(.*)@.*'
        replacement: $1
        target_label: app_ip
      - source_labels: [ __address__ ]
        regex: '.*@(.*)'
        replacement: $1
        target_label: instance
      - target_label: __address__
        replacement: ' blackbox_exporter_host : blackbox_exporter_port '

【讨论】:

【参考方案8】:

此答案的其他配置: https://***.com/a/64623786/2043385

  - job_name: 'node-exporter'
    kubernetes_sd_configs:
      - role: endpoints
    relabel_configs:
      - source_labels: [__meta_kubernetes_endpoints_name]
        regex: 'node-exporter'
        action: keep
      - source_labels: [__meta_kubernetes_pod_node_name]
        action: replace
        target_label: node

还有我的服务:

kind: Service
apiVersion: v1
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    app.kubernetes.io/component: exporter
    app.kubernetes.io/name: node-exporter
  ports:
    - name: node-exporter
      protocol: TCP
      port: 9100
      targetPort: 9100

【讨论】:

以上是关于在 Prometheus 中将实例重新标记为主机名的主要内容,如果未能解决你的问题,请参考以下文章

如何在 prometheus 配置中重新标记 ECS cadvisor 标签?

如何在本地 IIS 中将主机名设置为网站

Prometheus - 通过正则表达式聚合和重新标记

docker中的Prometheus node_exporter:主机网络与主机名

prometheus relabel 配置

prometheus relabel 配置