自动发现Prometheus服务我们了解了在Prometheus中使用Relabeling重新标记。在本文中,我们将学习如何使用Prometheus中的服务发现来查找和抓取目标。我们知道在Prometheus的配置文件中可以使用一个static_configs来配置静态的爬取任务,但是在云环境中,尤其是容器环境中,抓取目标地址是经常变化的,所以静态方式无法满足这些场景了。因此,我们需要监控系统能够动态感知这种变化。不可能手动重新配置每个更改。为了应对复杂的动态环境,Prometheus还在基础设施中提供了与服务发现集成的功能。Prometheus已经支持多种内置的服务发现机制:发现云服务提供商的VMKubernetes上的自动发现常见的服务查找,例如DNS、Consul、Zookeeper或自定义发现机制我们可以通过Prometheus配置文件中的scrape_config进行部分配置,Prometheus会不断更新动态捕获目标列表,自动停止捕获旧实例,并开始捕获新实例。Prometheus特别适合运行在Kubernetes集群下,可以自动发现监控目标。此外,大多数服务发现机制还会提供目标的一些元数据,通常以__为前缀,例如标签、注解、服务名称等。这些元数据可用于在relabeling阶段过滤和修改目标。信息标签在重新标记阶段后被删除。基于Consul的服务发现Consul是HashiCorp开发的开源软件,支持多数据中心的分布式服务发现和键值对存储服务。它是一种通用的服务发现和注册工具,广泛应用于基于微服务的软件架构中。接下来我们尝试使用Prometheus基于Consul的服务发现来监控前面三个demo服务:192.168.31.46:10000192.168.31.46:10001192.168.31.46:10002我们将demo服务注册到Consul,然后配置Prometheus发现它来自ConsulDemo服务实例并使用Relabeling操作过滤和调整目标标签。关于Consul本身的使用,可以查看官方文档https://learn.hashicorp.com/consul了解更多。安装配置Consul在https://www.consul.io/downloads页面下载适合自己系统的安装文件。比如我们这里是Linux系统。使用以下命令下载安装:??wgethttps://releases.hashicorp.com/consul/1.10.2/consul_1.10.2_linux_amd64.zip??unzipconsul_1.10.2_linux_amd64.zip#将consul二次移动到PATH路径下去??mvconsul/usr/local/bin??consulversionConsulv1.10.2Revision3cb6eeedbProtocol2spokenbydefault,understands2to3(agentwillautomaticallyuseprotocol>2whenspeakingtocompatibleagents)consul命令执行时会有命令提示符,证明安装完成。然后创建一个用于注册演示服务的Consul配置文件demo-service.json:{"services":[{"id":"demo1","name":"demo","address":"192.168.31.46","port":10000,"meta":{"env":"production"},"checks":[{"http":"http://192.168.31.46:10000/api/foo","interval":"1s"}]},{"id":"demo2","name":"demo","address":"192.168.31.46","port":10001,"meta":{"env":"production"},"checks":[{"http":"http://192.168.31.46:10001/api/foo","interval":"1s"}]},{"id":"demo3","name":"demo","address":"192.168.31.46","port":10002,"meta":{"env":"staging"},"checks":[{"http":"http://192.168.31.46:10002/api/foo","interval":"1s"}]}]}当然一般我们也是在Consul中进行动态注册服务,这里只是简单演示一下Prometheus基于Consul.这里只使用Consul配置文件来静态注册服务,Consul允许使用JSON中的meta属性将key-value元数据关联到每个注册的服务实例,比如我们这里配置的env属性是关联部署的环境production或staging,后面我们可以使用Prometheus中的Relabeling操作,将这个字段提取出来映射到每个爬取实例的标签上。为了查看更多的日志信息,我们可以在dev模式下运行Consul,如下:??consulagent-dev-config-file=demo-service.json-client0.0.0.0==>StartingConsulagent...Version:'1.10.2'NodeID:'a4a9418c-7f7d-a2da-c81e-94d3d37601aa'Nodename:'node2'Datacenter:'dc1'(Segment:'')Server:true(Bootstrap:false)ClientAddr:[0.0.0.0](HTTP:8500,HTTPS:-1,gRPC:8502,DNS:8600)ClusterAddr:127.0.0.1(LAN:8301,WAN:8302)加密:Gossip:false,TLS-Outgoing:false,TLS-Incoming:false,Auto-Encrypt-TLS:false==>Logdatawillnowstreaminasitoccurs:...这里我们在启动命令后使用-client参数指定客户端绑定的IP地址,默认为127.0.0.1。除了我们注册的3个demo服务外,Consul代理也会将自己注册为名为consul的服务,我们可以在浏览器中访问http://:8500查看注册的服务。在ConsulUI页面,可以看到有consul和demo两个服务。配置Consul自动发现上面我们通过Consul注册了3个demo服务,接下来我们将配置Prometheus通过Consul自动发现demo服务。在Prometheus配置文件prometheus.yml文件的scrape_configs部分,添加如下爬取配置:scrape_configs:-job_name:"consul-sd-demo"consul_sd_configs:-server:"localhost:8500"relabel_configs:-action:keepsource_labels:[__meta_consul_service,__meta_consul_health]regex:demo;passing-action:labelmapregex:__meta_consul_service_metadata_(.*)replacement:consul_$1这里我们添加了一个抓包任务,名字叫consul-sd-demo,通过consul_sd_configs配置自动发现Consul服务地址,然后使用relabel_configs重新标记配置。首先,只保留服务名称为demo,健康状态为passing。否则ConsulAgent本身会被捕获,它不提供metrics接口数据。另外,Usinglabelmapforlabelmapping,将所有Consul元标签映射到Prometheus中以consul_为前缀的标签。配置完成后,重启Prometheus,然后再次查看Prometheus页面的targets页面,验证是否存在上述配置:正常情况下,可以看到会有一个consul-sd-demo任务,并且有3下自动发现抓取目标。我们可以将鼠标悬停在Labels标签区域,查看目标任务在重新标记Relabeling之前的原始标签。例如,我们在Relabel之前会检查第一个demo实例是否包含以下原始标签:也可以通过查看网络请求接口http:///api/v1/targets?state=获取对应的原始标签活动标签数据:{"discoveredLabels":{"__address__":"192.168.31.46:10000","__meta_consul_address":"127.0.0.1","__meta_consul_dc":"dc1","__meta_consul_health":"passing","__meta_consul_node":"node2","__meta_consul_service":"demo","__meta_consul_service_address":"192.168.31.46","__meta_consul_service_id":"demo1","__meta_consul_service_metadata_env":"生产","__meta_consul_service_port":"10000consul_service_port0"consul:"100consul_service_port0"consul":"10000consul_service_port":"_add_resta","__meta_consul_service_port":"10000consul_service_port":"_meta_consul_service_port":"10000consul_service_port":"_add_res_:"127.0.0.1","__meta_consul_tagged_address_lan_ipv4":"127.0.0.1","__meta_consul_tagged_address_wan":"127.0.0.1","__meta_consul_tagged_address_wan_ipv4":"127.0.0.1","__meta_consul_tags":",","__metrics_path__":"/metrics","__scheme__":"http","job":"consul-sd-demo"},"标签":{"consul_env":"production","instance":"192.168.31.46:10000","job":"consul-sd-demo"},"scrapePool":"consul-sd-demo","scrapeUrl":"http://192.168.31.46:10000/metrics","globalUrl":"http://192.168.31.46:10000/metrics","lastError":"","lastScrape":"2021-09-28T11:56:01.919216851+08:00","lastScrapeDuration":0.013357276,"health":"up"}我们首先在relabel_configs配置了一个keep操作,只保留原来的标签__meta_consul_service作为demo,__meta_consul_health作为Fetchingtask顺便保留状态然后使用labelmap进行标签映射,这里我们会匹配__meta_consul_service_metadata_(.*)的所有标签,这里只有原来的标签__meta_consul_service_metadata_env符合正则表达式,其中env是匹配的捕获组,replacement中用$1替换,替换为标签consul_$1是标签consul_env,所以Relabeling后,只剩下如下目标标签:instance:"192.168.31.46:10000"job:"consul-sd-demo"consul_env:"production"instance标签自动转换重新标记后来自__address__。由于没有重新修改__metrics_path__和__scheme__标签,所以默认的爬取目标是通过HTTP端点/metrics进行爬取。现在如果我们杀掉demo1服务,就会出现一个在Consul中注册的服务不健康的实例:当然,Prometheus中只剩下两个正常的demo服务实例:当服务正常时,可以自动对应服务发现。这样,我们就完成了一个简单的基于Consul的Prometheus自动发现配置。基于文件的服务发现除了基于Consul的服务发现,Prometheus还允许我们进行自定义发现集成。我们可以通过观察一组本地文件来获取爬取??目标和标签信息,也就是我们常说的基于文件的服务发现。服务发现方法。基于文件的服务发现提供了一种更通用的方式来配置静态目标,并充当插入自定义服务发现机制的接口。它读取一组包含零个或多个列表的文件。磁盘监控会检测到所有已定义文件的更改并立即应用。文件可以YAML或JSON格式提供。该文件必须包含静态配置列表:JSONjson[{"targets":["",...],"labels":{"":"",...}},...]YAMLyaml-targets:[-'']labels:[:...]文件内容也会按照指定的刷新间隔周期性的重新读取。#Patternsforfilesfromwhichtargetgroupsareextracted.files:[-...]#Refreshintervaltore-readthefiles.[refresh_interval:|default=5m]其中可以是以.json、.yml或.yaml结尾的文件路径,最后一个路径段可以包含匹配任何字符序列的*,例如:my/path/tg_*.json。创建文件接下来,让我们创建一个用于服务发现的目标文件。在与prometheus.yml文件相同的目录下创建一个名为targets.yml的文件。内容如下:-targets:-"192.168.31.46:10000"-"192.168.31.46:10001"labels:env:production-targets:-"192.168.31.46:10002"labels:env:staging这个文件中,我们列出了3个demo服务实例,在前两个实例中添加了env=production的标签,后面添加了env=staging的标签,当然文件也可以配置为JSON格式:[{"targets":["",...],"labels":{"":"",...}},...]如果是YAML文件,则格式为:-targets:[-'']labels:[:...]配置文件服务发现创建发现目标文件后,让Prometheus自动从上述目标中读取爬取目标。yml文件,需要在prometheus.yml配置文件中的scrape_configs部分添加爬虫配置,如下图:-job_name:"file-sd-demo"file_sd_configs:-files:-"targets.yml"重新加载或重启Prometheus重新读取配置文件信息,然后去同样到PrometheusUI的targets页面下,检查是否有上面定义的爬取目标。那么我们可以尝试更改targets.yml的内容,比如为第三个实例添加一个role:sd标签,无需重新加载Prometheus配置,Prometheus会监视该文件并自动接收任何更改。注意:在生产Prometheus服务器中更改file_sd目标文件时,需要确保更改是原子的,以避免重新加载错误。最好的方法是在单独的位置创建更新文件,然后将其重命名为目标文件名(使用mv命令或rename()系统调用)。这样,我们就完成了一个基于文件的通用服务发现机制,可以让我们在不重启或重载Prometheus服务的情况下动态改变Prometheus的监控目标。当然,除了Consul和基于文件的服务发现,更多时候我们会用到Kubernetes环境下的Prometheus。由于这部分内容比较独立,后面我们会单独讲解(其实前面已经详细介绍过了)。