云原生第十一周——prometheus服务发现

Prometheus 服务发现

简介

prometheus采用pull方式拉取指定目标实例的监控数据,也就是间隔固定的周期去目标实例上抓取metrics数据,每一个被抓取的目标实例都需要暴露一个数据指标API接口,prometheus通过这个暴露的接口就可以获取到其指标数据,这种方式需要由目标服务决定采集的指标有哪些,prometheus通过配置在scrape_configs中指定目标节点,static_configs(静态配置)无法动态感知新的节点,即如果后面增加了节点或者删除节点,就得手动修promrtheus的配置文件,并重启promethues,因此后期维护很不方便,所以出现了很多不同类型的service discovery即动态服务发现机制,动态服务发现能够使prometheus自动发现集群中的新目标,并对其进行数据采集,通过服务发现机制使Prometheus能自动获取到需要监控的Target列表,然后轮询这些Target获取监控数据。

prometheus常用的服务发现类型:

  • kubernetes_sd_configs: #基于Kubernetes API实现的服务发现,让prometheus动态发现kubernetes中被监控的新目标
  • static_configs: #静态服务发现,基于prometheus配置文件指定的监控目标
  • dns_sd_configs: #DNS 服务发现监控目标
  • consul_sd_configs: #Consul 服务发现,基于consul服务动态发现监控目标
  • file_sd_configs: #基于指定的文件实现服务发现,基于指定的文件发现监控目标

基于kubernetes_sd_config支持的动态服务发现类型:

  • node #node节点
  • service #发现svc
  • pod #发现pod
  • endpoints #基于svc发现endpoints(pod)
  • Endpointslice #对endpoint进行切片
  • ingress #发现ingress

image

Prometheus服务发现基础-relabeling:

promethues的relabeling(重新修改标签)功能很强大,它能够在抓取到目标实例之前把目标实例的元数据标签动态重新修改,动态
添加或者覆盖标签。

prometheus从Kubernetes API动态发现目标(targer)之后,在被发现的target实例中,都包含一些原始的Metadata标签信息,默认的标签有:

__address__:以<host>:<port> 格式显示目标targets的地址
__scheme__:采集的目标服务地址的Scheme形式,HTTP或者HTTPS
__metrics_path__:采集的目标服务的访问路径

为了更好的识别监控指标,便于后期调用数据绘图、告警等需求,prometheus支持对发现之后的目标进行label修改,在两个阶段可以重新标记:

  • relabel_configs : 在对target进行数据采集之前(比如在采集数据之前重新定义标签信息,如目的IP、目的端口等信息),可以使用relabel_configs添加、修改或删除一些标签、也可以只采集特定目标或过滤目标。

  • metric_relabel_configs:在对target进行数据采集之后,即如果是已经抓取到指标数据时,可以使用metric_relabel_configs做最后的重新标记和过滤。

image

label类型:

  • source_labels:源标签,没有经过relabel处理之前的标签名字
  • target_label:通过action处理之后的新的标签名字
  • regex:给定的值或正则表达式匹配,匹配源标签的值
  • replacement:通过分组替换后标签(target_label)对应的/()/() $1:$2

配置示例:

静态配置:

- job_name: "prometheus-node"
static_configs:
- targets: ["192.168.110.206:9100","192.168.110.207:9100"]

基于kubernetes API Server的动态发现:

- job_name: 'kubernetes-apiserver' #job名称
kubernetes_sd_configs: #基于kubernetes_sd_configs实现服务发现
- role: endpoints #发现类型为endpoinsts
scheme: https #当前jod使用的发现协议
tls_config: #证书配置
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt #容器里的证书路径
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token #容器里的token路径
relabel_configs: #重新re修改标签label配置configs
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] #源标签,即对哪些标签进行操作
action: keep #action定义了relabel的具体动作,action支持多种
regex: default;kubernetes;https #指定匹配条件、只发现default命名空间的kubernetes服务后面的endpoint并且是https协议

action简介:

  • replace: #替换标签值,根据regex正则匹配到源标签的值,使用replacement来引用表达式匹配的分组。
  • keep: #满足regex正则条件的实例进行采集,把source_labels中没有匹配到regex正则内容的Target实例丢掉,即只采集匹配成功的实例。
  • drop: #满足regex正则条件的实例不采集,把source_labels中匹配到regex正则内容的Target实例丢掉,即只采集没有匹配到的实例。
  • labelmap:#匹配regex所有标签名称,然后复制匹配标签的值进行分组,可以通过replacement分组引用(${1},${2},…)替代
  • labelkeep:匹配regex所有标签名称,其它不匹配的标签都将从标签集中删除
  • labeldrop:匹配regex所有标签名称,其它匹配的标签都将从标签集中删除
  • hashmod:使用hashmod计算source_labels的Hash值并进行对比,基于自定义的模数取模,以实现对目标进行分类、重新赋值等功能

image

查看prometheus server容器证书:

image

image

可以看到容器的ca.crt 和宿主机/etc/kubernetes/ssl/ca.pem文件的md5值是一样的

Prometheus服务发现示例 api-server:


 vim case3-1-prometheus-cfg.yaml
- job_name: 'kubernetes-apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https #含义为匹配defaultnamespace,svc名称是kubernetes并且协议是https,匹配成功后进行保留,并且基于regex指定
匹配条件,最后source_labels为key、regex为value一一进行赋值,如下:
#__meta_kubernetes_namespace=default,__meta_kubernetes_service_name=kubernetes,__meta_kubernetes_endpoint_port_name=https

image

Prometheus服务发现示例-annotation

关于annotation_prometheus_io_scrape及kubernetes_service_annotation_prometheus_io_port:
在k8s中,如果deployment的yaml文件指定了annotation_prometheus_io_scrape及kubernetes_service_annotation_prometheus_io_port,那么基于prometheus的发现规则,需要在被发现的目的target定义注解匹配annotation_prometheus_io_scrape的值为true和kubernetes_service_annotation_prometheus_io_port对应的端口号如9153,且必须匹配成功该注解才会保留监控target,然后再进行数据抓取并进行标签替换,主要用于精确匹配目的target(过滤掉不匹配的其它target):

- job_name: 'kubernetes-service-endpoints' #job名称
kubernetes_sd_configs: #sd_configs发现
- role: endpoints #角色,endpoints 发现
relabel_configs: #标签重写配置
#匹配annotation_prometheus_io_scrape的值为true,保留标签然后再向下执行
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
#将__meta_kubernetes_service_annotation_prometheus_io_scheme修改为__scheme__
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?) #基于正则匹配协议http或https(?匹配全面的字符0次或一次),即其它协议不替换
#将__meta_kubernetes_service_annotation_prometheus_io_path替换为__metrics_path__
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+) #匹配路径为为1到任意长度(.为匹配除\n之外的任意单个字符,+为匹配一次或多次)
#地址发现及标签重写
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2 #格式为地址:端口
#匹配regex所匹配的标签,然后进行应用:
- action: labelmap
regex: __meta_kubernetes_service_label_(.+) #通过正则匹配名称


Prometheus服务发现示例 node:

root@k8s-master1:~/prometheus-case-files# vim case3-1-prometheus-cfg.yaml
kind: ConfigMap
apiVersion: v1
metadata:
labels:
app: prometheus
name: prometheus-config
namespace: monitor-sa
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_timeout: 10s
evaluation_interval: 1m
scrape_configs:
- job_name: 'kubernetes-node' #job name
kubernetes_sd_configs: #发现配置
- role: node #发现类型
relabel_configs: #标签重写配置
- source_labels: [__address__] #源标签
regex: '(.*):10250' #通过正则匹配后缀为:10250的实例,10250是kubelet端口
replacement: '${1}:9100' #重写为IP:9100,即将端口替换为prometheus node-
exporter的端口
target_label: __address__ #将[__address__]替换为__address__
action: replace #将[__address__] 的值依然赋值给__address__
#发现lable并引用
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)

image

node节点指标数据:


node节点常见监控指标:
node_cpu_:CPU相关指标
node_load1:load average #系统负载指标
node_load5
node_load15
node_memory_:内存相关指标
node_network_:网络相关指标
node_disk_:磁盘IO相关指标
node_filesystem_:文件系统相关指标
node_boot_time_seconds:系统启动时间监控
go_*:node exporte运行过程中go相关指标
process_*:node exporter运行时进程内部进程指标

Prometheus服务发现示例 Cadvisor :

tls_config配置的证书地址是每个Pod连接apiserver所使用的地址,无论证书是否用得上,在Pod启动的时候kubelet都会给每一个pod自动注入ca的公钥,即所有的pod启动的时候都会有一个ca公钥被注入进去用于在访问apiserver的时候被调用。


root@k8s-master1:~/prometheus-case-files# vim case3-1-prometheus-cfg.yaml
- job_name: 'kubernetes-node-cadvisor' #job 名称
kubernetes_sd_configs: #基于k8s的服务发现
- role: node #角色
scheme: https #协议
tls_config: #证书配置
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt #默认crt证书路径
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token #默认token路径
relabel_configs: #标签重写配置
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
#replacement指定替换后的标签(target_label)对应的值为kubernetes.default.svc:443
- target_label: __address__
replacement: kubernetes.default.svc:443
#将[__meta_kubernetes_node_name]重写为 __metrics_path__
- source_labels: [__meta_kubernetes_node_name]
regex: (.+) #至少1位长度以上
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor #指定cadvisord的API路径
查看cadvisor数据:
# curl --cacert /etc/kubernetes/ssl/ca.pem -H "Authorization: Bearer $TOKEN"
https://172.31.7.101:6443/api/v1/nodes/172.31.7.113/proxy/metrics/cadvisor

image

Prometheus服务发现示例 pod:


prometheus job配置:
root@k8s-master1:~/prometheus-case-files# kubectl apply -f case3-4-nginx.yaml
root@k8s-master1:~/prometheus-case-files# vim case3-1-prometheus-cfg.yaml
- job_name: 'kubernetes-nginx-pods'
kubernetes_sd_configs:
- role: pod
namespaces: #可选指定namepace,如果不指定就是发现所有的namespace中的pod
names:
- myserver
- magedu
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name

image

基于kube-state-metrics监控Service、Deployment、ingress等资源对象的指标状态

kube-state-metrics:

Kube-state-metrics:通过监听API Server生成有关资源对象的状态指标,比如Service、Deployment、Node、Pod等,需要注意的是kube-state-metrics的使用场景不是用于监控对方是否存活,而是用于周期性获取目标对象的metrics指标数据并在web界面进行显示或被prometheus抓取(如pod的状态是running还是Terminating、pod的创建时间等、Deployment、Pod、副本状态等,调度了多少个replicas?现在可用的有几个?多少个Pod是running/stopped/terminated状态?Pod重启了多少次? 目前有多少job在运行中),目前的kube-state-metrics收集的指标数据可参见官方的文档,https://github.com/kubernetes/kube-state-metrics/tree/master/docs ,kube-state-metrics并不会存储这些指标数据,所以需要使用Prometheus来抓取这些数据然后存储。

root@192:/usr/local/src/20230701/1.prometheus-case-files# cat case6-kube-state-metrics-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kube-state-metrics
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kube-state-metrics
  template:
    metadata:
      labels:
        app: kube-state-metrics
    spec:
      serviceAccountName: kube-state-metrics
      containers:
      - name: kube-state-metrics
        image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/kube-state-metrics:v2.6.0 
        ports:
        - containerPort: 8080

---
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kube-state-metrics
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kube-state-metrics
rules:
- apiGroups: [""]
  resources: ["nodes", "pods", "services", "resourcequotas", "replicationcontrollers", "limitranges", "persistentvolumeclaims", "persistentvolumes", "namespaces", "endpoints"]
  verbs: ["list", "watch"]
- apiGroups: ["extensions"]
  resources: ["daemonsets", "deployments", "replicasets"]
  verbs: ["list", "watch"]
- apiGroups: ["apps"]
  resources: ["statefulsets"]
  verbs: ["list", "watch"]
- apiGroups: ["batch"]
  resources: ["cronjobs", "jobs"]
  verbs: ["list", "watch"]
- apiGroups: ["autoscaling"]
  resources: ["horizontalpodautoscalers"]
  verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kube-state-metrics
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kube-state-metrics
subjects:
- kind: ServiceAccount
  name: kube-state-metrics
  namespace: kube-system

---
apiVersion: v1
kind: Service
metadata:
  annotations:
    prometheus.io/scrape: 'true'
  name: kube-state-metrics
  namespace: kube-system
  labels:
    app: kube-state-metrics
spec:
  type: NodePort
  ports:
  - name: kube-state-metrics
    port: 8080
    targetPort: 8080
    nodePort: 31666
    protocol: TCP
  selector:
    app: kube-state-metrics

image

导入kube-state-metrics模板10856并验证数据:

image

Prometheus 基于consul、file、dns实现服务发现

部署consul

root@k8s-deploy:~/docker-compose-deploy-single-consul# pwd
/root/docker-compose-deploy-single-consul
root@k8s-deploy:~/docker-compose-deploy-single-consul# docker-compose up -d

配置prometheus基于consul实现监控目标发现

- job_name: consul
honor_labels: true
metrics_path: /metrics
scheme: http
consul_sd_configs:
- server: 192.168.110.207:8500
services: [] #发现的目标服务名称,空为所有服务,可以写servicea,servcieb,servicec
relabel_configs:
- source_labels: ['__meta_consul_tags']
target_label: 'product'
- source_labels: ['__meta_consul_dc']
target_label: 'idc'
- source_labels: ['__meta_consul_service']
regex: "consul"
action: drop

image

Prometheus服务发现案例-文件:

基于文件的发现,由于使用的是k8s安装的prometheus,因此配置文件的引用需要挂载存储
进入nfs服务器 编写json文件
image

修改prometheus配置文件 添加文件发现:

image

重新启动Prometheus

image

Prometheus服务发现案例-DNS:

基于DNS实现服务发现:

  • 基于 DNS 的服务发现允许配置指定一组 DNS 域名,这些域名会定期查询以发现目标列表,域名需要可以被配置的DNS服务器解析为IP。
  • 此服务发现方法仅支持基本的 DNS A、AAAA 和 SRV 记录查询。
  • A记录: 域名解析为IP
  • SRV:SRV记录了哪台计算机提供了具体哪个服务,格式为:自定义的服务的名字.协议的类型.域名(例如:_example-server._tcp.www.mydns.com)

prometheus会对收集的指标数据进行重新打标,重新标记期间,可以使用以下元标签:
__meta_dns_name:产生发现目标的记录名称。
__meta_dns_srv_record_target: SRV 记录的目标字段
__meta_dns_srv_record_port: SRV 记录的端口字段

A记录服务发现:

# vim /etc/hosts
172.31.2.181 node1.example.com
172.31.2.182 node2.example.com
# vim /apps/prometheus/prometheus.yml
- job_name: 'dns-server-name-monitor'
metrics_path: "/metrics"
dns_sd_configs:
- names: ["node1.example.com", "node2.example.com"]
type: A
port: 9100
# systemctl restart prometheus.service

SRV服务发现:
需要有DNS服务器实现域名解析

# vim /apps/prometheus/prometheus.yml
- job_name: 'dns-node-monitor-srv'
metrics_path: "/metrics"
dns_sd_configs:
- names: ["_prometheus._tcp.node.example.com"]
type: SRV
port: 9100
# systemctl restart prometheus.service
posted @   黑夜有约  阅读(124)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示