5. 服务发现
当主机较少时,在抓取配置中手动列出它们的IP地址和端口是常见的做法,但不适用于较大规模的集群。尤其不适用使用容器和基于云的实例的动态集群,这些实例经常会变化、创建或销毁的情况。
Prometheus通过使用服务发现解决了这个问题:通过自动化的机制来检测、分类和识别新的和变更的目标。服务发现可以通过以下几种机制实现:
- 从配置管理工具生成的文件中接收目标列表。
- 查询API(例如AWS API)以获取目标列表
- 使用DNS记录以便返回目标列表
5.1 静态配置的局限性
在了解服务发现的工作原理前,先回顾下数据抓取的生命周期。如下图所示,当Prometheus 开始作业时,第一步就是服务发现,这将生成作业将要抓取的目标和元数据标签列表。
在现有的配置中,服务发现机制是在static_configs块中定义的。
scrape_configs:
config.
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "node"
static_configs:
- targets: ["localhost:9600"]
- job_name: "docker"
static_configs:
- targets: ["localhost:8080"]
从上可以看出,目标列表和关联标签都是采用手动服务发现的方式。可以看到在繁杂的工作中维护一长串主机列表并不是一个可扩展的任务。特别是对于大多数动态的集群环境,监控这些大集群的中的主机、应用程序和服务的规模,静态配置及其不方便。
选择成熟的服务发现机制显得尤为重要,常见的服务发现机制有:
- 基于文件的方式
- 基于云的方式
- 基于DNS的方式
5.2 基于文件进行服务发现
相比静态配置进行服务发现而言,基于文件的发现会更先进些。借助基于文件的服务发现,Prometheus 会使用文件中指定的目标。这些文件通常由另一系统生成,例如Puppet、Ansible或Chef等配置管理系统,或者从其他源(如CMDB)查询。定期执行脚本或进行查询可以(重新)生成这些文件。Prometheus 会按指定的时间计划从这些文件重新加载目标。
这些文件可以是YAML或JSON格式,包含定义的目标列表,就像我们在静态配置中定义它们一样。让我们从将现有作业迁移到基于文件的服务发现开始。
scrape_configs:
- job_name: "prometheus"
file_sd_configs:
- files:
- targets/prometheus/*.json
refresh_interval: 5m
- job_name: "node"
file_sd_configs:
- files:
- targets/node/*.json
refresh_interval: 5m
- job_name: "docker"
file_sd_configs:
- files:
- targets/docker/*.json
refresh_interval: 5m
我们用file_sd_configs块替换prometheus.yml文件中的 static_configs块。在这些块中,已经指定了文件列表,并包含在files列表中。我们在父目录targets下为每个作业指定对应的文件,并为每个作业创建一个子目录。你可以创建适合你的任何文件结构。
然后使用*.json的glob样式来指定文件。每当这些文件发生更改时,系统都将从此目录中所有以.json结尾的文件加载目标。我们选择JSON格式,因此它是一种方便使用各种语言和集成来编写的流行格式。
每次作业运行或这些文件发生变化时,Prometheus都会重新加载文件的内容。以防万一,我们还指定了refresh_interval选项,该选项将在每个间隔结束加载文件列表中的目标——对这个示例来说是5分钟。
让我们快速创建上述的目录结构。
sudo mkdir targets
sudo mkdir targets/{prometheus,node,docker}
将prometheus、节点和Docker守护进程列表移动到新的JSON文件,创建三个文件类保存这些目标。
sudo touch targets/prometheus/prometheus.json
sudo touch targets/node/node.json
sudo touch targets/docker/daemons.json
填充json文件,当然也可以使用yaml进行文件配置。
prometheus.json如下:
[{
"targets": [
"localhost:9090"
]
}]
node.json如下:
[{
"targets": [
"localhost:9600"
]
}]
daemons.json如下:
[{
"targets": [
"localhost:8080"
],
"labels": {
"datacenter": "nj"
}
}]
在这里,我们向Docker守护进程目标添加了值为nj的标签datacenter。基于文件的服务发现会在重新标记阶段自动给每个目标添加一个元数据标签_meta_filepath,它包含配置目标的文件路径和文件名。
编写文件
由于编写的JSON文件已经非常明确地定义了抓取目标的来源,当然可以使用能集中配置存储或配置管理数据库(CMDB)或者PuppetDB会更方便。
自定义编写脚本是,需要遵守以下几条简单的规则:
- 服务发现可配置——不要采用硬编码的方式。最好确保你的文件发现能够使用默认配置自动运行。如确保默认配置选项采用目标来源的默认安装状态。
- 不要在配置中暴露API或者秘钥、密码等信息,应该是依靠秘钥来保管库或环境变量。
- 针对输出目标的文件的操作应该是原子的。
PS: 在Prometheus文档中还有一个基于文档的服务发现集成列表。
服务启动
/usr/local/prometheus/prometheus --config.file="/usr/local/prometheus/prometheus.yml" &
启动后Prometheus结果如下:
5.3 基于API的服务发现
原生的服务发现集成在某些工具和平台上提供,它们内置支持Prometheus。这些服务发现插件使用工具和平台现有的数据存储或API来返回目标列表。
当前可用的本机服务发现插件包罗以下平台:
- Azure
- Amazon EC2
- Consual
- Google Compute Cloud
- Kuberneteszhe
Amazon EC2服务发现插件使用Amazon Web Service EC2 API来获取EC2实例列表,以用作 Prometheus目标。要是用该服务发现插件,需要拥有AWS账号,这里就不操作了。
5.4 基于DNS服务发现
当你不想选择基于文件的服务发现和基于API的服务发现,那么你可以选择基于DNS的服务发现。
这里不多做介绍,如果有兴趣可以在评论取留言。