17-prometheus自动发现机制

熊 0 阅读 监控平台

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服务

1. relabeling简介

官方链接 : Configuration | Prometheus

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如何进行配置 :

image-20240628140339226

1.1 relabel介绍

1.1.1 基础功能-重新标记

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

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

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

prometheus-service-discovery-1

常用方式 : 数据采集之前进行标签修改(relabel_configs)

  1. prometheus启动后 , 加载配置文件

  2. 根据配置文件中的服务发现配置 , 对标签进行修改(relabel_configs)

  3. 根据修改后的标签进行数据抓取

  4. 抓取后将数据写入到TSDB

这种方式就不需要metrics_relabel_configs配置。

prometheus-service-discovery-2

示例:

- 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

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

1.1.3 action详解

  • replace : 替换标签值 , 根据 regex 正则匹配到源标签的值 , 使用 replacement 来引用表达式匹配的分组

  • keep : 只采集满足 regex 正则条件的实例 , 将source_labels中不匹配regex 正则内容的Targ实例丢弃

  • drop : 和keep相反 , 只采集不满足 regex 正则条件的实例 , 将source_labels 中匹配到 regex 正则内容的 Target 实例丢弃

示例 : prometheus的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主机k8s-master02.cbear.top的标签 :

image-20240628152204722

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

image-20240628152333900

以下为重写之后的标签:

image-20240628153129050

可以看到 , 重写之后的标签只保留了正则表达式__meta_kubernetes_node*label\*(.+)中(.+)所匹配到的内容 , 并将该内容作为新的label , 这些标签正是node上的label , 根据这些label进行条件过滤

1.1.4 测试label功能

  1. 将prometheus-cfg.yaml文件中配置删除 , 然后查看prometheus监控页面 , 查看获取到的数据情况

        - 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. 重新加载对应配置文件

    root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-server# kubectl delete -f ./
    configmap "prometheus-config" deleted
    deployment.apps "prometheus-server" deleted
    service "prometheus" deleted
    root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-server# kubectl apply -f ./
    configmap/prometheus-config created
    deployment.apps/prometheus-server created
    service/prometheus created
    ​
  3. 修改前监控页面数据如下:

    image-20240628161311279
  4. 修改后监控页面数据如下:

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

    image-20240628160905532

因此 , 要对监控的资源进行条件限制

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进行校验

root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-server# kubectl exec -it prometheus-server-84b448dc5d-cp5td -n monitoring -- sh
/prometheus $ 
/prometheus $ ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt     namespace  token
/prometheus $ md5sum  /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 
356e5b8fa56db16c34406abc70d204b6  /var/run/secrets/kubernetes.io/serviceaccount/ca.crt

容器内ca证书校验值为:356e5b8fa56db16c34406abc70d204b6 对宿主机上的ca证书进行校验 , 校验值为 : 356e5b8fa56db16c34406abc70d204b6

oot@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-server# md5sum /etc/kubernetes/ssl/ca.pem 
356e5b8fa56db16c34406abc70d204b6  /etc/kubernetes/ssl/ca.pem

因此证书是一样的

2. 动态发现:kubernetes_sd_configs

2.1 支持的发现目标类型

官网链接 :Configuration | Prometheus

发现的资源类型类型可以配置以下类型之一来发现目标:

  1. node

  2. service

  3. pod

  4. endpoints

  5. Endpointslice #对 endpoint 进行切片 , 使用较少

  6. ingress

2.2 监控 api-server 实现

apiserver 作为 Kubernetes 最核心的组件 , 它的监控也是非常有必要的 , 对于apiserver 的监控 , 我们可以直接通过 kubernetes 的 service 来获取

prometheus-configmap.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的信息 , 与匹配规则相符合

root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-server# kubectl get svc kubernetes
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.68.0.1    <none>        443/TCP   38h
root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-server# kubectl get endpoints kubernetes
NAME         ENDPOINTS                                                  AGE
kubernetes   192.168.71.29:6443,192.168.71.30:6443,192.168.71.31:6443   38h

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

查看重写之前的标签:

image-20240628163959912

重写之后的标签:

image-20240628164100601

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)

    image-20240628164540347
    image-20240628164613138

    irate 和 rate 都会用于计算某个指标在一定时间间隔内的变化速率。但是它们的计算方法有所不同 : irate取的是在指定时间范围内的最近两个数据点来算速率 , 而 rate 会取指定时间范围内所有数据点 , 算出一组速率 , 然后取平均值作为结果。

    所以官网文档说 : irate 适合快速变化的计数器(counter) , 而 rate 适合缓慢变化的计数器(counter)。

    根据以上算法我们也可以理解 , 对于快速变化的计数器 , 如果使用 rate , 因为使用了平均值 , 很容易把峰值削平。除非我们把时间间隔设置得足够小 , 就能够减弱这种效应。

    示例:rate(apiserver_request_total{code=~"^(?:2..)$"}[5m])

    image-20240628165436104
  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 )

    image-20240628170134849

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

    示例:查看prometheus的配置文件数据抓取配置 prometheus-configmap.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 delete -f ./ && kubectl apply -f ./
    2. 查看监控页面数据, 查看重写之后的标签

      image-20240628180913519

2.3 kube-dns 的服务发现

  1. 查看kube-dns的状态

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

    root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-server# kubectl edit deployment/coredns -n kube-system
    
    spec:
      progressDeadlineSeconds: 600
      replicas: 2                 #将副本数更改为2
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          k8s-app: kube-dns
      strategy:
        rollingUpdate:
          maxSurge: 25%
          maxUnavailable: 1
        type: RollingUpdate
  3. 查看prometheus监控页面

    image-20240628181906986

2.4 node节点发现及指标

2.4.1 node服务发现配置

示例 : 查看prometheus配置文件node的服务发现配置

---
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 delete -f ./ && kubectl apply -f ./
  • 查看node主机k8s-master02.cbear.top的标签 :

    image-20240628152204722

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

    image-20240628152333900

    以下为重写之后的标签:

    可以看到 , 重写之后的标签只保留了正则表达式__meta_kubernetes_node*label\*(.+)中(.+)所匹配到的内容 , 并将该内容作为新的label , 这些标签正是node上的label , 根据这些label进行条件过滤

2.4.2 node节点指标数据

curl http://192.168.71.35:9100/metrics

字段说明:

#HELP:解释当前指标的含义 , 上面表示在每种模式下 node 节点的 cpu 花费的时间 , 以 s 为单位
#TYPE:说明当前指标的数据类型
root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-server# curl http://192.168.71.35:9100/metrics
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 2.1072e-05
go_gc_duration_seconds{quantile="0.25"} 5.1857e-05
go_gc_duration_seconds{quantile="0.5"} 7.3632e-05
go_gc_duration_seconds{quantile="0.75"} 9.3352e-05
go_gc_duration_seconds{quantile="1"} 0.000244757
go_gc_duration_seconds_sum 0.872813656
go_gc_duration_seconds_count 14463
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 9
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.22.3"} 1
# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
# TYPE go_memstats_alloc_bytes gauge
go_memstats_alloc_bytes 3.194608e+06
# HELP go_memstats_alloc_bytes_total Total number of bytes allocated, even if freed.
# TYPE go_memstats_alloc_bytes_total counter
go_memstats_alloc_bytes_total 2.9198462232e+10
# HELP go_memstats_buck_hash_sys_bytes Number of bytes used by the profiling bucket hash table.
# TYPE go_memstats_buck_hash_sys_bytes gauge
go_memstats_buck_hash_sys_bytes 1.944898e+06
# HELP go_memstats_frees_total Total number of frees.
# TYPE go_memstats_frees_total counter
go_memstats_frees_total 2.92824147e+08
# HELP go_memstats_gc_sys_bytes Number of bytes used for garbage collection system metadata.
# TYPE go_memstats_gc_sys_bytes gauge
go_memstats_gc_sys_bytes 3.33004e+06
# HELP go_memstats_heap_alloc_bytes Number of heap bytes allocated and still in use.
# TYPE go_memstats_heap_alloc_bytes gauge
go_memstats_heap_alloc_bytes 3.194608e+06
....

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

2.5 cadvisor发现

2.5.1 prometheus job配置

cadvisor的服务发现配置有两种方式:

  1. 通过k8s的api接口获取cadvisor的数据

        - 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   #指定值
  2. 重新加载配置文件

  3. 查看监控页面数据

    image-20240628190830211

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

  4. 通过cadvisor的服务端口8080获取数据

    cadvisor的服务发现配置可以和node-exporter使用同样的配置 , 只需要把10250端口替换为8080端口即可(8080端口是cadvisor的数据抓取端口)

    示例:

    prometheus-configmap.yaml : 只需将10250端口更改为8081即可

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

  6. 查看监控页面数据

    image-20240628191916558

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)

2.6 prometheus在k8s内部实现pod发现

在内部直接发现pod并执行监控数据采集

2.6.1 pod发现配置

    - 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
  1. 重新加载配置文件

  2. 查看监控页面数据

    这里已经发现了pod , 但是由于在prometheus发现配置中没有做端口替换 , 这些pod不具备抓取数据的uri , 因此处于down的状态 , 但已经发现新的pod

    image-20240628192630083

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

在k8s集群外部的prometheus如何采集k8s集群内资源数据

  1. 可以通过api-server向etcd获取k8s集群的资源数据

  2. 要访问k8s集群 , 则需要通过集群认证才可以访问

2.7.1 环境准备

  1. 在k8s集群外部部署prometheus

  2. 获取账号和token

    由于外部服务访问k8s集群需要进行账号授权 , 这里我们使用之前演示时创建的monitor账号即可

    创建一个新的账号

    root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues# cat 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
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: prometheus
      namespace:  monitoring
      annotations:
        kubernetes.io/service-account.name: "prometheus"   
    type: kubernetes.io/service-account-token 

    启用账号资源

    root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues# kubectl apply -f prom-rbac.yaml 
    serviceaccount/prometheus created
    clusterrole.rbac.authorization.k8s.io/prometheus created
    clusterrolebinding.rbac.authorization.k8s.io/prometheus created

    查看创建的新的账号:

    root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues# kubectl get serviceaccounts -n monitoring 
    NAME         SECRETS   AGE
    default      0         21h
    monitor      0         17h
    prometheus   0         60s
  3. 获取新建用户的token

    root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues# kubectl get secret -n monitoring prometheus -o jsonpath={".data.token"} | base64 -d
    eyJhbGciOiJSUzI1NiIsImtpZCI6IjBTNXBmREE4MGN1aG9PQjZWSHNsOWNHalpSOXJnTGF1TUFUMFVBZXFBXzQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtb25pdG9yaW5nIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InByb21ldGhldXMiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicHJvbWV0aGV1cyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjI3MjU1MTYwLWE1NDgtNDBkMy05MDQ5LTg5Mzg2OTU5NjU0OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDptb25pdG9yaW5nOnByb21ldGhldXMifQ.ogQC7MQp_1y8IP0FiQuhxMDlmg43OjeCeF0ro27AN4On1vwKHfnr-e6D6laSk92pbo41dU7aa8uXznkVJtw3f1J2jwCApafs5GyXsoSnXDLdEQ2rE3WcT-dr85mVzpb8ivyY9NgR5wfjuGi6XE1UKNDxyjEEWBcXr03ZiUQEZULpNBpjDvAQPpe02ytvquoWhHes8lzSqLLvxSuFtLRQ54U1Rs0O8XGA6PCoD9ibCPwwtHsHY-XxO03RhJwJDNue51eQnqosp2c14YiiOZ0-XfFyqs5ok0ZL4mazn2wThRSJDFBhkEYNsCuTMnlm_fezipbqycHnXOtVlKR_LzzLHQ

2.7.2 在prometheus添加token

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

root@prometheus01:/usr/local/src/prometheus# mkdir /app/prometheus -pv
mkdir: created directory '/app'
mkdir: created directory '/app/prometheus'

root@prometheus01:/usr/local/src/prometheus# cat /app/prometheus/k8s-token
eyJhbGciOiJSUzI1NiIsImtpZCI6IjBTNXBmREE4MGN1aG9PQjZWSHNsOWNHalpSOXJnTGF1TUFUMFVBZXFBXzQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtb25pdG9yaW5nIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InByb21ldGhldXMiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicHJvbWV0aGV1cyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjI3MjU1MTYwLWE1NDgtNDBkMy05MDQ5LTg5Mzg2OTU5NjU0OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDptb25pdG9yaW5nOnByb21ldGhldXMifQ.ogQC7MQp_1y8IP0FiQuhxMDlmg43OjeCeF0ro27AN4On1vwKHfnr-e6D6laSk92pbo41dU7aa8uXznkVJtw3f1J2jwCApafs5GyXsoSnXDLdEQ2rE3WcT-dr85mVzpb8ivyY9NgR5wfjuGi6XE1UKNDxyjEEWBcXr03ZiUQEZULpNBpjDvAQPpe02ytvquoWhHes8lzSqLLvxSuFtLRQ54U1Rs0O8XGA6PCoD9ibCPwwtHsHY-XxO03RhJwJDNue51eQnqosp2c14YiiOZ0-XfFyqs5ok0ZL4mazn2wThRSJDFBhkEYNsCuTMnlm_fezipbqycHnXOtVlKR_LzzLHQ
image-20240628222117469

2.7.3 添加job配置

这里做了一个高可用:192.168.71.150:6443对应后端的master主机三个节点的api-server

# my global config
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

#API Serevr节点发现
  - job_name: 'kubernetes-apiservers-monitor' 
    kubernetes_sd_configs: 
    - role: endpoints
      api_server: https://192.168.71.150:6443     #配置k8s集群api-server地址
      tls_config: 
        insecure_skip_verify: true      #跳过证书认证
      bearer_token_file: /app/prometheus/k8s-token    #指定k8s集群monitor账号token路径
    scheme: https 
    tls_config: 
      insecure_skip_verify: true 
    bearer_token_file: /app/prometheus/k8s-token
    relabel_configs: 
    - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] 
      action: keep 
      regex: default;kubernetes;https 
    #可自定义替换发现的服务器端口、协议等
    - source_labels: [__address__]
      regex: '(.*):6443'
      replacement: '${1}:9100'
      target_label: __address__
      action: replace
    - source_labels: [__scheme__]
      regex: https
      replacement: http
      target_label: __scheme__
      action: replace

#node节点发现
  - job_name: 'kubernetes-nodes-monitor' 
    scheme: http 
    tls_config: 
      insecure_skip_verify: true 
    bearer_token_file: /app/prometheus/k8s-token 
    kubernetes_sd_configs: 
    - role: node 
      api_server: https://192.168.71.150:6443     #配置k8s集群api-server地址
      tls_config: 
        insecure_skip_verify: true      #跳过证书认证
      bearer_token_file: /app/prometheus/k8s-token    #指定k8s集群monitor账号token路径
    relabel_configs: 
      - source_labels: [__address__] 
        regex: '(.*):10250' 
        replacement: '${1}:9100' 
        target_label: __address__ 
        action: replace 
      - source_labels: [__meta_kubernetes_node_label_failure_domain_beta_kubernetes_io_region] 
        regex: '(.*)' 
        replacement: '${1}' 
        action: replace 
        target_label: LOC 
      - source_labels: [__meta_kubernetes_node_label_failure_domain_beta_kubernetes_io_region] 
        regex: '(.*)' 
        replacement: 'NODE' 
        action: replace 
        target_label: Type 
      - source_labels: [__meta_kubernetes_node_label_failure_domain_beta_kubernetes_io_region] 
        regex: '(.*)' 
        replacement: 'K8S-test' 
        action: replace 
        target_label: Env 
      - action: labelmap 
        regex: __meta_kubernetes_node_label_(.+) 

#指定namespace 的pod
  - job_name: 'kubernetes-发现指定namespace的所有pod'
    kubernetes_sd_configs:
    - role: pod
      api_server: https://192.168.71.150:6443     #配置k8s集群api-server地址
      tls_config: 
        insecure_skip_verify: true      #跳过证书认证
      bearer_token_file: /app/prometheus/k8s-token    #指定k8s集群monitor账号token路径
      namespaces:
        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

#指定Pod发现条件
  - job_name: 'kubernetes-指定发现条件的pod' 
    kubernetes_sd_configs: 
    - role: pod 
      api_server: https://192.168.71.150:6443     #配置k8s集群api-server地址
      tls_config: 
        insecure_skip_verify: true      #跳过证书认证
      bearer_token_file: /app/prometheus/k8s-token    #指定k8s集群monitor账号token路径
    relabel_configs: 
    - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] 
      action: keep 
      regex: true 
    - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] 
      action: replace 
      target_label: __metrics_path__ 
      regex: (.+) 
    - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] 
      action: replace 
      regex: ([^:]+)(?::\d+)?;(\d+) 
      replacement: $1:$2 
      target_label: __address__ 
    - 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 

2.7.4 验证

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

image-20240628225251945

3. 静态发现static_configs

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

3.1 prometheus配置文件

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

  - job_name: "prometheus-node-exporter"
    static_configs:
      - targets: ["192.168.71.29:9100","192.168.71.30:9100","192.168.71.31:9100","192.168.71.35:9100","192.168.71.36:9100","192.168.71.37:9100"]

重启prometheus服务

然后浏览器访问prometheus:192.168.71.47:9090

image-20240628230734092

4. consul实现服务发现: consul_sd_configs

consul官网:Consul by HashiCorp

Consul 是分布式 k/v 数据存储集群 , 目前常用于服务的服务注册和发现。

服务发现流程:

  1. k8s集群中的pod和node把地址注册到consul集群中

  2. 在prometheus配置文件中配置consul的地址

  3. prometheus启动后加载配置文件 , 从consul获取k8s集群的pod和node信息

  4. prometheus根据获取到的信息进行监控

4.1 环境准备

  1. 环境准备:

    使用以下三台机器部署consul集群
    192.168.71.55
    192.168.71.56
    192.168.71.57
    这三台机器之前用作prometheus-node作为测试机器 , 这里不再需要 , 用来部署consul集群
  2. 在这三台机器上安装node-exporter , 模拟k8s集群中的node

    通过node-exporter提供获取指标数据的端口 , 端口为9100

    分别在192.168.71.55、192.168.71.56、192.168.71.57上安装node-exporter

    执行以下脚本进行安装:

    #!/bin/bash
    
    PKG="node_exporter-1.8.1.linux-amd64.tar.gz"
    S_DIR="node_exporter-1.8.1.linux-amd64"
    PKG_PATH="/apps"
    VER="v1.8.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端口是否启用

    image-20240628233920955

4.2 部署consul集群

  1. 下载consul安装包

    访问以下链接下载安装包 https://releases.hashicorp.com/consul/ 或者通过命令直接下载

    wget https://releases.hashicorp.com/consul/1.19.0/consul_1.19.0_linux_amd64.zip
  2. 三台主机分别安装consul

    root@ndoe01:~# unzip consul_1.19.0_linux_amd64.zip 
    Archive:  consul_1.19.0_linux_amd64.zip
      inflating: LICENSE.txt             
      inflating: consul                  
    root@ndoe01:~# ls
    consul  consul_1.19.0_linux_amd64.zip  LICENSE.txt  node_exporter-1.8.1.linux-amd64.tar.gz  snap
    
    root@ndoe01:~# scp consul root@192.168.71.56:/usr/local/bin/
    root@192.168.71.56's password: 
    consul                                                                                                      100%  175MB 103.7MB/s   00:01    
    root@ndoe01:~# scp consul root@192.168.71.57:/usr/local/bin/
    root@192.168.71.57's password: 
    consul                                                                                                      100%  175MB 106.4MB/s   00:01   

  3. 验证:

    执行以下命令验证consul命令是否可以正常执行

    root@ndoe01:~# consul --help
    Usage: consul [--version] [--help] <command> [<args>]
    
    Available commands are:
        acl             Interact with Consul's ACLs
        agent           Runs a Consul agent
        catalog         Interact with the catalog
        config          Interact with Consul's Centralized Configurations
        connect         Interact with Consul Connect
        debug           Records a debugging archive for operators
        event           Fire a new event
    ....
  4. 创建consul数据目录

    在三台主机上分别执行:

    mkdir -p /data/consul
  5. 启动服务

    • 在node01节点192.168.71.55上执行

      注意 : 第一个节点第一次启动需要进行初始化 , 因此要加上-bootstrap参数。第二个节点以及第三个节点可直接加入第一个节点 , 因此无需再进行初始化 , 所以启动时不需要加-bootstrap参数 , 且-join参数指向第一个节点即可

      nohup consul agent -server -bootstrap -bind=192.168.71.55 -client=192.168.71.55 -data-dir=/data/consul -ui -node=192.168.71.55 &
    • 在node02节点192.168.71.56上执行

      nohup consul agent -bind=192.168.71.56 -client=192.168.71.56 -data-dir=/data/consul -node=192.168.71.56 -join=192.168.71.55 &
    • 在node03节点192.168.71.57上执行

      nohup consul agent -bind=192.168.71.57 -client=192.168.71.57 -data-dir=/data/consul -node=192.168.71.57 -join=192.168.71.55 &
    • 参数说明

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

    image-20240629013855874

4.3 测试写入数据

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

  1. 将节点node01写入注册中心

    curl -X PUT -d '{"id": "node-exporter55","name": "node-exporter55","address":"192.168.71.55","port":9100,"tags": ["node-exporter"],"checks": [{"http":"http://192.168.71.55:9100/","interval": "5s"}]}' http://192.168.71.55:8500/v1/agent/service/register
  2. 将节点node02写入注册中心:

    curl -X PUT -d '{"id": "node-exporter56","name": "node-exporter56","address":"192.168.71.56","port":9100,"tags": ["node-exporter"],"checks": [{"http":"http://192.168.71.56:9100/","interval": "5s"}]}' http://192.168.71.56:8500/v1/agent/service/register
  3. 将节点node03写入注册中心

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

    参数说明:

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

    image-20240629131232402
  5. 查看注册信息:

    image-20240629131410356

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

  1. 修改二进制安装的prometheus配置

    在节点192.168.71.47上

      - job_name: consul
        honor_labels: true          #保留抓取的标签
        metrics_path: /metrics
        scheme: http
        consul_sd_configs:        #基于consul的服务发现配置
          - server: 192.168.71.55:8500
            services: []  #发现的目标服务名称 , 空为所有服务 , 可以写servicea,servcieb,servicec
          - server: 192.168.71.56:8500
            services: []
          - server: 192.168.71.57: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本身的服务不进行监控
  2. honor_labels说明:

    honor_labels控制Prometheus如何处理已经存在于已抓取数据中的标签与Prometheus将附加服务器端的标签之间的冲突("job"和"instance"标签 , 手动配置的目标标签以及服务发现实现生成的标签)。

    如果honor_labels设置为"true" , 则通过保留已抓取数据的标签值并忽略冲突的服务器端标签来解决标签冲突。

    如果honor_labels设置为"false" , 则通过将已抓取数据中的冲突标签重命名为"exported_<original-label>"(例如"exported_instance" , "exported_job")然后附加服务器端标签来解决标签冲突

  3. 重新加载配置

    root@prometheus01:/usr/local/src/prometheus# curl -X POST http://192.168.71.47:9090/-/reload
  4. 验证 查看Prometheus监控页面 , 已经获取到三台注册到consul的主机

    image-20240629133730806

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

    image-20240629133829013
  5. 如果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

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

  1. 在consul手动注册node4节点

    在consul集群node1节点192.168.71.55上执行命令:

    curl -X PUT -d '{"id": "node-exporter58","name": "node-exporter193","address":"192.168.71.58","port":9100,"tags": ["node-exporter"],"checks": [{"http":"http://192.168.71.58:9100/","interval": "5s"}]}' http://192.168.71.58:8500/v1/agent/service/register
  2. 在consul手动删除节点

    • 查看节点中的服务

      root@ndoe01:~# curl     http://192.168.71.55:8500/v1/agent/services

    • 在consul集群node01节点192.168.71.55上执行命令:

      root@ndoe01:~# curl --request PUT http://192.168.71.55:8500/v1/agent/service/deregister/node-exporter55
    • 查看prometheus监控页面192.168.71.47:9100 可以看到node01节点已经从监控中踢出(注册中心不再向消费者提供node01节点 , 因此prometheus不再对node01进行监控)

      image-20240629143627255

5. 基于文件的服务发现: file_sd_configs

创建一个json文件 , prometheus监控该文件 , 如果文件中的主机地址发生变化 , prometheus会做出好相应地调整。

这种方式和修改prometheus配置文件prometheus.yml的区别是 : 修改prometheus配置文件需要重启服务才能生效 , 而file_sd_configs修改之后直接生效 , 无需重启prometheus服务。

5.1 编辑json文件

在prometheus主机192.168.71.47上编辑json文件 创建存放文件目录

root@prometheus01:/usr/local/src/prometheus# mkdir -p /apps/prometheus/file_sd

root@prometheus01:/usr/local/src/prometheus# cd /apps/prometheus/file_sd
root@prometheus01:/apps/prometheus/file_sd# vim sd_my_server.json
root@prometheus01:/apps/prometheus/file_sd# cat sd_my_server.json 
[
  {
    "targets": ["192.168.71.55:9100"]
  }
]

5.2 prometheus配置job

在prometheus主机192.168.71.47上

  1. 编辑prometheus配置文件

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

    root@prometheus01:/usr/local/src/prometheus# curl -X POST http://192.168.71.47:9090/-/reload

  3. 验证 浏览器访问:http://192.168.71.47:9090

    image-20240629152024277

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

  1. 修改文件

    [
      {
        "targets": ["192.168.71.55:9100","192.168.71.56:9100","192.168.71.57:9100"]
      }
    ]
  2. 查看监控 会自动添加对56和57主机的监控

    image-20240629152509421

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

6.1 示例

由于没有DNS服务器 , 在prometheus主机通过配置/etc/hosts文件指定域名解析的ip地址 , 用来模拟DNS。

  1. 修改prometheus主机/etc/hosts文件

    vim /etc/hosts
    192.168.71.55 node01.example.com
    192.168.71.56 node02.example.com
  2. 修改prometheus配置

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

    注意: 默认30s刷新一次 , 可通过参数refresh_interval来配置刷新时间

  3. 重启prometheus服务

    root@prometheus01:/usr/local/src/prometheus# curl -X POST http://192.168.71.47:9090/-/reload
  4. 验证: 查看监控页面

    image-20240629154018481

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

  1. 在/etc/hosts文件中将解析关系更改 , 查看监控是否会自动更换

    vim /etc/hosts
    192.168.71.55 node01.example.com
    192.168.71.57 node02.example.com
  2. 查看监控页面 , 地址是否发生变化

    image-20240629154139810


参考链接

五、prometheus的服务发现机制 - 袁党生博客 (yuandangsheng.top)