工作笔记(2)—Prometheus服务发现机制
一、场景问题
在云原生、容器化的场景下,按需分配的方式成为主要的资源获取和使用方式。在这种情况下,所有的监控对象(基础设施、应用以及服务等)都在动态的变化。传统的基于Push模式的监控系统失去了一个固定地监控目标,不能很好的实时、准确地上报资源使用情况。
Prometheus
是一种典型的基于Pull模式的监控系统框架,其主要通过定义static_configs
配置文件,静态地去监控对象。为了解决上述问题,Prometheus
引入可服务发现模式。其基本的解决方法就是引入一个服务中心代理,可以存储所有监控对象的访问信息,Prometheus
只需要发送请求到服务注册中心就可以获取对应信息。
如上所示,体现Push
和Pull
的核心差异。相较于Push
模式,Pull
模式的优点可以简单总结为以下几点:
- 只要
Exporter
在运行,可以在任何地方(比如在本地),搭建你的监控系统; - 可以更容易的查看监控目标实例的健康状态,并且可以快速定位故障;
- 更利于构建
DevOps
文化的团队; - 松耦合的架构模式更适合于云原生的部署环境。
二、服务发现方式
根据Prometheus
的相关代码,总结目前支持的服务发现方式:
// 代码源于prometheus/discovery/config/config.go
type ServiceDiscoveryConfig struct {
StaticConfigs []*targetgroup.Group `yaml:"static_configs,omitempty"`
DNSSDConfigs []*dns.SDConfig `yaml:"dns_sd_configs,omitempty"`
FileSDConfigs []*file.SDConfig `yaml:"file_sd_configs,omitempty"`
ConsulSDConfigs []*consul.SDConfig `yaml:"consul_sd_configs,omitempty"`
ServersetSDConfigs []*zookeeper.ServersetSDConfig `yaml:"serverset_sd_configs,omitempty"`
NerveSDConfigs []*zookeeper.NerveSDConfig `yaml:"nerve_sd_configs,omitempty"`
MarathonSDConfigs []*marathon.SDConfig `yaml:"marathon_sd_configs,omitempty"`
KubernetesSDConfigs []*kubernetes.SDConfig `yaml:"kubernetes_sd_configs,omitempty"`
GCESDConfigs []*gce.SDConfig `yaml:"gce_sd_configs,omitempty"`
EC2SDConfigs []*ec2.SDConfig `yaml:"ec2_sd_configs,omitempty"`
OpenstackSDConfigs []*openstack.SDConfig `yaml:"openstack_sd_configs,omitempty"`
AzureSDConfigs []*azure.SDConfig `yaml:"azure_sd_configs,omitempty"`
TritonSDConfigs []*triton.SDConfig `yaml:"triton_sd_configs,omitempty"`
}
对应的模板如下:
# List of Azure service discovery configurations.
azure_sd_configs:
[ - <azure_sd_config> ... ]
# List of Consul service discovery configurations.
consul_sd_configs:
[ - <consul_sd_config> ... ]
# List of DNS service discovery configurations.
dns_sd_configs:
[ - <dns_sd_config> ... ]
# List of EC2 service discovery configurations.
ec2_sd_configs:
[ - <ec2_sd_config> ... ]
# List of OpenStack service discovery configurations.
openstack_sd_configs:
[ - <openstack_sd_config> ... ]
# List of file service discovery configurations.
file_sd_configs:
[ - <file_sd_config> ... ]
# List of GCE service discovery configurations.
gce_sd_configs:
[ - <gce_sd_config> ... ]
# List of Kubernetes service discovery configurations.
kubernetes_sd_configs:
[ - <kubernetes_sd_config> ... ]
# List of Marathon service discovery configurations.
marathon_sd_configs:
[ - <marathon_sd_config> ... ]
# List of AirBnB's Nerve service discovery configurations.
nerve_sd_configs:
[ - <nerve_sd_config> ... ]
# List of Zookeeper Serverset service discovery configurations.
serverset_sd_configs:
[ - <serverset_sd_config> ... ]
# List of Triton service discovery configurations.
triton_sd_configs:
[ - <triton_sd_config> ... ]
2.1 基于文件的服务发现
用户可以通过JSON
或YAML
格式的文件,定义所有的监控目标。例如,在下面的JSON
文件(targets.json)
中分别定义了3个采集任务,以及每个任务对应的Target
列表:
[
{
"targets": [ "localhost:8080"],
"labels": {
"env": "localhost",
"job": "cadvisor" #默认是prometheus.yml中配置的file_ds(见下),此cadvisor会覆盖前者
}
},
{
"targets": [ "localhost:9104" ],
"labels": {
"env": "prod",
"job": "mysqld"
}
},
{
"targets": [ "localhost:9100"],
"labels": {
"env": "prod",
"job": "node"
}
}
]
创建Prometheus
配置文件/etc/prometheus/prometheus-file-sd.yml
,并添加以下内容:
global:
scrape_interval: 15s
scrape_timeout: 10s
evaluation_interval: 15s scrape_configs:
- job_name: 'file_ds'
file_sd_configs:
- files:
- /opt/prometheus/file_sd_configs/targets.json #也可以模糊匹配多个文件
refresh_interval: 10s
通过这种方式,Prometheus
会自动的周期性读取文件中的内容。当文件中定义的内容发生变化时,不需要对Prometheus
进行任何的重启操作。
使用参考:https://www.cnblogs.com/xiangsikai/p/11289101.html
2.2 基于Consul的服务发现
Consul
是由HashiCorp
开发的一个支持多数据中心的分布式服务发现和键值对存储服务的开源软件,被大量应用于基于微服务的软件架构当中。
Consul作为一个通用的服务发现和注册中心,记录并且管理了环境中所有服务的信息。Prometheus
通过与Consul
的交互可以获取到相应Exporter
实例的访问信息。在Prometheus
的配置文件当可以通过以下方式与Consul
进行集成:
- job_name: node_exporter
metrics_path: /metrics
scheme: http
consul_sd_configs:
- server: localhost:8500 #指定了consul的访问地址
services: #为注册到consul中的实例信息
- node_exporter - cadvisor
在consul_sd_configs
定义当中通过server
定义了Consul
服务的访问地址,services
则定义了当前需要发现哪些类型服务实例的信息,这里限定了只获取node_exporter
和cadvisor
的服务实例信息。
使用参考:https://blog.csdn.net/aixiaoyang168/article/details/103022342,https://www.jianshu.com/p/a5dde3af8e18
2.3 DNS服务发现
Prometheus
的DNS
服务发现有俩种方法,第一种是使用DNA A
记录来做自动发现,第二种方法是DNS SRV
,第一种显然没有SRV
资源记录更为便捷,在这里就把俩种配置全部做一遍,对于取决用什么,根据你自己的环境来抉择。
DNA A
记录发现配置,首先你内网需要有一个DNS
服务器,或者直接自行配置解析记录即可,这里使用的dnsmasq
服务在内网测试
# 验证 test1 DNS记录
nslookup test1.example.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: test1.example.com
Address: 192.168.1.221
# 验证 test2 DNS记录
nslookup test2.example.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: test2.example.com
Address: 192.168.1.222
Prometheus配置
# 基于DNS A记录发现
- job_name: 'DNS-A' # job 名称
metrics_path: "/metrics" # 路径
dns_sd_configs:
- names: ["test1.example.com", "test2.example.com"] # A记录
type: A # 解析类型
port: 29100 # 端口
重启Prometheus
在targets
中可以看到dns-a
记录。
DNS SRV
是DNS
资源记录中的一种记录类型,用来指定服务器地址与端口,并且可以设置每个服务器的优先级和权重。访问到服务的时候,本地的DNS resolver
从DNS
服务器获取一个地址列表,然后根据优先级和权重来选择一个地址作为本次请求的目标地址。
SRV
的记录格式:
_service._proto.name. TTL class SRV priority weight port target
参数 | 说明 |
---|---|
_service |
服务名称,前缀 _ 是为了防止与DNS 标签(域名)冲突 |
proto |
服务使用的通讯协议 通常是 tcp udp
|
name |
此记录有效域名 |
TTL |
标准DNS class 字段 如 IN
|
priority |
记录优先级,数值越小,优先级越高。 0-65535 |
weight |
记录权重,数值越大,权重越高。0-65535 |
port |
服务使用端口 |
target |
使用服务的主机地址名称 |
这里没有使用named
,而是使用的dnsmasq
来做的测试,添加SRV
记录完成后,需要重启dnsmasq
服务使其生效。
# 配置dns解析
cat /etc/dnsmasq.d/localdomain.conf
address=/test1.example.com/192.168.1.221
address=/test2.example.com/192.168.1.222
# 添加 SRV 记录
cat /etc/dnsmasq.conf
srv-host =_prometheus._tcp.example.com,test1.example.com,29100
srv-host =_prometheus._tcp.example.com,test2.example.com,29100
# 验证srv服务是否正确,192.168.1.123 是内部DNS服务器,
dig @192.168.1.123 +noall +answer SRV _prometheus._tcp.example.com
output...
_prometheus._tcp.example.com. 0 IN SRV 0 0 9100 test1.example.com.
_prometheus._tcp.example.com. 0 IN SRV 0 0 9100 test2.example.com.
Prometheus配置完成以后,重载Prometheus服务。
- job_name: 'DNS-SRV' # 名称
metrics_path: "/metrics" # 获取数据的路径
dns_sd_configs: # 配置使用DNS解析
- names: ['_prometheus._tcp.example.com'] # 配置SRV对应的解析地址
这个时候在targets中可以看到DNS自动发现的记录了。
这个时候,我们在新加一个记录,用来做自动发现。
# 添加test0解析
cat /etc/dnsmasq.d/localdomain.conf
address=/test1.example.com/192.168.1.221
address=/test2.example.com/192.168.1.222
address=/test0.example.com/192.168.1.220
# 添加 test0 SRV 记录
cat /etc/dnsmasq.conf
srv-host =_prometheus._tcp.example.com,test1.example.com,29100
srv-host =_prometheus._tcp.example.com,test2.example.com,29100
srv-host =_prometheus._tcp.example.com,test0.example.com,19100
# 验证dns SRV记录是否成功
dig @192.168.1.123 +noall +answer SRV _prometheus._tcp.example.com
_prometheus._tcp.example.com. 0 IN SRV 0 0 19100 test0.example.com.
_prometheus._tcp.example.com. 0 IN SRV 0 0 29100 test2.example.com.
_prometheus._tcp.example.com. 0 IN SRV 0 0 29100 test1.example.com.
168.1.123 +noall +answer SRV _prometheus._tcp.example.com
_prometheus._tcp.example.com. 0 IN SRV 0 0 19100 test0.example.com.
_prometheus._tcp.example.com. 0 IN SRV 0 0 29100 test2.example.com.
_prometheus._tcp.example.com. 0 IN SRV 0 0 29100 test1.example.com.
这个时候在去观察targets就发现已经可以自动发现test0了。