袁党生博客

  • 主页
  • linux基础
  • SHELL
  • WEB
  • 负载
  • 企业级应用
  • 数据库
  • KVM
  • Docker
  • K8S
  • 监控
  • 存储
  • 博客搭建问题
  1. 首页
  2. 监控
  3. 正文

五、prometheus的服务发现机制

2024年1月9日 3779点热度 0人点赞 0条评论


本章概述

  • relabeling简介
  • 动态发现:kubernetes_sd_configs
  • 静态发现static_configs
  • consul实现服务发现:consul_sd_configs
  • 基于文件的服务发现:file_sd_configs
  • DNS服务发现

前言
  prometheus 默认是采用pull方式拉取监控数据的,也就是定时去目标主机上抓取metrics数据,每一个被抓取的目标需要暴露一个 HTTP 接口,prometheus通过这个暴露的接口就可以获取到相应的指标数据。这种方式需要由目标服务决定采集的目标有哪些,通过配置在scrape_configs中的各种job 来实现,无法动态感知新服务,如果后面增加了节点或者组件信息,需要手动修改promrtheus配置,并重启 promethues服务,很不方便。
  因此就出现了动态服务发现,动态服务发现能够自动发现集群中的新端点,并加入到配置中,通过服务发现,Prometheus能查询到需要监控的Target列表,然后轮询这些Target 获取监控数据。
  prometheus 获取数据源 target 的方式有多种,如静态配置和动态服务发现配置,prometheus 目前支持的服务发现有很多种,常用的主要分为以下几种:

(1)kubernetes_sd_configs: #基于Kubernetes API实现的服务发现,让prometheus动态发现kubernetes中被监控的目标(要求prometheus部署在k8s集群内)
(2)static_configs: #静态服务发现,基于prometheus配置文件指定的监控目标
(3)dns_sd_configs: #DNS服务发现监控目标
(4)consul_sd_configs: #Consul服务发现,基于consul服务动态发现监控目标
(5)file_sd_configs: #基于指定的文件实现服务发现,基于指定的文件发现监控目标

服务发现机制说明:

promethues 的静态静态服务发现 static_configs:
    每当有一个新的目标实例需要监控,都需要手动修改配置文件配置目标 target。
promethues 的 consul 服务发现 consul_sd_configs:
    Prometheus 一直监视 consul 服务,当发现在 consul中注册的服务有变化,prometheus 就会自动监控到所有注册到 consul 中的目标资源。
promethues 的 k8s 服务发现 kubernetes_sd_configs:
    Prometheus 与 Kubernetes 的 API 进行交互,动态的发现 Kubernetes 中部署的所有可监控的目标资源。
static_configs和file_sd_configs的区别在于:
    通过static_configs实现静态服务发现,修改文件后需要重启prometheus服务,而file_sd_configs方式则无需重启prometheus服务

5.1 relabeling简介

  官网链接:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
  promethues 的 relabeling(重新修改标签)功能很强大,它能够在抓取到目标实例之前把目标实例的元数据标签动态重新修改,动态添加或者覆盖标签
  prometheus 从 Kubernetes API 动态发现目标(targer)之后,在被发现的 target 实例中,都包含一些原始的Metadata 标签信息(这些信息是k8s集群内置的、自带的元数据标签),默认的标签有:

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

可以在官网查看不同类型relabel如何进行配置:

5.1.1 relabel介绍

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

relabel_configs : 
    在对 target 进行数据采集之前(比如在采集数据之前重新定义标签信息,如目的 IP、目的端口等信息),可以使用relabel_configs添加、修改或删除一些标签、也可以只采集特定目标或过滤目标。大多是在数据采集之前对标签进行修改或删除,修改完成后便于数据的采集和抓取。
metric_relabel_configs:
    在对 target 进行数据采集之后,即如果是已经抓取到指标数据时,可以使用metric_relabel_configs 做最后的重新标记和过滤。

常用方式:数据采集之前进行标签修改(relabel_configs)
(1)prometheus启动后,加载配置文件
(2)根据配置文件中的服务发现配置,对标签进行修改(relabel_configs)
(3)根据修改后的标签进行数据抓取
(4)抓取后将数据写入到TSDB
这种方式就不需要metrics_relabel_configs配置。

示例:

- job_name: 'kubernetes-apiserver'    #job 名称
kubernetes_sd_configs:          #基于 kubernetes_sd_configs 实现服务发现
- role: endpoints                #发现 endpoints
scheme: https                  #当前 jod 使用的发现协议
tls_config:                     #证书配置
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt   #容器里的公钥证书路径,k8s在创建容器时内嵌到容器内的证书,默认就在该路径下,和宿主机的公钥/etc/kubernetes/ssl/ca.pe保持一致
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token    #容器里的 token 路径
relabel_configs:            #重新修改标签 label 配置 configs
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name,__meta_kubernetes_endpoint_port_name]  #源标签,即对哪些标签进行操作,这里是对namespace,servicename,endpoint端口协议标签进行操作
action: keep    #action 定义了 relabel 的具体动作,对标签进行什么操作,action 支持多种,keep是指将匹配到的标签保留,不匹配的删除掉
regex: default;kubernetes;https    #通过正则表达式进行过滤,匹配规则是default 命名空间,servicename是 kubernetes,协议是https

5.1.1.2 label详解
source_labels:源标签,没有经过 relabel 处理之前的标签名字
target_label:通过 action 处理之后的新的标签名字
regex:给定的值或正则表达式匹配,匹配源标签
replacement:通过分组替换后标签(target_label)对应的值,可以通过$1来引用正则表达式中匹配的值
如:

regex: '(.*):10250'    #通过正则表达式进行匹配, (.*)是指ip地址为任意ip地址,端口为10250
replacement: '${1}:9100'    #${1}是指引用regex中的ip地址,即任意ip地址,将端口替换为9100

5.1.1.3 action详解
官网链接:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
replace:
  替换标签值,根据 regex 正则匹配到源标签的值,使用 replacement 来引用表达式匹配的分组
keep:
  只采集满足 regex 正则条件的实例,将source_labels中不匹配regex 正则内容的Targ实例丢弃
drop:
  和keep相反,只采集不满足 regex 正则条件的实例,将source_labels 中匹配到 regex 正则内容的 Target 实例丢弃
示例:prometheus的yaml文件中服务发现配置
vim case3-1-prometheus-cfg.yaml #这里只贴出数据抓取配置

    scrape_configs:
    - job_name: 'kubernetes-node'   #job名称,后续配置主要是对k8s集群内的node进行服务发现配置
      kubernetes_sd_configs:      #基于kubernetes_sd_configs实现服务发现
      - role: node               #服务发现配置的目标对象是node
      relabel_configs:            #重写配置
      - source_labels: [__address__]      #保留ip地址,把10250端口(kubelet端口)重写为9100端口,对该端口进行数据抓取,该端口正是node-exporter的端口(prometheus通过apiserver获取node数据,apiserver和kubelet保持长链接,kubelet端口是10250,因此需要把10250重写为9100)
        regex: '(.*):10250'      #通过正则表达式进行匹配, (.*)是指ip地址为任意ip地址,端口为10250
        replacement: '${1}:9100'   #注意${1}是引用regex中的ip地址,即任意ip地址,将端口替换为9100
        target_label: __address__         #目标label保持不变
        action: replace               #执行动作是替换,把10250端口替换为9100端口
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
    - job_name: 'kubernetes-node-cadvisor-n66'     #对k8s集群内的cadvisor进行服务发现配置,抓取k8s集群中容器的数据
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]      #保留ip地址,包端口10250替换为8080,对该端口进行数据抓取,该端口是cadvisor的端口
        regex: '(.*):10250'      #通过正则表达式进行匹配,ip地址为任意,端口为10250
        replacement: '${1}:8080'
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)

hashmod:
  使用 hashmod 计算 source_labels 的 Hash 值并进行对比,基于自定义的模数取模,以实现对目标进行分类、重新赋值等功能
示例:

scrape_configs:
- job_name: ip_job
relabel_configs:
- source_labels: [__address__]
modulus: 4       #对4取模
target_label: __ip_hash
action: hashmod
- source_labels: [__ip_hash]
regex: ^1$
action: keep

labelmap:
  匹配 regex 所有标签名称,然后复制匹配标签的值进行分组,通过 replacement 分组引用(${1},${2},…)替代
labelkeep:
  匹配 regex 所有标签名称,其它不匹配的标签都将从标签集中删除
labeldrop:
  匹配 regex 所有标签名称,其它匹配的标签都将从标签集中删除
示例:labelmap标签过滤和替换

    scrape_configs:
    - job_name: 'kubernetes-node'
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: '${1}:9100'
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)   #通过正则表达式匹配,只保留匹配到的值,而不保留__meta_kubernetes_node_label_,如:匹配到__meta_kubernetes_node_label_
    - job_name: 'kubernetes-node-cadvisor-n66'
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: '${1}:8080'
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)

查看node主机172.31.7.101的标签:

查看prometheus监控页面标签:
以下为重写之前(Before relabeling)匹配到的标签:

以下为重写之后的标签:

可以看到,重写之后的标签只保留了正则表达式__meta_kubernetes_nodelabel\(.+)中(.+)所匹配到的内容,并将该内容作为新的label,这些标签正是node上的label,根据这些label进行条件过滤
5.1.1.4 测试label功能
(1)将case3-1-prometheus-cfg.yaml文件中配置删除,然后查看prometheus监控页面,查看获取到的数据情况
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

(2)重新加载配置文件
kubectl apply -f case3-1-prometheus-cfg.yaml
(3)重新创建prometheus server
kubectl delete -f case3-2-prometheus-deployment.yaml && kubectl apply -f case3-2-prometheus-deployment.yaml
(4)修改前监控页面的数据如下:

(5)修改后的监控页面数据如下:
可以看到由于没有进行条件过滤,prometheus监控可以获取到所有namespace下的pod,而且有些pod因为对应端口下并没有抓取到的数据,因此处于down状态

因此,要对监控的资源进行条件限制
5.1.1.5 查看 prometheus server 容器证书
prometheus的yaml文件中配置的证书和宿主机上的ca证书是一样的

    - 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

随意找到一个容器进入查看ca证书,并用md5sum进行校验
kubectl get pod -n monitoring
kubectl exec -it prometheus-server-6bc679b999-52tkt -n monitoringls /var/run/secrets/kubernetes.io/serviceaccount/

容器内ca证书校验值为1a234520294780a972ab9b02658fe11b
对宿主机上的ca证书进行校验,校验值为1a234520294780a972ab9b02658fe11b

因此证书是一样的

5.2 动态发现:kubernetes_sd_configs

5.2.1 支持的发现目标类型

官网链接:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
发现的资源类型类型可以配置以下类型之一来发现目标:

(1)node
(2)service
(3)pod
(4)endpoints
(5)Endpointslice   #对 endpoint 进行切片,使用较少
(6)ingress

5.2.2 监控 api-server 实现

  apiserver 作为 Kubernetes 最核心的组件,它的监控也是非常有必要的,对于apiserver 的监控,我们可以直接通过 kubernetes 的 service 来获取
示例:
vim case3-1-prometheus-cfg.yaml #这里只贴出api-server数据抓取配置部分
由于集群外的主机不能访问api-server,因此需要配置证书

    - 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   #含义为匹配 default 的 namespace,svc 名称是 kubernetes,并且协议是 https,匹配成功后进行保留,并且把 regex 作为 source_labels 相对应的值。即 labels 为 key、regex 为值。

label 替换方式如下:
__meta_kubernetes_namespace=default,__meta_kubernetes_service_name=kubernetes,__meta_kubernetes_endpoint_port_name=https
最终,匹配到 api-server 的地址
查看api-server的信息,与匹配规则相符合

Prometheus监控上获取的标签信息如下:(注意:以下标签为重写之前(Before relabeling)的标签,这些标签在匹配过滤之后会根据规则进行重写,grafana最终显示的是重写之后的标签)
查看重写之前的标签:

重写之后的标签:

5.2.2.1 api-server 指标数据
  Apiserver 组件是 k8s 集群的入口,所有请求都是从 apiserver 进来的,所以对apiserver 指标做监控可以用来判断集群的健康状况。
1、apiserver_request_total
以下 promQL 语句为查询 apiserver 最近一分钟不同方法的请求数量统计:
apiserver_request_total 为请求各个服务的访问详细统计:
示例:
sum(rate(apiserver_request_total[10m]))by(resource,subresource,verb)

  irate 和 rate 都会用于计算某个指标在一定时间间隔内的变化速率。但是它们的计算方法有所不同:irate 取的是在指定时间范围内的最近两个数据点来算速率,而 rate 会取指定时间范围内所有数据点,算出一组速率,然后取平均值作为结果。
  所以官网文档说:irate 适合快速变化的计数器(counter),而 rate 适合缓慢变化的计数器(counter)。
  根据以上算法我们也可以理解,对于快速变化的计数器,如果使用 rate,因为使用了平均值,很容易把峰值削平。除非我们把时间间隔设置得足够小,就能够减弱这种效应。
示例:
rate(apiserver_request_total{code=~"^(?:2..)$"}[5m])

2、关于 annotation_prometheus_io_scrape
  在k8s中,有些容器会存在注解信息(即annotation字段),我们可以根据这些注解对目标资源进行过滤
  基于prometheus的发现规则,在目标资源上定义注解 annotation_prometheus_io_scrape=true,然后prometheus的yaml配置文件中进行服务发现配置,prometheus匹配成功后,再进行数据抓取并替换标签,如 annotation_prometheus_io_scheme标签为 http 或 https
查看kube-dns的注解信息(annotations)

因此可以在prometheus配置文件的服务发现配置中根据该注解对kube-dns容器进行数据抓取,如注解为prometheus.io/scrape,值为true时才会进行数据抓取

示例:查看prometheus的配置文件数据抓取配置
vim case3-1-prometheus-cfg.yaml #这里之贴出部分数据抓取配置

    - job_name: 'kubernetes-service-endpoints'
      kubernetes_sd_configs:
      - role: endpoints
      relabel_configs:

#annotation_prometheus_io_scrape 的值为 true,保留标签然后再向下执行
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]   #指定源标签
        action: keep       #正则匹配成功后保留标签
        regex: true    #正则表达式指定:annotation_prometheus_io_scrape 的值为 true

#将__meta_kubernetes_service_annotation_prometheus_io_scheme 修改为__scheme__
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]  #原标签
        action: replace       #匹配成功后进行标签替换
        target_label: __scheme__    #将__meta_kubernetes_service_annotation_prometheus_io_scheme 修改为__scheme__
        regex: (https?)        #正则匹配协议 http 或 https,(?是指匹配前面的字符0次或1次,即http或https协议),其它协议不替换

#将 source_labels 替换为 target_label,target_label为__metrics_path__
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]   #原标签
        action: replace      #匹配成功后进行表爱你替换
        target_label: __metrics_path__   #将 __meta_kubernetes_service_annotation_prometheus_io_path替换为__metrics_path__
        regex: (.+)          #正则匹配路径为为 1 到任意长度

#地址发现及标签重写
      - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]  
        action: replace
        target_label: __address__    #两个标签合的值通过一个标签显示,但该标签中显示的是ip和port
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2         #格式为地址:端口,引用正则表达式匹配成功的ip和端口

#发现新的label,并用新的 service name 作为 label,将发现的值作为新的 label 的值
      - action: labelmap   
        regex: __meta_kubernetes_service_label_(.+)    #通过正则匹配 service name

#将__meta_kubernetes_namespace 替换为 kubernetes_namespace
      - source_labels: [__meta_kubernetes_namespace]    #将__meta_kubernetes_namespace 替换为 kubernetes_namespace
        action: replace
        target_label: kubernetes_namespace

#将__meta_kubernetes_service_name 替换为 kubernetes_name
      - source_labels: [__meta_kubernetes_service_name]    #将__meta_kubernetes_service_name 替换为 kubernetes_name
        action: replace
        target_label: kubernetes_name

(1)重新加载配置文件
kubectl apply -f case3-1-prometheus-cfg.yaml
(2)重新部署prometheus
kubectl delete -f case3-2-prometheus-deployment.yaml && kubectl apply -f case3-2-prometheus-deployment.yaml
(3)查看监控页面数据:
查看重写之后的标签:

5.2.3 kube-dns 的服务发现

1、查看kube-dns的状态

2、新添加一个 node 节点或修改 deployment 控制器的副本数,以让 endpoint 数量发生变化,验证能否自动发现新添加的 pod
kubectl edit deployments coredns -n kube-system

spec:
  progressDeadlineSeconds: 600
  replicas: 2        #将副本数更改为2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kube-dns

3、查看prometheus监控页面

5.2.4 node节点发现及指标

5.2.4.1 node服务发现配置
示例:查看prometheus配置文件node的服务发现配置
vim case3-1-prometheus-cfg.yaml

---
kind: ConfigMap
apiVersion: v1
metadata:
  labels:
    app: prometheus
  name: prometheus-config
  namespace: monitoring
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
      scrape_timeout: 10s
      evaluation_interval: 1m
    scrape_configs:
    - job_name: 'kubernetes-node'
      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 并用新的 service name 作为 label、将发现的值依然新的 label 的值
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)

重新加载配置文件
kubectl apply -f case3-1-prometheus-cfg.yaml
重新部署prometheus
kubectl delete -f case3-2-prometheus-deployment.yaml && kubectl apply -f case3-2-prometheus-deployment.yaml
查看node主机172.31.7.101的标签:

查看prometheus监控页面标签:
以下为重写之前(Before relabeling)匹配到的标签:

以下为重写之后的标签:

可以看到,重写之后的标签只保留了正则表达式__meta_kubernetes_nodelabel\(.+)中(.+)所匹配到的内容,并将该内容作为新的label,这些标签正是node上的label,根据这些label进行条件过滤
5.2.4.2 node节点指标数据
curl http://172.31.7.111:9100/metrics
字段说明:

#HELP:解释当前指标的含义,上面表示在每种模式下 node 节点的 cpu 花费的时间,以 s 为单位
#TYPE:说明当前指标的数据类型

示例:

5.2.4.3 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 运行时进程内部进程指标

5.2.5 cadvisor发现

5.2.5.1 prometheus job配置
cadvisor的服务发现配置有两种方式:
1、通过k8s的api接口获取cadvisor的数据
示例:
vim case3-1-prometheus-cfg.yaml

    - job_name: 'kubernetes-node-cadvisor'
      kubernetes_sd_configs:
      - role:  node
      scheme: https    #协议
      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:
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
      - target_label: __address__
        replacement: kubernetes.default.svc:443    #指定的替换后的标签(target_label)的值为 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   #指定值

重新加载配置文件
kubectl apply -f case3-1-prometheus-cfg.yaml
重新部署prometheus
kubectl delete -f case3-2-prometheus-deployment.yaml && kubectl apply -f case3-2-prometheus-deployment.yaml
查看监控页面数据:

注意:
tls_config 配置的证书地址是每个 Pod 连接 apiserver 所使用的地址,无论证书是否用得上,在 Pod 启动的时候 kubelet 都会给每一个 pod 自动注入 ca 的公钥,即所有的 pod 启动的时候都会有一个 ca 公钥被注入进去用于在访问 apiserver 的时候被调用。
验证:
找到一个容器进入查看ca证书,并用md5sum进行校验
kubectl get pod -n monitoring
kubectl exec -it prometheus-server-6bc679b999-52tkt -n monitoringls /var/run/secrets/kubernetes.io/serviceaccount/

容器内ca证书校验值为1a234520294780a972ab9b02658fe11b
对宿主机上的ca证书进行校验,校验值为1a234520294780a972ab9b02658fe11b

因此证书是一样的

2、通过cadvisor的服务端口8080获取数据
cadvisor的服务发现配置可以和node-exporter使用同样的配置,只需要把10250端口替换为8080端口即可(8080端口是cadvisor的数据抓取端口)
示例:
vim case3-1-prometheus-cfg.yaml #只需将10250端口更改为8080即可
在case3-1-prometheus-cfg.yaml文件中添加以下配置

    - job_name: 'kubernetes-node-cadvisor-n66'
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'        #通过正则匹配后缀为:10250 的实例,10250 是 kubelet 端口
        replacement: '${1}:8080'   #重写为 IP:8080,即将端口替换为 prometheus node-exporter 的端口
        target_label: __address__    #将[__address__]替换为__address__
        action: replace     #将[__address__] 的值依然赋值给__address__

重新加载配置文件
kubectl apply -f case3-1-prometheus-cfg.yaml
重新部署prometheus
kubectl delete -f case3-2-prometheus-deployment.yaml && kubectl apply -f case3-2-prometheus-deployment.yaml
查看监控页面数据:

5.2.5.2 pod监控指标
常用监控指标

(1)CPU
(2)内存
(3)磁盘
(4)网卡

PromQL表达式:

sum(rate(container_cpu_usage_seconds_total{image!=""}[1m])) without (instance)
sum(rate(container_memory_usage_bytes{image!=""}[1m])) without (instance)
sum(rate(container_fs_io_current{image!=""}[1m])) without (device)
sum(rate(container_fs_writes_bytes_total{image!=""}[1m])) without (device)
sum(rate(container_fs_reads_bytes_total{image!=""}[1m])) without (device)
sum(rate(container_network_receive_bytes_total{image!=""}[1m])) without (interface)

5.2.6 prometheus在k8s内部实现pod发现

在内部直接发现pod并执行监控数据采集
5.2.6.1 pod发现配置
示例:
vim case3-1-prometheus-cfg.yaml

    - job_name: 'kubernetes-pods'
      kubernetes_sd_configs:
      - role: pod
        namespaces:  #可选指定namepace,如果不指定就是发现所有的namespace中的pod,需要注意的是,指定的namespace下的pod具备可抓取数据的uri,否则将无法获取监控数据
          names:
          - linux
          - python
      relabel_configs:
      - 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

重新加载配置文件
kubectl apply -f case3-1-prometheus-cfg.yaml
重新部署prometheus
kubectl delete -f case3-2-prometheus-deployment.yaml && kubectl apply -f case3-2-prometheus-deployment.yaml
查看监控页面数据:
这里已经发现了pod,但是由于在prometheus发现配置中没有做端口替换,这些pod不具备抓取数据的uri,因此处于down的状态,但已经发现新的pod

5.2.7 prometheus部署在k8s集群外并实现服务发现

在k8s集群外部的prometheus如何采集k8s集群内资源数据
1、可以通过api-server向etcd获取k8s集群的资源数据
2、要访问k8s集群,则需要通过集群认证才可以访问
架构图:

5.2.7.1 环境准备
环境说明:
我们使用2.3章节通过二进制部署的prometheus(在节点172.31.7.201上)作为ks8集群以外的prometheus
1、为了便于演示,先清空之前的监控数据
(1)停止prometheus服务
systemctl stop Prometheus
(2)删除prometheus数据目录,将之前演示时做的静态配置注释掉,只保留默认配置
rm -rf /apps/Prometheus/data
vim prometheus.yml #将配置文件中的以下内容注释掉

#  - job_name: "prometheus-node"
#    static_configs:
#      - targets: ["172.31.7.192:9100","172.31.7.193:9100"]
#  - job_name: "prometheus-container"
#    static_configs:
#      - targets: ["172.31.7.101:8080","172.31.7.102:8080","172.31.7.103:8080","172.31.7.111:8080","172.31.7.112:8080","172.31.7.113:8080"]
#  - job_name: "prometheus-node-exporter"
#    static_configs:
#      - targets: ["172.31.7.101:9100","172.31.7.102:9100","172.31.7.103:9100","172.31.7.111:9100","172.31.7.112:9100","172.31.7.113:9100"]

(3)启动服务,访问prometheus监控进行验证
systemctl start Prometheus
浏览器访问172.31.7.201:9090

5.2.7.2 获取账号和token
由于外部服务访问k8s集群需要进行账号授权,这里我们使用之前演示时创建的monitor账号即可
1、在k8s集群内查询可用账号(这里我们使用方法一)
方法一:使用原有账号
kubectl get serviceaccounts -n monitoring

方法二:直接创建一个新的账号:
vim case4-prom-rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups:
  - ""
  resources:
  - nodes
  - services
  - endpoints
  - pods
  - nodes/proxy
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - "extensions"
  resources:
    - ingresses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  - nodes/metrics
  verbs:
  - get
- nonResourceURLs:
  - /metrics
  verbs:
  - get
---
#apiVersion: rbac.authorization.k8s.io/v1beta1
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: monitoring

创建账号:
kubectl apply -f case4-prom-rbac.yaml
查看创建的新账号:

2、获取monitor账号的token
kubectl get serviceaccounts monitor -n monitoring -o yaml

kubectl describe secrets monitor-token-np5pg -n monitoring

5.2.7.3 在prometheus添加token
将token放到k8s集群外的prometheus主机上/apps/prometheus/k8s.token文件中(文件名称可自定义)
vim /apps/prometheus/k8s.token

eyJhbGciOiJSUzI1NiIsImtpZCI6Ii05ZmctQVVKcEdaLXpuN2pCUHg4WXloNEJYbVNPR1JpVEVhQTNmTUw1SkkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtb25pdG9yaW5nIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Im1vbml0b3ItdG9rZW4tbnA1cGciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoibW9uaXRvciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImQ2MjI3NjFiLTY0NGUtNGY3My1hNGViLWNmMjZlYTczNzY1YSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDptb25pdG9yaW5nOm1vbml0b3IifQ.dP5icaFyU1Ks4ImBkrCaozlZAOZYI0BPAmQfwUE3DBhZHWR_KGlZRYeW4oFuBeqRmYHoB9KVS6eSn4SDEm0-vAjXeWF8ljZQfmmj2YIrrBeFRMOGIo8neSsB8vY2yxEA15Kk7LeaZ0j8IqlU9mlXDrX7F0TUBvncHm-cksUao5-yte51S59zeQrbOF5Y6cFxwgtWQXHY4h71NqoQTk_LHrJKfAmMtpI1pDzlgV3bHxmhTgFR1Jd1WbLB0rC-ciglMBHn-BWWkuMDDayDcUZp0TUP5RCY0AjvyWwT6i8Z-PMiMz7JZJMj2EGk5ScsHrdjNKkHhaWE_bKMIgWMv4Ugzg


5.2.7.4 添加job配置
在172.31.7.201上
cd /apps/prometheus
vim prometheus.yaml #通过以下百度网盘链接获取yaml文件

链接:https://pan.baidu.com/s/1iMNam-iNc5JDQnsvPg1JBQ 
提取码:ctl2 

重启prometheus服务
systemctl restart Prometheus
5.2.7.5 验证
浏览器访问172.31.7.201:9090
由于"指定namespace 的pod"和"指定Pod发现条件"这两个job配置中的pod不能提供抓取数据的uri,因此处于down的状态,除此之外的其他几个配置项均可以正常发现

5.3 静态发现static_configs

后续都是以在节点172.31.7.201上二进制部署的prometheus环境为例进行

5.3.1 prometheus配置文件

vim prometheus.yml #这里只贴出数据抓取配置

  - job_name: "prometheus-node-exporter"
    static_configs:
      - targets: ["172.31.7.101:9100","172.31.7.102:9100","172.31.7.103:9100","172.31.7.111:9100","172.31.7.112:9100","172.31.7.113:9100"]

重启prometheus服务
systemctl restart prometheus
然后浏览器访问prometheus:172.31.7.201:9090

5.4 consul实现服务发现:consul_sd_configs

consul官网:https://www.consul.io/
Consul 是分布式 k/v 数据存储集群,目前常用于服务的服务注册和发现。

服务发现流程:

1、k8s集群中的pod和node把地址注册到consul集群中
2、在prometheus配置文件中配置consul的地址
3、prometheus启动后加载配置文件,从consul获取k8s集群的pod和node信息
4、prometheus根据获取到的信息进行监控

5.4.1 环境准备

1、环境准备:

使用以下三台机器部署consul集群
172.31.7.191
172.31.7.192
172.31.7.193
这三台机器之前用作prometheus-node作为测试机器,这里不再需要,用来部署consul集群

2、在这三台机器上安装node-exporter,模拟k8s集群中的node
通过node-exporter提供获取指标数据的端口,端口为9100
分别在172.31.7.191、172.31.7.192、172.31.7.193上安装node-exporter
执行以下脚本进行安装:
mkdir -p /root/scripts/
vim /root/scripts/node_exporter_install.sh

#!/bin/bash

PKG="node_exporter-1.3.1.linux-amd64.tar.gz"
S_DIR="node_exporter-1.3.1.linux-amd64"
PKG_PATH="/apps"
VER="v1.3.1"

#创建目录
mkdir  /apps  && cd /apps

#判断安装包是否存在,不存在就下载
ls  $PKG_PATH/$PKG
if [ $? -eq 0 ];then
        echo "file exist,not need download"
else
       wget https://github.com/prometheus/node_exporter/releases/download/$VER/$PKG
fi

#解压并做软链接
tar -xvf $PKG_PATH/$PKG -C $PKG_PATH
ln -sv $PKG_PATH/$S_DIR $PKG_PATH/node_exporter

#创建service文件
cat > /etc/systemd/system/node-exporter.service  << EOF
[Unit]
Description=Prometheus Node Exporter
After=network.target

[Service]
ExecStart=/apps/node_exporter/node_exporter

[Install]
WantedBy=multi-user.target
EOF

#启动服务并设置开机自启动
systemctl daemon-reload  && systemctl restart node-exporter.service  && systemctl enable  node-exporter.service

echo "node_exporter install success!"

3、安装完成后进行验证:
查看9100端口是否启用

5.4.2 部署consul集群

1、下载consul安装包
访问以下链接下载安装包
https://releases.hashicorp.com/consul/
或者通过命令直接下载
wget https://releases.hashicorp.com/consul/1.12.2/consul_1.12.2_linux_amd64.zip
2、三台主机分别安装consul
unzip consul_1.11.1_linux_amd64.zip
cp consul /usr/local/bin/
scp consul 172.31.7.192:/usr/local/bin/
scp consul 172.31.7.193:/usr/local/bin/
3、验证:
执行以下命令验证consul命令是否可以正常执行
consul --help

4、创建consul数据目录
在三台主机上分别执行:
mkdir -p /data/consul
5、启动服务(可以通过手动编写service文件启动服务,这里为了方便通过nohup且在命令后加上&符号,使进程后台运行)

(1)在node1节点172.31.7.191上执行:
nohup consul agent -server -bootstrap -bind=172.31.7.191 -client=172.31.7.191 -data-dir=/data/consul -ui -node=172.31.7.191 &``
(2)在node2节点172.31.7.192上执行:
nohup consul agent -bind=172.31.7.192 -client=172.31.7.192 -data-dir=/data/consul -node=172.31.7.192 -join=172.31.7.191 &
(3)在node3节点172.31.7.193上执行:
nohup consul agent -bind=172.31.7.193 -client=172.31.7.193 -data-dir=/data/consul -node=172.31.7.193 -join=172.31.7.191 &
注意:第一个节点第一次启动需要进行初始化,因此要加上-bootstrap参数。第二个节点以及第三个节点可直接加入第一个节点,因此无需再进行初始化,所以启动时不需要加-bootstrap参数,且-join参数指向第一个节点即可

命令参数说明:
consul agent -server   #使用server模式运行consul服务
-bootstrap    #首次部署使用初始化模式,需要在第一个节点上执行,另外两个节点无需执行
-bind    #设置集群通信的监听地址
-client   #设置客户端访问的监听地址
-data-dir   #指定数据保存路径
-ui    #启动内置静态web界面,可选参数,可在一个节点启用,也可以三个节点都启用
-node  #此节点的名称,可自定义,但在集群中必须唯一
-datacenter=dc1   #集群名称,默认是dc1
-join    #加入到已有consul环境

5.4.3 验证

1、查看8500端口是否被监听:

2、浏览器访问 172.31.7.191:8500
查看node是否为3个

5.4.4 测试写入数据

通过 curl命令向consul 的 API 写入数据(只要可以访问consul,该命令在哪执行都可以)

(1)将节点node1写入注册中心:
curl -X PUT -d '{"id": "node-exporter191","name": "node-exporter191","address":"172.31.7.191","port":9100,"tags": ["node-exporter"],"checks": [{"http":"http://172.31.7.191:9100/","interval": "5s"}]}' http://172.31.7.191:8500/v1/agent/service/register
(2)将节点node2写入注册中心:
curl -X PUT -d '{"id": "node-exporter192","name": "node-exporter192","address":"172.31.7.192","port":9100,"tags": ["node-exporter"],"checks": [{"http":"http://172.31.7.192:9100/","interval": "5s"}]}' http://172.31.7.191:8500/v1/agent/service/register

参数说明:
"id": "node-exporter191"       #向注册中心写入id为node-exporter191
"name": "node-exporter191"    #向注册中心写入name为node-exporter191
"address":"172.31.7.191"       #向注册中心写入地址为172.31.7.191
"port":9100                #向注册中心写入端口为9100
"tags": ["node-exporter"]      #向注册中心写入tag为node-exporter
"checks": [{"http":"http://172.31.2.181:9100/","interval": "5s"}]      #通过url http://172.31.2.181:9100/对节点进行服务检查,每隔5s检查一次。如果node-exporter挂掉,最多5秒,注册中心consul就会把该节点从注册中心踢出,消费者就不会再调用该节点上的服务
http://172.31.7.191:8500/v1/agent/service/register     #consul的api接口

验证:
在web页面查看是否注册成功:

查看注册信息:

5.4.5 修改prometheus配置文件,添加job

1、修改二进制安装的prometheus配置
在节点172.31.7.201上
vim /apps/prometheus/prometheus.yml #在配置文件中添加以下配置

  - job_name: consul
    honor_labels: true          #保留抓取的标签
    metrics_path: /metrics
    scheme: http
    consul_sd_configs:        #基于consul的服务发现配置
      - server: 172.31.7.191:8500
        services: []  #发现的目标服务名称,空为所有服务,可以写servicea,servcieb,servicec
      - server: 172.31.7.192:8500
        services: []
      - server: 172.31.7.193:8500
        services: []
    relabel_configs:     #标签替换
    - source_labels: ['__meta_consul_tags']    #源标签
      target_label: 'product'         #将源标签替换为product
    - source_labels: ['__meta_consul_dc']
      target_label: 'idc'
    - source_labels: ['__meta_consul_service']   #对consul本身不监控,只监控注册到consul的服务
      regex: "consul"
      action: drop    #丢弃匹配到的服务,consul本身的服务名称为consul,即对consul本身的服务不进行监控

honor_labels说明:

    honor_labels 控制Prometheus如何处理已经存在于已抓取数据中的标签与Prometheus将附加服务器端的标签之间的冲突("job"和"instance"标签,手动配置的目标标签以及服务发现实现生成的标签)。
    如果honor_labels设置为"true",则通过保留已抓取数据的标签值并忽略冲突的服务器端标签来解决标签冲突。
    如果honor_labels设置为"false",则通过将已抓取数据中的冲突标签重命名为"exported_<original-label>"(例如"exported_instance","exported_job")然后附加服务器端标签来解决标签冲突

2、重启prometheus服务
systemctl restart Prometheus
3、验证
查看Prometheus监控页面,已经获取到两台注册到consul的主机

查看label标签,可以看到修改前和修改之后的标签正好可以匹配上

如果prometheus在k8s集群内,yaml文件配置如下:(注意缩进)

- job_name: 'nginx-monitor-serverA'
static_configs:
- targets: ['172.30.7.201:9913']
- job_name: consul
honor_labels: true
metrics_path: /metrics
scheme: http
consul_sd_configs:
- server: 172.31.2.181:8500
services: []
- server: 172.31.2.182:8500
services: []
- server: 172.31.2.183:8500
services: []
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

5.4.6 在consul新增或删除节点,查看监控效果

1、在consul手动注册node3节点
(1)在consul集群node1节点172.31.7.191上执行命令:

curl -X PUT -d '{"id": "node-exporter193","name": "node-exporter193","address":"172.31.7.193","port":9100,"tags": ["node-exporter"],"checks": [{"http":"http://172.31.7.193:9100/","interval": "5s"}]}' http://172.31.7.191:8500/v1/agent/service/register

(2)查看prometheus监控页面 172.31.7.201:9090
可以对新增节点进行监控

2、在consul手动删除节点
(1)在consul集群node1节点172.31.7.191上执行命令:
curl --request PUT http://172.31.7.191:8500/v1/agent/service/deregister/node-exporter193
(2)查看prometheus监控页面 172.31.7.201:9090
可以看到node3节点已经从监控中踢出(注册中心不再向消费者提供node3节点,因此prometheus不再对node3进行监控)

5.5 基于文件的服务发现:file_sd_configs

  创建一个json文件,prometheus监控该文件,如果文件中的主机地址发生变化,prometheus会做出好相应地调整。
  这种方式和修改prometheus配置文件prometheus.yml的区别是:修改prometheus配置文件需要重启服务才能生效,而file_sd_configs修改之后直接生效,无需重启prometheus服务。
架构图:

5.5.1 编辑json文件

1、在prometheus主机172.31.7.201上编辑json文件
(1)创建存放文件目录
mkdir -p /apps/prometheus/file_sd
cd /apps/prometheus/file_sd
vim sd_myserver.json

[
  {
    "targets": ["172.31.7.191:9100"]
  }
]

5.5.2 prometheus配置job

在prometheus主机172.31.7.201上
1、编辑prometheus配置文件
vim /app/prometheus/prometheus.yml #这里只贴出添加的内容

  - job_name: 'file_sd_my_server'
    file_sd_configs:       #基于文件实现服务发现
      - files:
        - /apps/prometheus/file_sd/sd_my_server.json     #配置文件路径,列表形式,可以配置多个
        refresh_interval: 10s       #刷新时间为10s

2、重启prometheus服务,使配置生效
systemctl restart prometheus.service
3、验证
浏览器访问:http://172.31.7.201:9090/

5.5.3 在文件中手动添加主机,查看监控效果

1、修改文件
vim sd_myserver.json

[
  {
    "targets": ["172.31.7.191:9100","172.31.7.192:9100","172.31.7.193:9100"]
  }
]

2、查看监控
会自动添加对192和193主机的监控

5.6 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 记录的端口字段

5.6.1 示例

由于没有DNS服务器,在prometheus主机通过配置/etc/hosts文件指定域名解析的ip地址,用来模拟DNS。
1、修改prometheus主机/etc/hosts文件
vim /etc/hosts
172.31.7.191 node1.example.com
172.31.7.192 node2.example.com
2、修改prometheus配置
vim prometheus.yml #这里只贴出dns 数据抓取配置

  - job_name: 'dns-server-name-monitor'
    metrics_path: "/metrics"
    dns_sd_configs:
    - names: ["node1.example.com","node2.example.com"]
      type: A           #指定类型为A记录
      port: 9100

注意:默认30s刷新一次,可通过参数refresh_interval来配置刷新时间
3、重启prometheus服务
systemctl restart prometheus.service
验证:
查看监控页面

5.6.2 手动修改A记录,查看监控效果

1、在/etc/hosts文件中将解析关系更改,查看监控是否会自动更换
vim /etc/hosts
172.31.7.191 node1.example.com
172.31.7.193 node2.example.com
2、查看监控页面,地址是否发生变化

标签: prometheus 监控
最后更新:2024年1月9日

袁党生

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2023 linux学习. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

豫ICP备18039507号-1