Prometheus实战教程 - 服务发现
目录
- 静态配置(static_configs)的局限性
- Prometheus与服务发现
- 1. 基于文件的服务发现(file_sd_configs)
- 2. 通过 HTTP (S) 接口 (http_sd_config)
- 3. 对接 Consul 服务注册中心(consul_sd_configs)
- consul_sd_configs 基础配置格式
- 服务注册示例(Consul)
- 4. Kubernetes 服务发现(kubernetes_sd_configs)
- 配置实例
- 生产环境配置案例
- 标签重写(`relabel_configs`)
- 指标过滤(`metric_relabel_configs`)
静态配置(static_configs)的局限性
static_configs 是最简单直接的目标配置方式,适用于监控目标的 IP 或域名固定不变的场景(例如物理机、固定部署的服务)。通过手动指定目标的地址,Prometheus 会直接对这些地址进行指标采集。
scrape_configs:- job_name: "node_exporter" # 任务名称(自定义,用于标识一组目标)static_configs:- targets: # 监控目标的地址列表(格式:[IP:端口] 或 [域名:端口])- "192.168.1.100:9100"- "192.168.1.101:9100"labels: # 可选:为该组目标添加额外标签(便于后续筛选和聚合)env: "production"group: "servers"
局限性
- 静态固定:目标地址需要手动填写,变更时需修改配置并重启 / 重载 Prometheus。
- 简单直观:适合少量、地址固定的目标(如独立服务器、固定端口的服务)。
- 无动态发现能力:无法自动感知目标的新增、删除或地址变化(例如容器重启后 IP 变化)。
Prometheus与服务发现
在基于云(IaaS或者CaaS)的基础设施环境中用户可以像使用水、电一样按需使用各种资源(计算、网络、存储)。按需使用就意味着资源的动态性,这些资源可以随着需求规模的变化而变化。例如在AWS中就提供了专门的AutoScall服务,可以根据用户定义的规则动态地创建或者销毁EC2实例,从而使用户部署在AWS上的应用可以自动的适应访问规模的变化。
这种按需的资源使用方式对于监控系统而言就意味着没有了一个固定的监控目标,所有的监控对象(基础设施、应用、服务)都在动态的变化。
而对于Prometheus这一类基于Pull模式的监控系统,显然也无法继续使用的static_configs的方式静态的定义监控目标。而对于Prometheus而言其解决方案就是引入一个中间的代理人(服务注册中心),这个代理人掌握着当前所有监控目标的访问信息,Prometheus只需要向这个代理人询问有哪些监控目标控即可, 这种模式被称为服务发现。
Prometheus 支持多种服务发现方式
1. 基于文件的服务发现(file_sd_configs)
通过监听文件(JSON/YAML)的变化自动更新目标,是静态配置和动态发现的中间方案(适合半动态场景)。
配置示例:
scrape_configs:- job_name: "file_sd_demo"file_sd_configs:- files:- "/etc/prometheus/targets/*.json" # 监听该路径下的 JSON 文件refresh_interval: 5m # 刷新间隔(默认5m)
目标文件(如 targets/node.json):
[{"targets": ["10.0.0.1:9100", "10.0.0.2:9100"],"labels": {"env": "test"}}
]
通过为这些实例添加一些额外的标签信息,例如使用env标签标示当前节点所在的环境,这样从这些实例中采集到的样本信息将包含这些标签信息,从而可以通过该标签按照环境对数据进行统计。
通过这种方式,Prometheus会自动的周期性读取文件中的内容。当文件中定义的内容发生变化时,不需要对Prometheus进行任何的重启操作。
2. 通过 HTTP (S) 接口 (http_sd_config)
http_sd_config 是一种通过 HTTP (S) 接口动态获取监控目标的服务发现机制。它允许 Prometheus 定期从一个 HTTP 端点(如自定义的服务注册接口、配置服务器等)拉取目标列表,适用于需要自定义服务发现逻辑的场景(例如企业内部自建的服务注册中心,或无法直接对接 Consul、K8s 等现有组件的情况)。
HTTP 端点返回的 JSON 或 YAML 数据需遵循以下格式(以 JSON 为例):
[{"targets": ["10.0.0.10:9100", "10.0.0.11:9100"], // 监控目标的地址列表(必填)"labels": { // 可选:为该组目标添加标签"env": "production","service": "node-exporter"}},{"targets": ["10.0.0.20:8080"],"labels": {"env": "test","service": "api-service"}}
]
假设用 Python Flask 搭建一个返回目标数据的 HTTP 服务:
from flask import Flask, jsonifyapp = Flask(__name__)# 模拟服务注册中心返回的目标数据
@app.route('/targets')
def get_targets():return jsonify([{"targets": ["192.168.1.10:9100", "192.168.1.11:9100"],"labels": {"env": "prod", "role": "web"}},{"targets": ["192.168.1.20:9100"],"labels": {"env": "test", "role": "db"}}])if __name__ == '__main__':app.run(host='0.0.0.0', port=8080)
启动后,访问 http://localhost:8080/targets 可获取上述 JSON 数据。
Prometheus 配置 http_sd_config
scrape_configs:- job_name: "http_discovery"http_sd_configs:- url: "http://localhost:8080/targets" # 对接上面的 Flask 服务refresh_interval: 10s # 每 10s 拉取一次relabel_configs:# 仅保留 env=prod 的目标- source_labels: [__meta_http_sd_label_env]action: keepregex: prod# 将服务角色(role)作为标签- source_labels: [__meta_http_sd_label_role]target_label: role
注意事项
- 可用性保障:HTTP 端点需保证高可用,否则 Prometheus 可能无法获取目标数据(建议部署多个实例并配合负载均衡)。
- 性能优化:若目标数量庞大,需确保 HTTP 端点的响应速度(避免超时),并合理设置 refresh_interval(避免频繁请求导致压力)。
- 安全机制:若 HTTP 端点暴露在公网或敏感环境,需通过 tls_config 启用 HTTPS,并添加认证(如 Token、Basic Auth),防止未授权访问。
3. 对接 Consul 服务注册中心(consul_sd_configs)
consul_sd_configs 基础配置格式
scrape_configs:- job_name: "consul_sd_demo"consul_sd_configs:- server: "consul-server:8500" # Consul 服务器地址(默认 localhost:8500)scheme: "http" # 通信协议(http/https)services: [] # 要发现的服务列表(空表示所有服务)tags: [] # 按标签筛选服务(空表示不筛选)node_meta: # 按节点元数据筛选(k-v 形式,如 {"env": "prod"})refresh_interval: 30s # 刷新间隔(默认30s)
Consul 服务注册与元标签(Meta Labels)
Prometheus 通过 Consul 获取服务实例时,会自动生成一系列元标签(_meta_consul*),包含服务的详细信息,可用于筛选或标签重写。
| 元标签 | 含义 |
|---|---|
__meta_consul_address | 服务实例的 IP 地址(如 10.0.0.10)。 |
__meta_consul_port | 服务实例的端口(如 8080)。 |
__meta_consul_service | 服务名称(如 api-service)。 |
__meta_consul_tags | 服务实例的标签(逗号分隔,如 prod,http)。 |
__meta_consul_node | 服务所在的 Consul 节点名称。 |
__meta_consul_health | 服务健康状态(passing/warning/critical)。 |
__meta_consul_service_metadata_<key> | 服务注册时附带的元数据(如 __meta_consul_service_metadata_env 对应注册时的 env: prod)。 |
服务注册示例(Consul)
若要让 Prometheus 正确发现服务,需在服务注册到 Consul 时,提供指标采集的端口和相关元数据。例如,通过 Consul API 注册一个 node-exporter 服务:
curl -X PUT http://consul-server:8500/v1/agent/service/register -d '{"Name": "node-exporter", # 服务名称"ID": "node-exporter-10.0.0.10", # 唯一ID"Address": "10.0.0.10", # 服务IP"Port": 9100, # 指标采集端口(node-exporter默认端口)"Tags": ["monitoring", "prod"], # 标签"Meta": { # 元数据(可自定义)"env": "production","group": "web-server"},"Check": { # 健康检查(确保服务存活)"HTTP": "http://10.0.0.10:9100/metrics","Interval": "10s"}
}'
4. Kubernetes 服务发现(kubernetes_sd_configs)
针对 Kubernetes 集群设计,可自动发现 Pod、Service、Node、Endpoint 等资源作为监控目标(最常用的容器环境方案)。
配置实例
scrape_configs:- job_name: "k8s_pods"kubernetes_sd_configs:- role: pod # 发现角色:pod(可选:node、service、endpoints 等)namespaces:names: ["default", "prod"] # 限定命名空间# 筛选规则:仅监控带 "monitor: true" 标签的 Podrelabel_configs:- source_labels: [__meta_kubernetes_pod_label_monitor]action: keepregex: true
生产环境配置案例
- job_name: 'kubernetes-node-exporter'kubernetes_sd_configs:- role: nodebasic_auth:username: adminpassword: NWxLxW22hD22te9xDWg81relabel_configs:- regex: '__meta_kubernetes_node_label_([0-9]+)'action: labeldrop- source_labels: [__address__]regex: '(.*):10250'replacement: '${1}:7100'target_label: __address__action: replace- source_labels: [__meta_kubernetes_node_name]action: replacetarget_label: node- action: labelmapregex: __meta_kubernetes_node_label_(.+)- source_labels: [__meta_kubernetes_node_address_InternalIP]action: replacetarget_label: ipmetric_relabel_configs:- source_labels: [__name__]separator: ','regex: '(node_memory_Slab|node_memory_Slab_bytes|node_exporter_build_info|node_boot_time|node_time|node_cpu|node_context_switches|node_intr|node_filesystem_free|node_memory_MemTotal|node_memory_MemAvailable|node_memory_MemFree|node_
memory_Buffers|node_memory_Cached|node_vmstat_pgpgin|node_vmstat_pgpgout|node_forks|node_procs_running|node_procs_blocked|node_filefd_maximum|node_filefd_allocated|node_sockstat_TCP_tw|node_sockstat_TCP_alloc|node_sockstat_TCP_inuse|nod
e_filesystem_size|node_filesystem_avail|node_load1|node_load5|node_load15|node_network_receive_bytes|node_network_transmit_bytes|node_netstat_Tcp_CurrEstab|node_disk_io_time_seconds_total|node_disk_reads_completed_total|node_disk_writes
_completed_total|node_disk_bytes_read|node_disk_bytes_written|node_memory_SwapTotal|node_memory_SwapFree|node_netstat_Tcp_ActiveOpens|node_netstat_Tcp_PassiveOpens|node_netstat_Tcp_EstabResets|node_netstat_Tcp_AttemptFails|node_netstat_
Tcp_RetransSegs|node_netstat_Udp_InDatagrams|node_netstat_Udp_InErrors|node_netstat_Udp_OutDatagrams|node_netstat_Udp_NoPorts|node_netstat_Udp_InCsumErrors|node_netstat_Udp_RcvbufErrors|node_netstat_Udp_SndbufErrors|new_node_exporter|no
de_exporter_build_info|node_boot_time_seconds|node_time_seconds|node_cpu_seconds_total|node_memory_MemTotal_bytes|node_filesystem_free_bytes|node_filesystem_size_bytes|node_filesystem_avail_bytes|node_load1|node_load5|node_load15|node_n
etwork_receive_bytes_total|node_network_transmit_bytes_total|node_netstat_Tcp_CurrEstab|node_memory_MemAvailable_bytes|node_memory_MemFree_bytes|node_memory_Buffers_bytes|node_memory_Cached_bytes|node_disk_read_bytes_total|node_disk_wri
tten_bytes_total|node_memory_SwapTotal_bytes|node_memory_SwapFree_bytes|node_context_switches_total|node_intr_total|node_forks_total|node_disk_io_time_ms|node_disk_reads_completed|node_disk_writes_completed|node_uname_info|node_disk_rea
d_time_seconds_total|node_disk_write_time_seconds_total|node_filesystem_files_free|node_filesystem_files|node_vmstat_pgmajfault)'action: keep
标签重写(relabel_configs)
用于修改目标实例的元标签(如地址、标签等),影响Prometheus如何识别和采集目标。
-
规则1:过滤特定标签
- regex: '__meta_kubernetes_node_label_([0-9]+)'action: labeldrop- 作用:删除所有以
__meta_kubernetes_node_label_开头且后面跟数字的标签(例如节点上带数字的标签会被过滤掉)。 action: labeldrop:表示删除匹配的标签。
- 作用:删除所有以
-
规则2:修改采集地址
- source_labels: [__address__]regex: '(.*):10250'replacement: '${1}:7100'target_label: __address__action: replace- 作用:Kubernetes节点默认的服务发现地址是
节点IP:10250(kubelet端口),这里将其替换为节点IP:7100(假设node-exporter运行在节点的7100端口,Prometheus将从这个端口采集指标)。 source_labels: [__address__]:读取原始地址标签(__address__是服务发现自动生成的目标地址)。regex: '(.*):10250':匹配格式为IP:10250的地址。replacement: '${1}:7100':将匹配到的IP保留,端口替换为7100。target_label: __address__:修改后的地址写回__address__标签(最终采集地址)。
- 作用:Kubernetes节点默认的服务发现地址是
-
规则3:添加
node标签- source_labels: [__meta_kubernetes_node_name]action: replacetarget_label: node- 作用:将Kubernetes节点的名称(从元标签
__meta_kubernetes_node_name获取)添加到指标的node标签中,方便后续按节点筛选指标。
- 作用:将Kubernetes节点的名称(从元标签
-
规则4:映射节点标签
- action: labelmapregex: __meta_kubernetes_node_label_(.+)- 作用:将Kubernetes节点自身的标签(如
kubernetes.io/hostname、env=prod等)自动添加到Prometheus指标中。 - 原理:Kubernetes的服务发现会生成
__meta_kubernetes_node_label_<标签名>格式的元标签(例如节点有env=prod标签,会生成__meta_kubernetes_node_label_env=prod),这条规则会去掉前缀,将其转换为env=prod这样的标签。
- 作用:将Kubernetes节点自身的标签(如
-
规则5:添加
ip标签- source_labels: [__meta_kubernetes_node_address_InternalIP]action: replacetarget_label: ip- 作用:将节点的内部IP(从元标签
__meta_kubernetes_node_address_InternalIP获取)添加到指标的ip标签中,方便按IP定位节点。
- 作用:将节点的内部IP(从元标签
指标过滤(metric_relabel_configs)
用于在采集到指标后,过滤需要保留的指标(只保留符合条件的指标,其他丢弃)。
- source_labels: [__name__]separator: ','regex: '(node_memory_Slab|node_cpu|node_filesystem_free|...)' # 省略部分指标名action: keep
- 作用:只保留指标名称(
__name__)匹配regex中列出的指标。 - 列出的指标主要是
node-exporter采集的节点级监控指标,包括:- 内存相关(
node_memory_*) - CPU相关(
node_cpu_*) - 磁盘相关(
node_filesystem_*、node_disk_*) - 网络相关(
node_network_*、node_netstat_*) - 系统负载(
node_load1、node_load5等) - 其他基础指标(
node_boot_time、node_exporter_build_info等)
- 内存相关(
action: keep:表示保留匹配的指标,不匹配的指标会被丢弃(减少存储和处理压力)。
