当前位置: 首页 > news >正文

prometheus主动服务发现机制

prometheus主动服务发现机制

简介

  • prometheus是基于pull模式抓取监控数据,首先要能够发现需要监控的目标对象target,那么prometheus如何获取数据的监控,目前有2种方式,静态手工配置和动态服务发现配置。
    1. 对于小型的系统环境来说,可以通过static_config静态指定各个Target便能解决这个问题,这个就是最简单的手工配置
  • 但是,prometheus最开始设是一个面向云原生应用程序的,云原生,容器场景下按需的资源使用方式,对于监控系统而言就意味着没有一个固定的监控目标,所有的监控对象(基础设施,应用,服务)都在动态的变化,因此,对于有较强的动态性云环境中,静态配置显然难以适用,于是就出现了动态服务发现机制
  • 为了适应静态和动态发现机制,prometheus引入了一个中间代理(服务注册中心),这个代理人掌握着当前所有的当前监控目标访问信息,prometheus只需要引入代理人询问有那些目标即可,这种模式被称作为服务发现(service discovery )

在这里插入图片描述

如图: SD模块是专门负责发现需要监控的target信息,prometheus去SD模块订阅该信息,有target信息会推送到Prometheus,然后Prometheus拿到target信息后通过pull http 协议去拉取该指标的数据。

  • kubernetes_sd_configs: kubernetes服务发现,让prometheus动态发现kubernetes中被监控的目标。
  • static_configs: 静态服务发现,基于prometheus配置文件指定监控目标
  • dns_sd_configs: DNS服务发现监控目标
  • consul_sd_configs: Consul服务发现,基于consul服务动态发现监控目标
  • file_sd_configs: 基于指定的文件事先服务发现,prometheus定时读取文件如果发生变化则加载新目标

1、静态配置的局限性

静态服务发现机制,配置简单,但是监控目标是写死在了配置文件中,如果要新增、修改、删除监控节点时,需要每次都去修改配置文件,然后再通知prometheus重新加载,这太麻烦了。于是出现了动态服务发现

2、基于文件的服务发现

我们下面有更好的代替,这里这个服务发现先简单的了解明白工作原理

通过定义一组资源“子”配置文件,yaml格式文件里面只存储需要采集的targets信息,此种方式可以被prometheus实时动态获取,而不需要重启prometheus服务。

首先,定义一个JSON格式文件的服务发现文件:

[root@prometheus-server targets]# more node.json 
[{"targets": [ "172.16.213.90:9100" ],"labels": {"env": "dev_gameserver"}}
]

或者也可以定义一个YAML格式文件的服务发现文件:

[root@prometheus-server targets]# more node.yaml 
- targets:- "172.16.213.29:9100"labels:app: node-exporterjob: nodes

接着,将这两个文件放到当前的targets目录下(先创建targets目录),最后,修改prometheus.yml 配置文件,增加如下内容:

  - job_name: 'node_service_discovery'file_sd_configs:- files:- targets/*.jsonrefresh_interval: 60s- files:- targets/*.yamlrefresh_interval: 60s

配置文件说明:

  • file_sd_configs,指定prometheus基于文件的服务发现配置。
  • files,自定义的和prometheus程序同级目录的targets目录,要被自动加载的所有.json格式、yaml格式的文件。当然也可以单独指定某一个JSON格式的文件。
  • refresh_interval: 60m,自定义刷新间隔时间为60秒。

3、Prometheus中的标签重写机制

(1)、Prometheus中标签的概念

在Prometheus所有的Target监控实例中,都包含一些默认的Metadata标签信息。可以通过Prometheus UI的Targets页面中查看这些实例的Metadata标签的内容

在这里插入图片描述

  • __address__:当前Target实例的访问地址<host>:<port>
  • __scheme__:采集目标服务访问地址的HTTP Scheme,HTTP或者HTTPS
  • __metrics_path__:采集目标服务访问地址的访问路径
  • __param_<name>:采集任务目标服务的中包含的请求参数

上面这些标签将会告诉Prometheus如何从Target实例中获取监控数据。除了这些默认的标签以外,我们还可以为Target添加自定义的标签。

一般来说,Target以__作为前置的标签是在系统内部使用的,因此这些标签不会被写入到样本数据中。不过这里有一些例外,比如,指标上的instance标签的默认值就来自于_address__标签的值。这里实际上是发生了一次标签的重写处理。

这种发生在采集样本数据之前,对Target实例的标签进行重写的机制在Prometheus被称为Relabeling。Prometheus允许用户在采集任务中设置通过relabel_configs来添加自定义的Relabeling过程。

(2)、relabel_configs的使用

relabel_configs常用的几个参数如下:

  • source_labels: 源标签,没有经过relabel处理之前的名字
  • target_labels: 通过action处理之后的新标签名字
  • regex: 正则表达式,匹配源标签
  • replacement: 通过分组替换后标签(target_label)对应的值
  • action:执行的动作。支持: replace,drop,keep,labelmap,labeldrop,labelkeep,hashmod

下面我简单列举一下action里面每个 relabel_action 的作用:

relabel_action参数含义
replace根据 regex 的配置,匹配 source_labels 标签的值,并且将匹配到的值写入到 target_label 当中,如果有多个匹配组,则可以使用 ${1}, ${2} 确定写入的内容。如果没匹配到任何内容,则不对 target_label 进行重新, 默认为 replace。
keep丢弃 source_labels 的值中没有匹配到 regex 正则表达式内容的 Target 实例
drop丢弃 source_labels 的值中匹配到 regex 正则表达式内容的 Target 实例
hashmod将 target_label 设置为关联的 source_label 的哈希模块
labelmap根据 regex 去匹配 Target 实例所有标签的名称(注意是名称),并且将捕获到的内容作为新的标签名称,regex 匹配到标签的的值,作为新标签的值
labeldrop对 Target 标签进行过滤,会移除匹配过滤条件的所有标签
labelkeep对 Target 标签进行过滤,会移除不匹配过滤条件的所有标签

例子1:给target增加标签

修改prometheus.yml,增加如下内容:

  - job_name: 'prometheus'static_configs:- targets: [ 'localhost:9090']labels:env: 'prod'__hostname__: 'localhost'

然后执行:# curl -X POST http://172.16.213.35:9090/-/reload

此操作会在原来的标签基础之上又增加了两个标签。
注意,内部标签默认是不显示的,只有把鼠标移动到Labels那里才会显示。同时,要注意__开头的标签是不会写到metrics指标里面的,因为这属于系统内置标签。env这种没有__作为前缀的,是可以写到metrics指标中的。

例子2:将target的初始标签里面的值替换到新的标签中

修改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'

然后执行: # curl -X POST http://172.16.213.35:9090/-/reload

上面直接替换了两个标签,如果只替换一个标签,就不用写两个source_lables了,还有一点要注意,目标标签不能用__标签名 __

如果要替换成指定值,可做如下修改:

    relabel_configs:- source_labels: [ '__address__' ]target_label:  'addr'replacement: 'localhost'

上面就是将__address__替换成addr,然后再让addr=localhost。

如果要使用正则匹配替换,可做如下修改:

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

上面就是将localhost:9090通过正则截成两段,然后将第一段交给replacement去替换addr的值。

当然也可以使用下面的写法:

   relabel_configs:- action: replacesource_labels: [ '__address__' ]regex: "(.*):(.*)"replacement: $1target_label:  'addr'

例子3:使用labelmap标签名替换

labelmap: 根据 regex 去匹配 Target 实例所有标签的名称(注意是名称),并且将捕获到的内容作为为新的标签名称,regex 匹配到标签的的值作为新标签的值.当然这个新的标签也会加到样本数据中。

 relabel_configs:- source_labels: [ '__metrics_path__' ]regex: __metrics_(.+)__   #这相当于将path截取出来作为新的标签名称action: labelmap

或者下面的方式

 relabel_configs:- regex:  __metrics_(.+)__action: labelmap

最终会新增一个path="/metrics"的新标签。

下面是这个博客的重点哦

基于consul的服务发现

Consul是基于Go语言开发的开源工具,提供服务注册,服务发现,健康检查,Key/Value存储,多数据中心和分布式一致性保证等一系列功能。

之前我们呢通过prometheus实现监控,当新增加一个Target时,需要变更服务器上的配置文件,即使使用了file_sd_configs配置,也需要登录服务器修改对应的json文件会十分的麻烦,不过prometheus官方支持多种自动服务发现的类型,其中就支持consul

  • 安装consul
    • 这里我们使用docker的方式快速简单的启动和运行。
  • Consul安装很方便,官网(https://www.consul.io/downloads) 提供各个系统版本二进制安装包,解压安装即可,同时也可以通过 Docker 来快速安装。这里我在172.16.213.26主机上,执行如下命令docker方式安装:
[root@docker-110 ~]#  docker run -d -p 8500:8500 \
> --restart=always \
> -v /data/consul/data:/consul/data \
> --name=consul \
> hashicorp/consul:1.15.2 agent \
> -server \
> -bootstrap \
> -ui \
> -node=dc1 \
> -client='0.0.0.0'
Unable to find image 'hashicorp/consul:1.15.2' locally1.15.2: Pulling from hashicorp/consul
f56be85fc22e: Pull complete 
d7d6b9886c5f: Pull complete 
996f67d6a296: Pull complete 
6368458efd23: Pull complete 
716242560a20: Pull complete 
4f4fb700ef54: Pull complete 
6b40a7781f0c: Pull complete 
Digest: sha256:c2169f3bb18dd947ae8eb5f6766896695c71fb439f050a3343e0007d895615b8
Status: Downloaded newer image for hashicorp/consul:1.15.2
4d25f24d12c2d6c651b2980efbca4597c80a4c1bbd2170adb1a8402985db1b45
  • agent :表示启动Agent进程

  • server: 表示启动Consul Server 模式

  • client:表示启动Consul Client模式

  • bootstrap: 表示这个节点时server_Leader,每一个数据中心只能运行一台服务器,技术角度上讲Leader 是通过 Raft 算法选举的,但是集群第一次启动时需要一个引导 Leader,在引导群集后,建议不要使用此标志。

  • ui: 表示启动 Web UI 管理器,默认开放端口 8500,所以上面使用 Docker 命令把 8500 端口对外开放。

  • node: 节点的名称,集群中必须是唯一的,默认是该节点的主机名。

  • client: consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0

这里就可以访问呢10.0.0.110:8500

在这里插入图片描述

默认情况下这里就只有一个consul本身的services服务

通过api注册服务到Consul

  • Consul服务注册提供了两种注册方法:一种是定义配置文件服务注册方法,即在配置文件中定义服务来进行注册;一种是HTTP API服务注册方法,即在启动服务后,自身通过调用API进行自我注册。

  • 这里介绍第二种,consul主要是添加和删除命令,都是使用接口调用。先创建test.json文件,内容如下:

    {"id": "docker-110","name": "docker-110-10.0.0.110","address": "10.0.0.110","port": 9100,"tags": ["test"],"checks": [{"http": "http://10.0.0.110:9100/metrics","interval": "5s"}]
    }
    

注意这里的test.json时在你敲命令的当前目录

curl --request PUT --data @test.json http://10.0.0.110:8500/v1/agent/service/register

执行完毕后,刷新一下 Consul Web 控制台页面,可以看到成功注册到 Consul 中。

在这里插入图片描述

要删除这个服务,可执行如下命令:

$ curl --request PUT  http://172.16.213.26:8500/v1/agent/service/deregister/node-exporter

注意,url最后的node-exporter是注册对应的ID,删除哪个服务,就指定哪个ID。

为了报红

原因是他的这个访问不了

在这里插入图片描述

因此我们知道时目标主机的node_exporter没有起来

在这里插入图片描述

  • 我们刷新后看看

在这里插入图片描述

  • 获取的node节点信息

在这里插入图片描述

配置prometheus实现服务自动发现

现在 Consul 服务已经启动完毕,并成功注册了一个服务,接下来,我们需要配置 Prometheus 来使用 Consul 自动服务发现,目的就是能够将上边添加的服务自动发现到 Prometheus 的 Targets 中,增加 prometheus.yml 配置如下:

  - job_name: 'consul-prometheus'consul_sd_configs:- server: '10.0.0.110:8500'services: [] 

说明一下:

  • consul_sd_configs:表示使用 Consul 服务发现类型
  • server: 为 Consul 的服务地址,这里跟上边要对应上。
  • services: []:这个表示匹配consul中所有的service。

配置完毕后,重启 Prometheus 服务,此时可以通过 Prometheus UI 页面的 Targets 下查看是否配置成功。

可以看到,在 Targets 中能够成功的自动发现 Consul 中的 Services 信息,后期需要添加新的 Targets 时,只需要通过 API 往 Consul 中注册服务即可,Prometheus 就能自动发现该服务,非常方便。

(4)、使用relabel_configs自定义标签

修改刚才的test.json文件,内容如下:

{"ID": "node-exporter","Name": "node-exporter-172.16.213.28","Tags": ["test"],"Address": "172.16.213.28","Port": 9100,"Meta": {"app": "spring-boot","team": "appgroup","project": "bigdataserver"},"EnableTagOverride": false,"Check": {"HTTP": "http://172.16.213.28:9100/metrics","Interval": "10s"},"Weights": {"Passing": 10,"Warning": 1}
}

参数含义:

  • replace-existing-checks:在重新注册服务时替换现有的检查。
  • Name:指定服务名称,必选。
  • ID:指定服务ID,如果未指定,默认为服务名称。
  • Tags:指定标记,用于筛选。
  • Address:指定服务的地址。
  • Port:指定服务的端口。
  • Meta:指定 KV 元数据。
  • Weights:指定服务的权重。
  • Check:指定健康检测。

说明:

该 Json 文件为要注册的服务信息,同时往 Meta 信息中添加了 app=spring-bootteam=appgroupproject=bigdataserver 三组自定义标签,目的就是为了方便告警分组使用。执行如下命令进行注册:

 $ curl --request PUT --data @test.json http://172.12.213.26:8500/v1/agent/service/register?replace-existing-checks=1

注册完毕,通过 Consul Web 管理页面可以查看到已注册成功,并且包含了 Meta 信息。

然后修改 prometheus.yml 配置如下:

- job_name: 'consul-prometheus'consul_sd_configs:- server: '172.16.213.26:8500'services: []  relabel_configs:- source_labels: [__meta_consul_tags]regex: .*test.*action: keep- regex: __meta_consul_service_metadata_(.+)action: labelmap

(5)、使用relabel_configs将自动发现的服务进行分类

重新修改test.json文件,此类服务实现node-exporter自动注册,内容如下:

{"ID": "node-exporter","Name": "node-exporter-172.16.213.28","Tags": ["node-exporter"],"Address": "172.16.213.28","Port": 9100,"Meta": {"app": "spring-boot","team": "appgroup","project": "bigdataserver"},"EnableTagOverride": false,"Check": {"HTTP": "http://172.16.213.28:9100/metrics","Interval": "10s"},"Weights": {"Passing": 10,"Warning": 1}
}

然后更新注册服务:

$ curl --request PUT --data @test.json http://172.16.213.26:8500/v1/agent/service/register?replace-existing-checks=1

新增另一个文件docker.json,用于docker类服务的自动发现,内容如下:

{"ID": "cadvisor-exporter","Name": "cadvisor-exporter-172.16.213.29","Tags": ["cadvisor-exporter"],"Address": "172.16.213.29","Port": 8080,"Meta": {"app": "docker","team": "cloudgroup","project": "docker-service"},"EnableTagOverride": false,"Check": {"HTTP": "http://172.16.213.29:8080/metrics","Interval": "10s"},"Weights": {"Passing": 10,"Warning": 1}
}

继续注册服务到consul:

$ curl --request PUT --data @docker.json http://172.16.213.26:8500/v1/agent/service/register?replace-existing-checks=1

最后,我们修改 prometheus.yml 配置如下:

  - job_name: 'consul-node-exporter'consul_sd_configs:- server: '172.16.213.26:8500'services: []  relabel_configs:- source_labels: [__meta_consul_tags]regex: .*node-exporter.*action: keep- regex: __meta_consul_service_metadata_(.+)action: labelmap- job_name: 'consul-cadvisor-exproter'consul_sd_configs:- server: '172.16.213.26:8500'services: []relabel_configs:- source_labels: [__meta_consul_tags]regex: .*cadvisor-exporter.*action: keep- regex: __meta_consul_service_metadata_(.+)action: labelmap

这里通过relabel_configs 中配置的 Tags 来做匹配区分,对注册的服务进行分类,重启 Prometheus 服务,可以看到服务已经按照类型分类了,方便查看。

虽然prometheus 使用consul的服务发现做监控,不对prometheus 做修改了,但是,我们每次还要手动去注册服务,感觉很麻烦,于是呢,来个终极方法,分享一个脚本,自动去consul注册服务,自动检测服务状态,还能卸载consul里面的服务:

#!/bin/bash#usage:
#param1:check_service or register_service or deregister_service
#param2: an exist file,and the file content format is as follows,pay attention to remove the first #
#group_name cluster_name service_ip service_port#注册服务
function register_service()
{
cat $1 | while read line
dogroup_name=$(echo $line | awk '{print $1}')cluster_name=$(echo $line | awk '{print $2}')service_ip=$(echo $line | awk '{print $3}')service_port=$(echo $line | awk '{print $4}')cat >service-$service_ip-$service_port.json<<EOF
{"id":"service-${service_ip}-${service_port}","name":"service-${service_ip}-${service_port}","address":"${service_ip}","port":${service_port},"tags":["$cluster_name"],"meta":{"group":"$group_name","cluster":"$cluster_name","instance_name":"$service_ip:$service_port"},"checks":[{"http":"http://${service_ip}:$service_port/metrics","interval":"5s"}],"Weights": {"Passing": 10,"Warning": 1},"EnableTagOverride": false
}
EOF
curl --request PUT --data @service-$service_ip-$service_port.json \
http://${consul_host}:${consul_http_api_port}/v1/agent/service/register?replace-existing-checks=1rm -rf service-$service_ip-$service_port.json
done
}#注销服务
function deregister_service()
{
cat $1 | while read line
doservice_ip=$(echo $line | awk '{print $3}')service_port=$(echo $line | awk '{print $4}')#let service_port=redis_port+10000consul_service_id="service-$service_ip-$service_port"curl --request PUT  http://${consul_host}:${consul_http_api_port}/v1/agent/service/deregister/${consul_service_id}
done
}#检查服务
check_service()
{
cat $1 | while read line
doservice_ip=$(echo $line | awk '{print $3}')service_port=$(echo $line | awk '{print $4}')#let service_port=redis_port+10000consul_service_id="service-$service_ip-$service_port"ret1=$(curl -s http://${consul_host}:${consul_http_api_port}/v1/agent/service/$consul_service_id?pretty)if [[ $ret1 =~ "unknown proxy service ID" ]];thenecho "不存在服务$consul_service_id"elseret2=$(curl -s http://${consul_host}:${consul_http_api_port}/v1/health/service/service-$service_ip-$service_port?pretty \| grep "$service_ip:$service_port/metrics: 200 OK")if [[ -z "$ret2" ]];thenecho -e "\033[5;34m服务$consul_service_id已注册,但服务状态异常  <---\033[0m"elseecho "服务$consul_service_id已注册,且服务状态正常"fifi
done
}function main()
{
if [[ $# -ne 2 ]];thenecho -e "must two parameters:\nfirst exec_command(check_service or register_service or deregister_service)\nsecond filename"exit
elsecase $1 incheck_service)shift 1check_service $1;;register_service)shift 1register_service $1;;deregister_service)shift 1deregister_service $1;;*)echo "无效的指令"esac
fi
}consul_host="172.16.213.26"
consul_http_api_port=8500
main $1 $2

将上面脚本命名为consul-register.sh,脚本执行方式:

[root@docker-server consul]# ./consul-register.sh 
must two parameters:
first exec_command(check_service or register_service or deregister_service)
second filename

第一个参数可从check_service or register_service or deregister_service选择,对应检测服务、注册服务、注销服务。

第二个参数对应一个文件,文件名随便,内容格式为:

group_name cluster_name service_ip service_port

例如,consul-service文件内容如下:

dbgroup  mysql-exports 172.16.213.27 9104

每个部分,用空格分开。下面是一个执行例子:

[root@docker-server consul]# ./consul-register.sh   check_service consul-service 
服务service-172.16.213.27-9104已注册,且服务状态正常
http://www.dtcms.com/a/290883.html

相关文章:

  • 在 React 中实现全局防复制hooks
  • Java 解析前端上传 ZIP 压缩包内 Excel 文件的完整实现方案
  • Neo4j 5.x版本的导出与导入数据库
  • 易语言+懒人精灵/按键中控群控教程(手机、主板机、模拟器通用)
  • CFD总压边界条件的理解与开发处理
  • DM8数据库Docker镜像部署最佳实践
  • 自学鸿蒙测试day01-插件安装推荐
  • Vue 3 响应式原理详细解读【一】—— Proxy 如何突破 defineProperty 的局限
  • 计算机发展史:晶体管时代的技术飞跃
  • Boost库智能指针boost::shared_ptr详解和常用场景使用错误示例以及解决方法
  • 软件测试 —— A / 入门
  • 数据结构 之 【排序】(直接插入排序、希尔排序)
  • 基于 Nginx 搭建 OpenLab 多场景 Web 网站:从基础配置到 HTTPS 加密全流程
  • Nginx IP授权页面实现步骤
  • Grok网站的后端语言是php和Python2.7
  • Python 变量赋值与切片语法(in-place 修改 vs 重新赋值)
  • 《画布角色的双重灵魂:解析Canvas小游戏中动画与碰撞的共生逻辑》
  • 状压DP学习笔记[浅谈]
  • 计算机网络:概述层---计算机网络的性能指标
  • IFN影视官网入口 - 4K影视在线看网站|网页|打不开|下载
  • 算法训练营DAY37 第九章 动态规划 part05
  • Linux开发⊂嵌入式开发
  • 复制docker根目录遇到的权限问题
  • Mac安装Typescript报错
  • macOS 上安装 Kubernetes(k8s)
  • 深度学习-常用环境配置
  • 基于R语言的分位数回归技术应用
  • next.js刷新页面时二级菜单展开状态判断
  • Java 通过 HttpURLConnection发送 http 请求
  • CG-04 翻斗式雨量传感器 分辨率0.1mm,0.2mm可选择 金属材质