Skip to content

第十九章-Prometheus告警

本章所讲内容:

19.1 深度解读 Prometheus

19.2 安装采集节点资源指标组件 node-exporter

19.3 在 k8s 集群中安装 Prometheus server 服务

19.4 安装和配置可视化 UI 界面 Grafana

19.5 kube-state-metrics 组件解读

19.1 深度解读 Prometheus

19.1.1 Prometheus 基本介绍

​ Prometheus 配置文件参考地址:

https://prometheus.io/docs/prometheus/latest/configuration/configuration/

​ Prometheus 监控组件对应的exporter 部署地址:

https://prometheus.io/docs/instrumenting/exporters/

​ Prometheus 基于 k8s 服务发现参考:

https://github.com/prometheus/prometheus/blob/release-2.31/documentation/examples/prometheus-kubernetes.yml

​ Prometheus 是一个开源的系统监控和警报工具,用于收集、存储和查询时间序列数据。它专注于监控应用程序和基础设施的性能和状态,并提供丰富的查询语言和灵活的告警机制。

以下是对 Prometheus 的基本介绍:

  1. 数据模型:Prometheus 使用时间序列数据模型来存储监控数据。时间序列由一个唯一的指标名称和一组键值对标签组成,代表了某个指标在特定时间点的数值。这种数据模型非常适合度量指标的变化和趋势。

  2. 数据采集:Prometheus 支持多种数据采集方式。它可以直接采集应用程序的指标数据,也可以通过各种监控插件和集成来获取系统和网络层面的指标数据。采集的数据通过** HTTP 或其他协议发送给 Prometheus 服务器进行存储和处理。

  3. 存储和查询:Prometheus 使用本地存储方式,将采集的时间序列数据保存在本地磁盘上。它提供了灵活而高效的查询语言(PromQL),可以对存储的数据进行实时查询和聚合操作,以便生成有关监控指标的图表、报表和警报。

  4. 告警和警报规则:Prometheus 具有强大的告警功能,可以根据指标的阈值、表达式和持续时间等条件设置警报规则。当条件满足时,它可以触发警报并发送通知,如发送电子邮件、短信或通过集成的通知服务进行报警。

  5. 可视化和集成:虽然 Prometheus 本身提供了基本的查询和图表功能,但它也可以与其他工具和服务集成,如 Grafana,用于更丰富的数据可视化和仪表板展示。

19.1.2 prometheus 特点

  1. 多维度数据模型:Prometheus 采用了多维度的时间序列数据模型,每个时间序列都由指标名称和一组标签键值对组成。这种数据模型使得用户可以灵活地对监控数据进行多维度的查询和聚合,以获取更准确和细粒度的监控指标。

  2. 高效的数据采集:Prometheus 支持多种灵活的数据采集方式。它可以通过客户端库(例如Prometheus 客户端库)直接采集应用程序的指标数据,也可以通过各种监控插件和集成方式获取系统、网络和第三方服务的指标数据。数据采集的过程高效而可靠,可以适应各种规模和复杂度的监控场景。

  3. 强大的查询语言:Prometheus 提供了强大而灵活的查询语言(PromQL),用于对存储的监控数据进行实时查询和聚合操作。PromQL 支持范围查询、聚合函数、算术运算和向量操作等,使得用户能够方便地分析和提取所需的监控指标。

  4. 动态监控和自动发现:Prometheus 支持动态监控和自动发现机制。它可以自动探测和监控新加入集群的目标,例如新部署的应用实例或新增的节点。通过定义合适的自动发现规则, Prometheus 能够及时识别和监控新的目标,实现动态的监控配置和管理。

  5. 灵活的告警机制:Prometheus 具备强大的告警功能,用户可以定义灵活的警报规则,并根据阈值、表达式和持续时间等条件触发警报。它能够及时发送通知,如电子邮件、短信或调用API,以便运维人员能够快速响应和解决潜在的问题。

  6. 生态系统和集成:Prometheus 拥有丰富的生态系统和广泛的集成能力。它可以与其他工具和服务集成,如 Grafana 用于可视化、Alertmanager 用于告警通知、Exporter 用于采集非Prometheus 格式的指标数据等。这种集成能力使得用户能够构建全面和强大的监控解决方案。

19.1.3 prometheus 生态系统包含的组件

architecture

  1. Prometheus Server:Prometheus 服务器是核心组件,用于收集、存储和处理时间序列数据。它负责从各个目标主机上抓取监控指标数据,并将其存储在本地磁盘中供后续查询和分析使用。

  2. Exporters:Exporter 是用于从各种系统、服务和应用程序中抓取指标数据的组件。Prometheus 提供了一些官方的 Exporter,同时也支持社区开发的 Exporter。Exporter 将特定系统的指标数据暴露出来,使其可以被 Prometheus Server 收集。

  3. Client Library:Prometheus 提供了一组客户端库,用于在应用程序中嵌入监控指标的采集和上报。通过将客户端库集成到应用程序中,应用程序可以自动将指标数据暴露给 Prometheus Server。

  4. Alertmanager:Alertmanager 是负责处理和发送警报通知的组件。当 Prometheus Server 检测到警报条件时,它将警报发送给 Alertmanager,然后 Alertmanager 负责对警报进行处理、去重、分组和路由,并将警报通知发送给配置的接收方(如电子邮件、Slack、PagerDuty 等)。

  5. Grafana:Grafana 是一个流行的可视化仪表板工具,用于创建漂亮的监控仪表板。通过与Prometheus 集成,Grafana 可以从 Prometheus Server 中查询和展示监控指标数据,并以图表和图形的形式展示给用户。

  6. Pushgateway:Pushgateway 是一个中间组件,允许短期作业(如批处理任务)将其指标数据推送到 Prometheus Server。短期作业通常无法被长期监控,因此 Pushgateway 提供了一个临时存储的机制,以便 Prometheus Server 可以主动从Pushgateway 拉取指标数据。

19.2 安装采集节点资源指标组件 node-exporter

​ node-exporter 官方网站:

https://prometheus.io/docs/guides/node-exporter/

​ node-exporter 的 github 地址:

https://github.com/prometheus/node_exporter/

node-exporter 基本介绍

​ Node Exporter 是 Prometheus 的一个官方 Exporter,用于收集和暴露有关操作系统和硬件资源的指标数据。它在目标主机上运行,并提供了各种系统级别的指标,例如 CPU 利用率、内存使用情况、磁盘空间、网络流量等。

安装 node-exporter 组件,在 k8s 集群的控制节点操作

$ kubectl create ns monitor-sa

node-exporter.tar.gz 镜像压缩包上传到 k8s 的各个节点,手动解压:

# containerd容器运行时
$ ctr -n=k8s.io images import node-exporter.tar.gz 

#docker容器运行时
$ docker load -i node-exporter.tar.gz 
$ cat > node-export.yaml << EOF
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitor-sa
  labels:
    name: node-exporter
spec:
  selector:
    matchLabels:
     name: node-exporter
  template:
    metadata:
      labels:
        name: node-exporter
    spec:
      hostPID: true
      hostIPC: true
      hostNetwork: true
      containers:
      - name: node-exporter
#        image: prom/node-exporter:v0.16.0
        image: 192.168.2.206/library/node-exporter:v0.18.1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9100
        resources:
          requests:
            cpu: 0.15
        securityContext:
          privileged: true
        args:
        - --path.procfs
        - /host/proc
        - --path.sysfs
        - /host/sys
        - --collector.filesystem.ignored-mount-points
        - '"^/(sys|proc|dev|host|etc)($|/)"'
        volumeMounts:
        - name: dev
          mountPath: /host/dev
        - name: proc
          mountPath: /host/proc
        - name: sys
          mountPath: /host/sys
        - name: rootfs
          mountPath: /rootfs
      tolerations:
      - key: "node-role.kubernetes.io/master" # 需要根据K8S版本更改污点格式
        operator: "Exists"
        effect: "NoSchedule"
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: dev
          hostPath:
            path: /dev
        - name: sys
          hostPath:
            path: /sys
        - name: rootfs
          hostPath:
            path: /
EOF

通过 kubectl apply 更新 node-exporter

$ kubectl apply -f node-export.yaml

备注:yaml 文件字段解读:

        args:
        - --path.procfs
        - /host/proc
        - --path.sysfs
        - /host/sys
        - --collector.filesystem.ignored-mount-points
        - '"^/(sys|proc|dev|host|etc)($|/)"'


--path.procfs /host/proc:指定 proc 文件系统的路径为/host/proc。Node Exporter 使用proc 文件系统来获取有关进程和系统信息的指标数据。

--path.sysfs /host/sys:指定 sys 文件系统的路径为/host/sys。Node Exporter 使用 sys 文件系统来获取有关系统硬件资源和内核信息的指标数据。

--collector.filesystem.ignored-mount-points "^/(sys|proc|dev|host|etc)($|/)":配置要忽略的文件系统挂载点的正则表达式。这个正则表达式指定了一些常见的文件系统挂载点,如/sys、/proc、/dev、/host 和/etc。Node Exporter 将忽略这些挂载点上的文件系统,不采集与其相关的指标数据。

查看 node-exporter 是否部署成功

$ kubectl get pods -n monitor-sa
NAME                  READY   STATUS    RESTARTS   AGE
node-exporter-22mdw   1/1     Running   0          12s
node-exporter-8vz68   1/1     Running   0          12s
node-exporter-kxfjj   1/1     Running   0          12s
node-exporter-twtbd   1/1     Running   0          12s
node-exporter-w4crx   1/1     Running   0          12s
node-exporter-whjvq   1/1     Running   0          12s

通过 node-exporter 采集数据

curl http://主机 ip:9100/metrics

node-export 默认的监听端口是 9100,可以看到当前主机获取到的所有监控数据

$ curl http://192.168.2.201:9100/metrics | grep node_cpu_seconds

显示主机 cpu 的使用情况:

# HELP node_cpu_seconds_total Seconds the cpus spent in each mode.
# TYPE node_cpu_seconds_total counter
node_cpu_seconds_total{cpu="0",mode="idle"} 559690.13
node_cpu_seconds_total{cpu="0",mode="iowait"} 20092.4
node_cpu_seconds_total{cpu="0",mode="irq"} 0
node_cpu_seconds_total{cpu="0",mode="nice"} 0.3
node_cpu_seconds_total{cpu="0",mode="softirq"} 3898.72
node_cpu_seconds_total{cpu="0",mode="steal"} 0
node_cpu_seconds_total{cpu="0",mode="system"} 35928.15
node_cpu_seconds_total{cpu="0",mode="user"} 37928.54
node_cpu_seconds_total{cpu="1",mode="idle"} 557732.68
node_cpu_seconds_total{cpu="1",mode="iowait"} 20967.02
node_cpu_seconds_total{cpu="1",mode="irq"} 0
node_cpu_seconds_total{cpu="1",mode="nice"} 0.35
node_cpu_seconds_total{cpu="1",mode="softirq"} 6489.73
node_cpu_seconds_total{cpu="1",mode="steal"} 0
node_cpu_seconds_total{cpu="1",mode="system"} 35026
node_cpu_seconds_total{cpu="1",mode="user"} 37406.63

​ 上述内容是通过向 Node Exporter 的默认监听端口发送 HTTP 请求,获取到的有关 CPU 使用情况的监控数据。以下是对这些数据的解释说明:

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

# TYPE:说明当前指标的数据类型,上面是 counter 类型,只是采集递增的指标

​ 1、node_cpu_seconds_total 是一个指标(metric),表示 CPU 在不同模式下花费的时间(以秒为单位)。它是一个计数器类型的指标,用于记录 CPU 在各个模式下的累计时间。

​ 2、{cpu="0", mode="idle"}:这是 node_cpu_seconds_total 指标的标签(label),用于标识具体的 CPU 核心和模式。在这个例子中,cpu="0"表示标识为 0 的 CPU 核心,mode="idle"表示CPU 处于空闲状态。

​ 3、72963.37 是 CPU 核心 0 在空闲模式下花费的累计时间,单位是秒。这表示 CPU 核心 0 在空闲状态下的时间总和。

​ 类似地,还有其他标签和对应的数值,表示 CPU 在不同模式下的累计时间,例如 iowait(等待 I/O 操作的时间)、irq(处理硬件中断的时间)、nice(优先级较低的用户态时间)、softirq(处理软件中断的时间)、steal(被虚拟化环境偷取的时间)、system(内核态时间)和 user(用户态时间)。

$ curl http://192.168.2.201:9100/metrics | grep node_load
# HELP node_load1 1m load average.
# TYPE node_load1 gauge
node_load1 0.15
# HELP node_load15 15m load average.
# TYPE node_load15 gauge
node_load15 0.35
# HELP node_load5 5m load average.
# TYPE node_load5 gauge
node_load5 0.32

​ 上述内容是通过向 Node Exporter 获取到的关于系统负载的监控数据。以下是对这些数据的解释说明:

​ 1、node_load1 1m load average 表示 1 分钟的系统负载平均值。

​ 2、gauge 是指 node_load1 指标的类型。Gauge 类型的指标表示一个瞬时的数值,可以任意上升或下降。

​ 0.15 是实际的负载数值。在这个例子中,负载数值为 0.1,表示系统当前的负载相对较低。

19.3 在 k8s 集群中安装 Prometheus server 服务

19.3.1 创建 sa 账号

在 k8s 集群的控制节点操作,创建一个 sa 账号

$ kubectl create serviceaccount monitor -n monitor-sa

把 sa 账号 monitor 通过 clusterrolebing 绑定到clusterrole 上

$ kubectl create clusterrolebinding monitor-clusterrolebinding -n monitor-sa --clusterrole=cluster-admin --serviceaccount=monitor-sa:monitor

注意:有的同学执行上面授权也会报错,那就需要下面的授权命令:

$ kubectl create clusterrolebinding monitor-clusterrolebinding-1 -n monitor-sa --clusterrole=cluster-admin --user=system:serviceaccount:monitor:monitor-sa

19.3.2 创建数据目录

在 存储 作节点创建存储数据的目录:

$ mkdir /data -p
$ chmod 777 /data/

19.3.3 安装 prometheus 服务

以下步骤均在 k8s 集群的控制节点操作:

创建一个 configmap 存储卷,用来存放 prometheus 配置信息

prometheus-cfg.yaml 文件内容如下:

$ cat 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'
      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_(.+)
    - 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
      relabel_configs:
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
      - target_label: __address__
        replacement: kubernetes.default.svc:443
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
        target_label: __metrics_path__
        replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
    - 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
    - job_name: 'kubernetes-service-endpoints'
      kubernetes_sd_configs:
      - role: endpoints
      relabel_configs:
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex: (https?)
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
      - action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_service_name]
        action: replace
        target_label: kubernetes_name

基于 yaml 文件创建 configmap 资源

$ kubectl apply -f  prometheus-cfg.yaml

备注:prometheus-cfg.yaml 解释说明:

  • scrape_interval: 15s:这个参数定义了两次数据采集之间的间隔时间。在这个例子中,数据将每隔 15 秒进行一次采集。
  • scrape_timeout: 10s:这个参数定义了单次数据采集的超时时间。如果在10 秒内无法完成数据采集,系统可能会中止该次采集。
  • evaluation_interval: 1m:这个参数定义了评估(或触发报警)的时间间隔。在这个例子中, 系统将每隔 1 分钟对采集到的数据进行一次评估或触发报警。
    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_(.+)


•   scrape_configs:这个参数定义了要采集的目标配置列表。   

•   job_name: 'kubernetes-node':这个参数定义了采集任务的名称,这里命名为'kubernetes-node'。

•   kubernetes_sd_configs:这个参数定义了 Kubernetes 服务发现的配置。在这个例子中, 使用了 Kubernetes 服务发现来发现节点信息。

•   role: node:这个参数指定了要发现的 Kubernetes 资源的角色。在这个例子中,只发现节点(node)资源。

•   relabel_configs:这个参数定义了对采集的目标进行标签重整的配置列表。标签重整可以用于修改目标的标签或标签值,以便在监控系统中进行更精确的标识和查询。

•   source_labels: [ address ]:这个参数指定了要使用的源标签,这里使用的是    address标签。

•   regex: '(.*):10250':这个参数定义了一个正则表达式,用于匹配源标签的值。在这个例子中, 匹配形如 IP:10250 的地址。

•   replacement: '${1}:9100':这个参数定义了替换匹配结果的表达式。${1} 表示正则表达式中第一个括号捕获到的内容,这里将 IP:10250 中的 10250 替换为 9100。

•   target_label: address   :这个参数定义了目标标签,用于存储替换后的地址。

•   action: replace:这个参数定义了标签重整的动作,这里是替换操作。

•   action: labelmap: 标签重整的操作。它基于一个正则表达式meta_kubernetes_node_label_(.+),来匹配具有特定前缀的标签,并为匹配到的每个标签创建一个标签映射。

假设在 Kubernetes 的节点资源中,存在以下标签:

•      meta_kubernetes_node_label_app: frontend 

•      meta_kubernetes_node_label_env: production

•      meta_kubernetes_node_label_region: us-west

    使用  action: labelmap  并指定正则表达式 meta_kubernetes_node_label_(.+) 标签,并为每个匹配到的标签创建一个对应的标签映射。在这个例子中,它会创建以下标签映射:
•   app: frontend

•   env: production

•   region: us-west
    这样,在监控系统中,你就可以根据这些新的标签进行更精确的标识和查询。例如,你可以根据app:  

frontend 标签过滤出所有具有该标签的节点,并针对这些节点进行特定的监控配置或报警设置。

    标签重整的目的是提供更灵活和有针对性的标签处理,以便更好地利用监控系统的功能和查询能力。希望这次解释更加清晰明了。
    - 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
      relabel_configs:
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
      - target_label: __address__
        replacement: kubernetes.default.svc:443
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
        target_label: __metrics_path__
        replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor 


•   job_name: 'kubernetes-node-cadvisor': 这是作业的名称,用于在 Prometheus 配置中唯一标识该作业。

•   kubernetes_sd_configs: 这是 Kubernetes 服务发现的配置部分。
        •   role: node  : 指定要发现的 Kubernetes 对象的角色,这里是节点。

•   scheme: https: 指定使用的协议,这里是 HTTPS。

•   tls_config: 这是用于配置 TLS 连接的部分。
    •   ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 
        Kubernetes API 服务器证书的 CA 文件路径。它位于 Kubernetes 集群中的/var/run/secrets/kubernetes.io/serviceaccount/ca.crt。

•   bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
行身份验证的令牌文件路径。它位于 Kubernetes 集群中的/var/run/secrets/kubernetes.io/serviceaccount/token。

•   relabel_configs: 这是重新标签配置的部分,用于修改或添加指标标签。

    •   - action: labelmap  : 将匹配的标签映射为新标签。
            •   regex:   meta_kubernetes_node_label_(.+)    : 正则表达式用于匹配Kubernetes 节点的标签。
    •   - target_label: address     : 指定目标标签为       address ,表示 Prometheus 将请求发送到该地址。
        •   replacement: kubernetes.default.svc:443: 替换目标地址为kubernetes.default.svc:443,这是 Kubernetes 集群内部的服务地址和端口。
    •   - source_labels: [ meta_kubernetes_node_name]: 指定源标签为meta_kubernetes_node_name,表示从该标签获取值。
        •   regex: (.+) : 使用正则表达式捕获节点名称的值。
        •   target_label: metrics_path : 指定目标标签为 metrics_path ,表示替换指标路径。
            •   replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
替换目标路径为 /api/v1/nodes/${1}/proxy/metrics/cadvisor,其中${1} 是前面捕获的节点名称。
    - 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


•   job_name: 'kubernetes-apiserver': 这是作业的名称
•   kubernetes_sd_configs: 这是 Kubernetes 服务发现的配置部分。
    •   role: endpoints : 指定要发现的 Kubernetes 对象的角色,这里是端点。
•   scheme: https   : 指定使用的协议,这里是 HTTPS。
•   tls_config: 这是用于配置 TLS 连接的部分。
    •   ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt : 指定用于验证 Kubernetes API 服务器证书的 CA 文件路径。它位于 Kubernetes 集群中的 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt。

•   bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token  : 指定用于进行身份验证的令牌文件路径。它位于 Kubernetes 集群中的 /var/run/secrets/kubernetes.io/serviceaccount/token。

•   relabel_configs: 这是重新标签配置的部分,用于修改或添加指标标签。

•   - source_labels: [ meta_kubernetes_namespace,meta_kubernetes_service_name, meta_kubernetes_endpoint_port_name]: 指定源标签为 Kubernetes 命名空间、服务名称和端口名称,表示从这些标签获取值。

•   - action: keep: 指定执行的操作是保留匹配的标签。

•   - regex: default;kubernetes;https: 使用正则表达式匹配标签的值。这里的正则表达式表示只保留命名空间为 "default"、服务名称为 "kubernetes" 和端口名称为"https" 的标签。

​ 基于案例分析,这个配置的目的是仅保留与 Kubernetes API 服务器相关的指标,并且仅关注具有特定命名空间、服务名称和端口名称的端点。这是为了确保只收集与 Kubernetes API 服务器的HTTPS 端口相关的指标,以便进行监控和分析。

    - job_name: 'kubernetes-service-endpoints'
      kubernetes_sd_configs:
      - role: endpoints
      relabel_configs:
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex: (https?)
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
      - action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_service_name]
        action: replace
        target_label: kubernetes_name 
    上述内容是一个 Prometheus 的配置文件片段,用于配置 Kubernetes 服务的终端点抓取规则。让我们逐个解释每个参数的含义和为什么要这样编写。
1. job_name: 'kubernetes-service-endpoints'
    •   这是定义作业名称的参数。在 Prometheus 中,作业代表一组具有相似功能的目标。
2. kubernetes_sd_configs:
    •   这个参数用于配置 Kubernetes 服务发现(Service Discovery)。它告诉
Prometheus 在 Kubernetes 集群中查找哪些资源作为目标。
3. role: endpoints
    •   这个参数指定了要发现的资源角色。在这种情况下,我们正在查找 Kubernetes 的终
端点资源。
4. relabel_configs:
    •   这是一个重标签配置列表,用于在 Prometheus 抓取目标之前对它们进行转换和修改。

5.- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true
    •   这个配置表明只保留带有prometheus.io/scrape注释且值为 true 的目标。这是一种过滤机制,确保只抓取具有该注释的目标。

6. source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex: (https?)
    •   这个配置用于替换meta_kubernetes_service_annotation_prometheus_io_scheme 标签的值。它将匹配的标签值替换为   scheme   标签的值。正则表达式(https?)匹配 http 或 https,并将结果作为替换值。

7. source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
    •   这个配置类似于前一个配置,但用于替换meta_kubernetes_service_annotation_prometheus_io_path 标签的值,并将结果存储在 metrics_path 标签中。正则表达式(.+)匹配任何非空字符串作为替换值。

8. source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
    •   这个配置将 address 标签的值和 meta_kubernetes_service_annotation_prometheus_io_port 标签的值结合起来,并替换 address 标签的值。正则表达式([^:]+)(?::\d+)?;(\d+)将匹配的地址和端口组合起来,使用冒号分隔,并存储在 address 标签中。

9.action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
    •   这个配置是一个标签映射操作,它从带有特定前缀的标签中提取标签的值,并创建相应的目标标签。
在这种情况下,它从以 meta_kubernetes_service_label_开头的标签中提取值,并创建具有相同名称的目标标签。

10. source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
    •   这个配置用于替换 meta_kubernetes_namespace 标签的值,并将结果存储在 kubernetes_namespace 目标标签中。它将命名空间作为一个标签提供给 Prometheus,以便在查询和筛选时使用。

11. source_labels: [__meta_kubernetes_service_name]
        action: replace
        target_label: kubernetes_name
    •   这个配置类似于前一个配置,但用于替换 meta_kubernetes_service_name 标签的值,并将结果存储在 kubernetes_name 目标标签中。它将服务名称作为一个标签提供给Prometheus,以便在查询和筛选时使用。

通过 deployment 部署 prometheus

​ 安装 prometheus server 需要的镜像 prometheus_2.33.5.tar.gz 上传到 k8s 的工作节点 ,手动解压:

$ ctr -n=k8s.io images import prometheus_2.33.5.tar.gz

$ docker load -i prometheus_2.33.5.tar.gz

prometheus-deploy.yaml ,上传到自己的 k8s 的控制节点,内容如下:

$ cat prometheus-deploy.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-server
  namespace: monitor-sa
  labels:
    app: prometheus
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
      component: server
    #matchExpressions:
    #- {key: app, operator: In, values: [prometheus]}
    #- {key: component, operator: In, values: [server]}
  template:
    metadata:
      labels:
        app: prometheus
        component: server
      annotations:
        prometheus.io/scrape: 'false'
    spec:
      nodeName: k8s-node01
      serviceAccountName: monitor
      containers:
      - name: prometheus
        image: 192.168.2.206/library/prometheus:v2.33.5
        imagePullPolicy: IfNotPresent
        command:
          - prometheus
          - --config.file=/etc/prometheus/prometheus.yml
          - --storage.tsdb.path=/prometheus
          - --storage.tsdb.retention=720h
          - --web.enable-lifecycle
        ports:
        - containerPort: 9090
          protocol: TCP
        volumeMounts:
        - mountPath: /etc/prometheus
          name: prometheus-config
        - mountPath: /prometheus/
          name: prometheus-storage-volume
      volumes:
        - name: prometheus-config
          configMap:
            name: prometheus-config
        - name: prometheus-storage-volume
          hostPath:
           path: /data
           type: Directory

​ 注意:在上面的 prometheus-deploy.yaml 文件有个 nodeName 字段,这个就是用来指定创建的这个 prometheus 的 pod 调度到哪个节点上。

​ 我们这里让 nodeName=k8s-node01,也即是让 pod 调度到 k8s-node01 节点上,因为 k8s-node01 节点我们创建了数据目录/data,所以大家记住:你在 k8s 集群的哪个节点创建/data,就让 pod 调度到哪个节点。

通过 kubectl apply 更新 prometheus

$ kubectl apply -f prometheus-deploy.yaml 

查看 prometheus 是否部署成功

$ kubectl get pods -n monitor-sa
NAME                                 READY   STATUS    RESTARTS   AGE
node-exporter-22mdw                  1/1     Running   0          60m
node-exporter-8vz68                  1/1     Running   0          60m
node-exporter-kxfjj                  1/1     Running   0          60m
node-exporter-twtbd                  1/1     Running   0          60m
node-exporter-w4crx                  1/1     Running   0          60m
node-exporter-whjvq                  1/1     Running   0          60m
prometheus-server-864f4b95df-2mxpr   1/1     Running   0          72s

给 prometheus pod 创建一个 service

prometheus-svc.yaml ,上传到 k8s 的控制节点,内容如下:

$ cat prometheus-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: prometheus
  namespace: monitor-sa
  labels:
    app: prometheus
spec:
  type: NodePort
  ports:
    - port: 9090
      targetPort: 9090
      protocol: TCP
  selector:
    app: prometheus
    component: server

通过 kubectl apply 更新 service

$ kubectl apply -f prometheus-svc.yaml 

查看 service 在物理机映射的端口

$ kubectl get svc -n monitor-sa
NAME         TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
prometheus   NodePort   10.108.218.38   <none>        9090:31200/TCP   21s

​ 通过上面可以看到 service 在宿主机上映射的端口是 31200,这样我们访问 k8s 集群的控制节点的 ip:30009,就可以访问到prometheus 的web ui 界面了

访问 prometheus web ui ,界面浏览器输入如下地址:

http://192.168.2.201:31200/graph

可看到如下页面:

image-20231029155854595

热加载:

$ kubectl get pod -n monitor-sa -owide |grep prometheus-server
prometheus-server-864f4b95df-2mxpr   1/1     Running   0          13m   10.244.85.204   k8s-node01     <none>           <none>

$ curl -X POST http://10.244.85.204:9090/-/reload

19.4 安装和配置可视化 UI 界面 Grafana

​ 安装 Grafana 需要的镜像 grafana_8.4.5.tar.gz ,把镜像上传到 k8s 的各个控制节点和 k8s 的各个工作节点,然后在各个节点手动解压:

$ ctr -n=k8s.io images import grafana_8.4.5.tar.gz 

$ docker load -i grafana_8.4.5.tar.gz 
[root@k8s-master01 ~]# mkdir /var/lib/grafana -p
[root@k8s-master01 ~]# chmod 777 /var/lib/grafana/ 

[root@k8s-node01 ~]# mkdir /var/lib/grafana -p 
[root@k8s-node01 ~]# chmod 777 /var/lib/grafana/

grafana.yaml 上传到 k8s 的控制节点,内容如下:

[root@xuegod63 ~]# cat grafana.yaml 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: monitoring-grafana
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      task: monitoring
      k8s-app: grafana
  template:
    metadata:
      labels:
        task: monitoring
        k8s-app: grafana
    spec:
      nodeName: k8s-node01
      containers:
      - name: grafana
#        image: grafana/grafana:8.4.5
        image: 192.168.2.206/library/grafana:8.4.5
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 3000
          protocol: TCP
        volumeMounts:
        - mountPath: /etc/ssl/certs
          name: ca-certificates
          readOnly: true
        - mountPath: /var
          name: grafana-storage
        - mountPath: /var/lib/grafana/
          name: lib
        env:
        - name: INFLUXDB_HOST
          value: monitoring-influxdb
        - name: GF_SERVER_HTTP_PORT
          value: "3000"
          # The following env variables are required to make Grafana accessible via
          # the kubernetes api-server proxy. On production clusters, we recommend
          # removing these env variables, setup auth for grafana, and expose the grafana
          # service using a LoadBalancer or a public IP.
        - name: GF_AUTH_BASIC_ENABLED
          value: "false"
        - name: GF_AUTH_ANONYMOUS_ENABLED
          value: "true"
        - name: GF_AUTH_ANONYMOUS_ORG_ROLE
          value: Admin
        - name: GF_SERVER_ROOT_URL
          # If you're only using the API Server proxy, set this value instead:
          # value: /api/v1/namespaces/kube-system/services/monitoring-grafana/proxy
          value: /
      volumes:
      - name: ca-certificates
        hostPath:
          path: /etc/ssl/certs
      - name: grafana-storage
        emptyDir: {}
      - name: lib
        hostPath:
         path: /var/lib/grafana
         type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
metadata:
  labels:
    # For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons)
    # If you are NOT using this as an addon, you should comment out this line.
    kubernetes.io/cluster-service: 'true'
    kubernetes.io/name: monitoring-grafana
  name: monitoring-grafana
  namespace: kube-system
spec:
  # In a production setup, we recommend accessing Grafana through an external Loadbalancer
  # or through a public IP.
  # type: LoadBalancer
  # You could also use NodePort to expose the service at a randomly-generated port
  # type: NodePort
  ports:
  - port: 80
    targetPort: 3000
  selector:
    k8s-app: grafana
  type: NodePort

更新 yaml 文件

$ kubectl apply -f grafana.yaml 

验证是否安装成功

$ kubectl get pod -n kube-system |grep grafana
monitoring-grafana-6d58d4fd78-6ffpr        1/1     Running   0                38s

查看 grafana 前端的 service

$ kubectl get svc -n kube-system |grep grafana
monitoring-grafana   NodePort    10.108.189.116   <none>        80:31438/TCP                   77s

登陆 grafana,在浏览器访问 http://192.168.2.201:31438

可看到如下界面:

image-20231029162412628

配置 grafana 界面

开始配置 grafana 的 web 界面:

选择 Add your first data source

img

出现如下:

img

选择 Prometheus,出现如下:

Name: Prometheus

HTTP 处的 URL 如下:

http://prometheus.monitor-sa.svc:9090

配置好的整体页面如下:

img

img

​ 点击右下角 Save & Test,出现如下 Data source is working,说明 prometheus 数据源成功的被 grafana 接入了:

img

​ 导入监控模板,可在如下链接搜索

https://grafana.com/dashboards?dataSource=prometheus&search=kubernetes

可直接导入 node_exporter.json 监控模板,这个可以把 node 节点指标显示出来

可直接导入 docker_rev1.json,这个可以把容器资源指标显示出来

按如下步骤:

上面 Save & Test 测试没问题之后,就可以返回 Grafana 主页面

image-20231029163713321

点击左侧+号下面的 Import

img

出现如下界面:

img

选择 Upload json file,出现如下

image-20231029163744357

​ 选择一个本地的 json 文件,我们选择的是上面让大家下载的 node_exporter.json 这个文件,选择之后出现如下:

img

注:箭头标注的地方 Name 后面的名字是 node_exporter.json 定义的

Prometheus 后面需要变成 Prometheus,然后再点击 Import,就可以出现如下界面:

image-20231029163844198

导入 docker_rev1.json 监控模板,步骤和上面导入 node_exporter.json 步骤一样

导入之后显示如下:

image-20231029164037488

19.5 kube-state-metrics 组件解读

19.5.1 什么是 kube-state-metrics?

​ kube-state-metrics 是一个开源的 Kubernetes 监控工具,它通过将 Kubernetes 集群中的资源 状态转换为可观察的指标(metrics),提供了对 Kubernetes 对象的详细监控和可视化。

​ 以下是 kube-state-metrics 的基本介绍:

1. 功能:kube-state-metrics 从 Kubernetes API 服务器中获取资源对象的当前状态,并将其转换为 Prometheus 指标。它监视集群中的各种资源,包括节点、命名空间、部署、服务、副本集、状态集、持久卷等。通过 kube-state-metrics,您可以获取有关这些资源的重要指标,例如资源的数量、创建时间、标签、状态等。

2. 架构:kube-state-metrics 作为一个独立的容器化应用程序运行在 Kubernetes 集群中,它定期轮询 Kubernetes API 服务器以获取资源对象的信息。然后,它将这些信息转换为可观察的指标,并将其公开为 Prometheus 兼容的 HTTP 端点。

3. Prometheus 兼容性:kube-state-metrics 以 Prometheus 的数据模型为基础,生成符合Prometheus 指标格式的指标数据。这使得 Prometheus 能够通过 HTTP 抓取 kube-statemetrics 的指标数据,并将其用于监控和警报。

4. 指标示例:kube-state-metrics 生成的指标包括对象的数量、重启次数、资源限制、标签信息、容器状态等。例如,您可以获取每个命名空间的 Pod 数量、每个节点的 CPU 和内存使用情况、每个服务的副本数量等信息。

5. 可视化和监控:通过将 kube-state-metrics 与 Prometheus 和 Grafana 等工具结合使用,您可以创建仪表板和报警规则,对 Kubernetes 集群中的资源进行实时监控和可视化。这使您能够了解集群中资源的状态、趋势和性能,以便进行故障排查、容量规划和性能优化。

19.5.2 安装和配置 kube-state-metrics

​ 创建 sa,并对 sa 授权

​ 在 k8s 的控制节点生成一个 kube-state-metrics-rbac.yaml 文件,kube-state-metrics- rbac.yaml 文件在课件,大家自行下载到 k8s 的控制节点即可,内容如下:

$ cat kube-state-metrics-rbac.yaml

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

通过 kubectl apply 更新 yaml 文件

$ kubectl apply -f kube-state-metrics-rbac.yaml 

安装 kube-state-metrics 组件

安装 kube-state-metrics 组件需要的镜像上传到 k8s 所有节点,手动解压:

$ docker load -i kube-state-metrics_1_9_0.tar.gz 

kube-state- metrics-deploy.yaml内容如下:

$ cat 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: quay.io/coreos/kube-state-metrics:v1.9.0
        image: 192.168.2.206/library/kube-state-metrics:v1.7.1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

通过 kubectl apply 更新 yaml 文件

$ kubectl apply -f kube-state-metrics-deploy.yaml 

查看 kube-state-metrics 是否部署成功

$ kubectl get pods -n kube-system -l app=kube-state-metrics 
NAME                                 READY   STATUS    RESTARTS   AGE
kube-state-metrics-57b998845-zltjv   1/1     Running   0          27s

创建 service

$ cat kube-state-metrics-svc.yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    prometheus.io/scrape: 'true'
  name: kube-state-metrics
  namespace: kube-system
  labels:
    app: kube-state-metrics
spec:
  ports:
  - name: kube-state-metrics
    port: 8080
    protocol: TCP
  selector:
    app: kube-state-metrics

通过 kubectl apply 更新 yaml

$ kubectl apply -f kube-state-metrics-svc.yaml 

查看 service 是否创建成功

$ kubectl get svc -n kube-system | grep kube-state-metrics
kube-state-metrics   ClusterIP   10.111.77.122    <none>        8080/TCP                       17s

​ 在 grafana web 界面导入 Kubernetes Cluster (Prometheus)-1577674936972.json 和Kubernetes cluster monitoring (via Prometheus) (k8s 1.16)-1577691996738.json

​ 导入 Kubernetes Cluster (Prometheus)-1577674936972.json 之后出现如下页面

image-20231029165816155

​ 在 grafana web 界面导入 Kubernetes cluster monitoring (via Prometheus) (k8s 1.16)- 1577691996738.json,出现如下页面

image-20231029165827359

总结:

19.1 深度解读 Prometheus

19.2 安装采集节点资源指标组件 node-exporter

19.3 在 k8s 集群中安装 Prometheus server 服务

19.4 安装和配置可视化 UI 界面 Grafana

19.5 kube-state-metrics 组件解读