云原生监控Prometheus安装部署

第十七章、云原生监控Prometheus入门

17.1什么是Prometheus

Prometheus 是一个开源的系统监控和告警工具包。它最初是由 SoundCloud 开发的,目前已经成为云原生计算基金会(CNCF)的第二个毕业项目(仅次于 Kubernetes)。

主要特点包括:

  1. 多维度数据模型
  • 时间序列数据由指标名称和键值对标签组成
  • 支持灵活的查询语言 PromQL
  1. 数据收集
  • 通过 HTTP 协议采用 pull 模型拉取数据
  • 支持 push 网关来接收短期任务的数据推送
  • 支持服务发现和静态配置
  1. 数据存储
  • 使用本地时序数据库存储监控数据
  • 高效的数据压缩算法
  • 支持数据的长期存储
  1. 可视化
  • 内置简单的图形界面
  • 可以与 Grafana 等工具集成实现更强大的可视化
  1. 告警
  • 支持灵活的告警规则配置
  • 通过 Alertmanager 组件统一处理告警

17.2Prometheus结构解析

1. Prometheus Server-核心组件

  • 核心功能:Prometheus Server 是整个监控系统的核心,用于从不同的目标(targets)拉取指标数据,存储在时间序列数据库(TSDB)中,并提供查询接口。
  • 主要组件
    • Retrieval:检索模块,负责从配置的监控目标(如 exporters)中定期拉取(pull)指标数据。
    • TSDB(Time Series Database):时间序列数据库,用于存储拉取到的监控数据。
    • HTTP Server:提供 HTTP API 接口服务 和 Prometheus 查询语言(PromQL)接口,用户和其他服务可以通过它访问数据和执行查询。
  • 数据存储:Prometheus 通过本地磁盘(如 HDD/SSD)来存储数据。

2. Prometheus Targets-数据采集层

  • 定义:Prometheus 通过拉取(pull)的方式从不同的监控目标(Targets)收集数据。Targets 包括各种可以提供 Prometheus 格式指标数据的进程或服务。
  • Jobs 和 Exporters:这些目标可能是应用的实例(称为 Jobs),也可以是特定的 Exporters,如 Node Exporter(收集操作系统数据)或其他第三方导出器。
  • 数据拉取方式:Prometheus Server 定期从这些目标拉取数据,以便获得最新的监控指标。

3. Pushgateway-数据采集层

  • 作用:Pushgateway 用于接收短生命周期任务的指标数据。某些任务可能只运行一次或持续时间很短(例如批处理任务),如果直接被 Prometheus 拉取,可能无法及时捕获这些任务的状态。Pushgateway 允许这些任务在退出时推送数据,保证 Prometheus Server 能拉取到这些数据。
  • 数据流向:短生命周期任务在结束时向 Pushgateway 推送数据,Prometheus Server 再从 Pushgateway 拉取这些数据。

4. Service Discovery-服务发现

支持两种主要的服务发现方式:

  • kubernetes: 自动发现 K8s 集群中的监控目标

  • file_sd: 基于文件的服务发现机制

  • 作用:Prometheus 使用服务发现机制动态发现需要监控的目标。常见的服务发现方式包括 Kubernetes API、静态文件配置(file_sd)等。

  • Kubernetes Integration:对于 Kubernetes 环境,Prometheus 可以直接通过 Kubernetes API 动态发现 Pod、Service 等资源,实现自动化监控。

5. Alertmanager-告警模块

  • 作用:Prometheus 中的 Alertmanager 负责处理由 Prometheus Server 生成的告警。Prometheus 使用预先定义的告警规则来触发告警事件(例如某些指标超过阈值)。
  • 告警推送:Prometheus Server 会根据配置的告警规则将告警推送给 Alertmanager。Alertmanager 负责对告警进行分组、去重、抑制等操作,并根据配置发送到不同的通知渠道。
  • 通知渠道:Alertmanager 可以将告警通过 Email、PagerDuty 或其他集成工具发送给运维团队。

6. 数据可视化与查询接口(图右下部分)

PromQL: Prometheus 的查询语言

  • Prometheus Web UI:Prometheus 自带的 Web UI 提供了一些基本的可视化和查询功能,用户可以通过 PromQL 执行查询,并查看实时数据。
  • Grafana:更高级的可视化需求通常会借助 Grafana,它可以直接查询 Prometheus 数据,并提供丰富的图表选项和可定制的仪表板。
  • API Clients:Prometheus 提供 HTTP API,使得外部应用或脚本可以直接查询 Prometheus 中的数据,以实现自定义分析或集成需求。

7. 数据流向总结

Pull 模式:

  • Prometheus server 主动从 targets 拉取数据
  • 从 Pushgateway 拉取短期任务的数据
  • Pull 模式:Prometheus 的默认数据采集模式是从 Targets 拉取数据,Prometheus Server 定期访问每个目标的 HTTP 指标端点,获取并存储指标。

Push 模式:

  • 短期任务推送数据到 Pushgateway

  • Prometheus server 推送告警到 Alertmanager

  • Push 模式(Pushgateway):对于短生命周期任务,通过 Pushgateway 推送数据。Pushgateway 存储这些数据,供 Prometheus Server 拉取。

告警流:

  • Prometheus Server 通过配置的告警规则触发告警事件,将其推送给 Alertmanager。Alertmanager 处理告警并发送给指定的通知系统(如 Email、PagerDuty)。

总结

Prometheus 架构的关键在于「拉取模式」的数据采集、「时间序列数据库」的数据存储、「告警管理」的处理方式和「数据可视化」的整合。这个设计使得 Prometheus 在云原生环境中具备了高效、自动化、动态监控的能力,并且与 Kubernetes 等系统无缝集成。

17.3Prometheus常见的自定义资源

Kubernetes 环境中部署 Prometheus 时,常见的自定义资源(CRD,Custom Resource Definitions)通常是 Prometheus Operator 提供的。它们主要是为了让 Prometheus 在 K8s 上能自动化地配置和管理,而不是让你每次都手动写繁琐的配置文件。

  1. Prometheus:定义并部署一个或多个 Prometheus 实例,也就是监控系统本身。
  2. Alertmanager:定义并部署 Alertmanager 实例,他负责接受Prometheus 发送的告警,并根据规则将告警通过钉钉、邮件、企业微信等通知到相关人员。
  3. ServiceMonitor:告诉 Prometheus “去监控这个 Service 的指标”,只适用于 Kubernetes 内部服务
  4. PodMonitor:与 ServiceMonitor 类似,当服务没有 Service(比如直接通过 Pod IP 访问),就用它来监控单个 Pod。
  5. Probe:通常用于定义监控静态目标,和BlackBox Exporter配合使用,监控官网是否能访问。
  6. ScrapeConfig:用于自定义监控目标,通常用于抓取Prometheus集群外部的目标数据。
  7. AlertmanagerConfig:用于定义Alertmanager 的配置,告诉 Alertmanager 如何处理告警(路由、分组、抑制规则等)。
  8. PrometheusRule:定义告警规则,也就是告诉 Prometheus “什么时候该报警”(比如阈值、持续时间)。

17.3.1Prometheus资源配置详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
apiVersion: monitoring.coreos.com/v1  # Prometheus Operator的API版本
kind: Prometheus # 资源类型,定义一个Prometheus实例
metadata:
name: prometheus # Prometheus实例的名称
namespace: monitoring # 部署的命名空间
spec:
replicas: 3 # Prometheus实例副本数,用于高可用
image: quay.io/prometheus/prometheus:v3.1.0 # 指定Prometheus镜像版本

# 服务账户配置(必需)
serviceAccountName: prometheus # 指定运行Prometheus Pod使用的ServiceAccount

# 告警管理器配置
alerting:
alertmanagers:
- namespace: monitoring # Alertmanager所在的命名空间
name: alertmanager-main # Alertmanager服务的名称
apiVersion: v2 # Alertmanager API版本
port: web # 连接Alertmanager的端口名称(通常是9093)

# 资源限制配置
resources:
requests: # 最小资源请求,用于Pod调度
memory: 400Mi # 最小内存需求
cpu: 100m # 最小CPU需求(0.1核)
limits: # 最大资源限制,防止资源过度使用
memory: 800Mi # 最大内存限制
cpu: 200m # 最大CPU限制(0.2核)

# 节点选择器(已修正为新标签)
nodeSelector:
kubernetes.io/os: linux # 仅在Linux节点上调度Pod

# 持久化存储配置
storage:
volumeClaimTemplate: # 动态创建PVC的模板
spec:
storageClassName: fast-ssd # 存储类名称,通常指向SSD存储
resources:
requests:
storage: 20Gi # 每个副本请求的存储空间大小

# 监控目标选择器配置(新增必需字段)
serviceMonitorSelector: # 选择要监控的ServiceMonitor资源
matchLabels:
app: prometheus # 选择带有此标签的ServiceMonitor

podMonitorSelector: # 选择要监控的PodMonitor资源
matchLabels:
app: prometheus # 选择带有此标签的PodMonitor

ruleSelector: # 选择要加载的PrometheusRule资源
matchLabels:
app: prometheus # 选择带有此标签的PrometheusRule

# 安全上下文配置(推荐添加)
securityContext:
fsGroup: 2000 # 设置文件系统组ID,确保存储权限正确
runAsNonRoot: true # 以非root用户运行,提高安全性
runAsUser: 1000 # 指定运行用户ID

# 数据保留配置(推荐添加)
retention: "30d" # 数据保留时间,30天后自动删除旧数据
retentionSize: "15GB" # 数据保留大小限制,超出后删除最老数据

# 外部访问配置(可选)
portName: web # 服务端口名称

# 配置重载间隔(可选)
evaluationInterval: 30s # 规则评估间隔
scrapeInterval: 30s # 默认抓取间隔

17.3.2Alertmanager资源配置详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: monitoring.coreos.com/v1   # CRD 版本,由 Prometheus Operator 定义
kind: Alertmanager # 声明资源类型是 Alertmanager
metadata:
name: alertmanager # Alertmanager 实例的名字
namespace: monitoring # 部署在哪个命名空间
labels: # 附加标签,便于选择器和管理
app: alertmanager # 自定义标签,用来标识资源类型
app.kubernetes.io/name: alertmanager # 语义化应用名(Kubernetes 推荐规范标签)
app.kubernetes.io/component: alerting # 组件角色,这里是告警模块
app.kubernetes.io/part-of: monitoring # 所属系统,这里是监控系统
app.kubernetes.io/instance: k8s # 实例名,表示该应用隶属于哪个实例
app.kubernetes.io/version: 0.23.0 # 版本号,标注该实例运行的版本
spec:
replicas: 3 # 部署副本数,通常配置为 2~3,保证高可用
image: quay.io/prometheus/alertmanager:v0.23.0 # 使用的镜像地址(不推荐,建议用 version 字段)
# version: v0.23.0 # 推荐写法,Operator 会自动拼接 quay.io/prometheus/alertmanager:v0.23.0
nodeSelector: # 节点选择器,用来约束 Pod 部署在哪类节点
kubernetes.io/os: linux # 运行在 Linux 节点(k8s 推荐标签)

17.3.3ServiceMonitor资源配置详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: monitoring.coreos.com/v1   # CRD 版本,由 Prometheus Operator 定义
kind: ServiceMonitor # 定义 ServiceMonitor 资源,用来发现并采集服务的监控指标
metadata:
name: grafana-monitor # ServiceMonitor 的名字
namespace: monitoring # 所属命名空间(不必须和应用一致,只要 Prometheus 能选中即可),建议和被监控的应用所在的命名空间一致,例如你要监控的应用在prod命名空间下,那么这里也应该是prod命名空间。
labels: # 附加标签,用于 Prometheus 的 serviceMonitorSelector 选择
app.kubernetes.io/name: servicemonitor # 资源类型标识
app.kubernetes.io/component: microservice-monitor # 表示该监控对象属于微服务监控组件
app.kubernetes.io/part-of: monitoring # 所属系统(监控体系)
app.kubernetes.io/version: 1.0.0 # 版本号,方便管理
spec:
selector: # 用来选择目标 Service
matchLabels: # 选择带有这些 label 的 Service
app.kubernetes.io/name: grafana # 目标 Service 的标签(需要和应用 Service 的 labels 对应)
endpoints: # 定义如何采集指标
- port: app-metrics # Service 暴露的端口名(必须和 Service spec.ports[].name 对应)
path: /actuator/prometheus # 指标暴露路径(Spring Boot 应用常用 /actuator/prometheus)
interval: 30s # 抓取间隔,Prometheus 每 30 秒采集一次
scrapeTimeout: 10s # 抓取超时时间,超过 10 秒就放弃

17.3.4PodMonitor资源配置详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: monitoring.coreos.com/v1       # CRD 版本,由 Prometheus Operator 定义
kind: PodMonitor # 定义 PodMonitor 资源,用于直接监控 Pod
metadata:
name: myapp-pod-monitor # PodMonitor 的名字
namespace: monitoring # PodMonitor 所在命名空间
labels: # 附加标签,供 Prometheus 的 podMonitorSelector 选择
app.kubernetes.io/name: podmonitor
app.kubernetes.io/component: app-metrics
app.kubernetes.io/part-of: monitoring
app.kubernetes.io/version: 1.0.0
spec:
selector: # 选择哪些 Pod 需要被监控
matchLabels: # 根据标签筛选目标 Pod
app: myapp # 例如只监控标签为 app=myapp 的 Pod
namespaceSelector: # 命名空间选择器,决定在哪些命名空间里找 Pod
matchNames: # 只在以下命名空间中查找
- prod # 只监控 prod 命名空间里的 Pod
podMetricsEndpoints: # 定义如何从 Pod 里采集指标
- port: metrics # Pod 容器暴露的端口名(必须和容器 spec.ports[].name 对应)
path: /metrics # 指标暴露路径(Prometheus 默认路径是 /metrics)
interval: 30s # 抓取间隔,每 30 秒采集一次
scrapeTimeout: 10s # 超时时间,超过 10 秒则放弃
scheme: http # 协议,可以是 http 或 https

17.3.5Probe

Prometheus Operator 中,Probe 用来监控非 K8s Service 的目标,例如外部 HTTP 服务、TCP 端口探活等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: monitoring.coreos.com/v1  #指定 CRD 的版本,这里是 monitoring.coreos.com/v1。
kind: Probe #定义资源类型,这里是 Probe。
metadata: #定义资源的元数据
name: external-probe-example # Probe 资源名称,方便区分
namespace: monitoring # Probe 所在的命名空间
labels: # 标签,用于选择和标识
app.kubernetes.io/name: probe
app.kubernetes.io/component: monitoring
app.kubernetes.io/part-of: prometheus
spec:
jobName: probe-external-example # 定义探测任务名称,用于区分不同探测任务
interval: 30s # 探测间隔,每隔 30 秒执行一次探测
scrapeTimeout: 10s # 超时时间,超过 10 秒未响应则视为失败
prober: # 定义探测器(prober)本身信息,负责执行探测
url: http://blackbox-exporter.monitoring.svc:9115 # blackbox-exporter 服务地址
scheme: http # 使用的协议(http/https)
module: http_2xx # 使用 blackbox-exporter 的模块(定义探测方式)
targets: # 目标配置
staticConfig: # 静态配置(支持 ServiceMonitor/PodMonitor 动态发现)
static: # 静态目标列表
- https://www.google.com # 被探测的目标 1
- https://www.github.com # 被探测的目标 2

Prometheus Operator 中,一个 Probe 只能对应 一个探测任务(它只有一个 prober、一个 module)。
所以如果想同时探测 HTTP 服务TCP 端口(比如 Redis、MySQL),需要为它们分别定义 多个 Probe 资源

示例:增加 Redis 和 MySQL 的探测

需要写 3 个探测任务:

  • HTTP 探测(外部网站)
  • Redis 探测(TCP 6379 端口)
  • MySQL 探测(TCP 3306 端口)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# ================================
# 1. HTTP 探测(外部网站)
# ================================
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
name: probe-http-external
namespace: monitoring
spec:
jobName: probe-http-external
interval: 30s
scrapeTimeout: 10s
prober:
url: blackbox-exporter.monitoring.svc:9115 # 注意这里不要写 /probe,operator 会自动拼接
scheme: http
module: http_2xx
targets:
staticConfig:
static:
- https://www.google.com
- https://www.github.com

---
# ================================
# 2. Redis 探测(TCP 6379)
# ================================
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
name: probe-redis
namespace: monitoring
spec:
jobName: probe-redis
interval: 30s
scrapeTimeout: 5s
prober:
url: blackbox-exporter.monitoring.svc:9115
scheme: http
module: tcp_connect # 使用 blackbox-exporter 的 tcp_connect 模块
targets:
staticConfig:
static:
- redis-service.default.svc.cluster.local:6379 # 集群内 Redis 地址
- 192.168.1.10:6379 # 外部 Redis 地址

---
# ================================
# 3. MySQL 探测(TCP 3306)
# ================================
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
name: probe-mysql
namespace: monitoring
spec:
jobName: probe-mysql
interval: 30s
scrapeTimeout: 5s
prober:
url: blackbox-exporter.monitoring.svc:9115
scheme: http
module: tcp_connect # 同样用 tcp_connect
targets:
staticConfig:
static:
- mysql-service.default.svc.cluster.local:3306 # 集群内 MySQL 地址
- 192.168.1.20:3306 # 外部 MySQL 地址

17.3.6ScrapeConfig

ScrapeConfig 和 ServiceMonitor / PodMonitor 的区别在于:

  • ServiceMonitor / PodMonitor / Probe → 针对 Kubernetes 应用、Pod、外部探测,算是“高级抽象”。
  • ScrapeConfig → 原生 Prometheus 的 scrape_configs 的 CRD 版本,灵活度高,可以配置任何 Prometheus 支持的采集方式(包括文件发现、Consul、静态目标等)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# Kubernetes API 版本,指定使用 Prometheus Operator 的 ScrapeConfig CRD
apiVersion: monitoring.coreos.com/v1alpha1

# 资源类型:ScrapeConfig 是 Prometheus Operator 提供的自定义资源
# 用于定义 Prometheus 如何抓取指标数据
kind: ScrapeConfig

# 资源元数据配置
metadata:
# ScrapeConfig 资源的唯一名称标识符
name: redis-exporter-scrape

# 部署的命名空间,通常监控相关资源放在 monitoring 命名空间
namespace: monitoring

# 标签用于资源分类和选择器匹配
labels:
# 应用程序名称标签,遵循 Kubernetes 推荐标签规范
app.kubernetes.io/name: scrapeconfig
# 组件标签,标识这是监控组件
app.kubernetes.io/component: monitoring
# 所属系统标签,表明这是 Prometheus 监控系统的一部分
app.kubernetes.io/part-of: prometheus

# ScrapeConfig 的具体配置规范
spec:
# Prometheus 中的 job 名称,用于在指标中标识数据来源
# 所有从此配置抓取的指标都会带上 job="redis-exporter" 标签
jobName: redis-exporter

# 抓取间隔:每 30 秒向目标发起一次指标抓取请求
# 较短的间隔提供更高的监控精度,但增加网络和存储开销
scrapeInterval: 30s

# 抓取超时时间:单次抓取请求的最大等待时间
# 超过此时间未响应则认为抓取失败,应小于 scrapeInterval
scrapeTimeout: 10s

# 是否保留目标服务原有的标签
# true:保留目标暴露的所有原始标签,避免 Prometheus 自动添加的标签覆盖
honorLabels: true

# 请求协议:使用 HTTP 协议抓取指标
# 可选值:http, https
scheme: http

# 指标端点路径:Redis Exporter 暴露指标的 URL 路径
# Redis Exporter 通常使用 /scrape 而不是标准的 /metrics
metricsPath: /scrape

# 静态目标配置:手动指定要监控的目标列表
staticConfigs:
# 目标配置组
- targets:
# Redis 服务地址:使用 Redis 协议连接到 default 命名空间的 redis 服务的 6379 端口
# 这里是 Redis 实例的连接字符串,不是 HTTP 端点
- redis://redis.default:6379

# 为此目标组添加的静态标签
# 这些标签会附加到所有从该目标抓取的指标上
labels:
# 环境标签:标识为生产环境
env: prod
# 导出器类型标签:标识使用的是 redis exporter
exporter: redis

# 重新标签配置:在抓取前修改目标的标签
# 这是实现间接抓取模式的关键配置
relabelings:
# 规则1:将原始目标地址传递给 exporter
# 将 __address__ (redis://redis.default:6379) 复制到 __param_target 参数中
# Redis Exporter 通过 target 参数知道要连接哪个 Redis 实例
- sourceLabels: [__address__]
targetLabel: __param_target

# 规则2:设置实例标签
# 将 __param_target 的值设置为 instance 标签,用于在监控中识别具体的 Redis 实例
- sourceLabels: [__param_target]
targetLabel: instance

# 规则3:重定向抓取目标
# 将实际的抓取地址改为 Redis Exporter 服务地址
# Prometheus 实际会向 redis-exporter.monitoring:9121 发送请求
- targetLabel: __address__
replacement: redis-exporter.monitoring:9121

# 工作流程说明:
# 1. Prometheus 读取此配置,发现目标 redis://redis.default:6379
# 2. 经过 relabeling,实际请求变成:
# GET http://redis-exporter.monitoring:9121/scrape?target=redis://redis.default:6379
# 3. Redis Exporter 收到请求后连接到指定的 Redis 实例,获取指标并返回
# 4. Prometheus 将获取的指标存储,并添加 job="redis-exporter" 等标签

# 这种间接抓取模式的优势:
# - 一个 Redis Exporter 实例可以监控多个 Redis 实例
# - 无需为每个 Redis 实例部署独立的 exporter
# - 便于集中管理和配置监控目标

17.3.7Relabeling详解

17.3.8AlertmanagerConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: monitoring.coreos.com/v1alpha1   # CRD 的 API 版本
kind: AlertmanagerConfig # 定义资源类型,这里是 AlertmanagerConfig
metadata:
name: alertmanager-config-example # 配置资源名称
namespace: monitoring # 命名空间,需要和 Alertmanager 实例相同
spec:
route: # 根路由配置,定义告警的匹配和分发规则
receiver: default-receiver # 默认接收器(未匹配到时使用)
groupBy: ['alertname', 'severity'] # 按这些标签对告警进行分组
groupWait: 30s # 告警分组后,等待 30 秒再发送(用于收集更多告警一起发)
groupInterval: 5m # 同一个分组内新告警间隔至少 5 分钟再发送一次
repeatInterval: 3h # 已经发送的告警,如果仍未恢复,3 小时后重新提醒一次
routes: # 子路由(可以针对不同条件做不同处理)
- matchers: # 匹配规则
- name: severity
value: critical
matchType: =
receiver: critical-receiver # 匹配 severity=critical 的告警发到 critical-receiver
continue: false # 不继续往下匹配,匹配到就结束

receivers: # 定义告警接收器(通知方式)
- name: default-receiver
emailConfigs: # 邮件通知配置
- to: ops-team@example.com # 收件人邮箱
from: alertmanager@example.com # 发件人邮箱
smarthost: smtp.example.com:587 # 邮件服务器地址和端口
authUsername: alertmanager@example.com # SMTP 登录用户名
authPassword:
name: smtp-secret # 从 Secret 获取密码
key: password

- name: critical-receiver
webhookConfigs: # Webhook 通知配置
- url: 'http://alert-webhook-service.monitoring.svc:8080/' # Webhook 地址
sendResolved: true # 当告警恢复时也发送通知

17.3.9PrometheusRule

PrometheusRule 是 Prometheus Operator 提供的一种 CRD,用于集中管理告警规则(alerting rules)和录制规则(recording rules)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: monitoring.coreos.com/v1  # CRD 的 API 版本
kind: PrometheusRule # 资源类型,PrometheusRule 表示规则集合
metadata:
name: example-prometheus-rules # 规则名称
namespace: monitoring # 命名空间(通常和 Prometheus 实例在一起)
labels: # 标签,用于选择和管理
role: alert-rules
prometheus: k8s
spec:
groups: # 规则分组,可以有多个
- name: example.rules # 分组名称,逻辑上的分组单位
interval: 30s # 执行规则的间隔,覆盖 Prometheus 全局设置
rules: # 规则列表
- alert: HighErrorRate # 告警规则(Alerting Rule)名称
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
# 表达式,计算过去 5 分钟的 5xx 错误率是否大于 5%
for: 10m # 条件成立持续 10 分钟才触发告警
labels: # 给告警打标签
severity: warning
annotations: # 附加说明(展示在告警系统中)
summary: "High error rate detected"
description: "More than 5% of requests are failing with 5xx errors on {{ $labels.job }} for 10m."

17.3.10Prometheus资源分类

安装:Operator、Prometheus、Alertmanager、Grafana

监控:ServiceMonitor、Probe、PodMonitor、ScrapeConfig

告警:PrometheusRule

通知:AlertmanagerConfig

17.4Prometheus安装

笔记中选择Kube-Prometheus Stack的方式进行安装。

Kube-Prometheus项目地址:https://github.com/prometheus-operator/kube-prometheus/

首先需要通过该项目地址,找到和自己Kubernetes版本对应的Kube Prometheus Stack的版本:(我的k8s集群版本是v1.31.4,选择release-0.14、release-0.15、release-0.16都可以,我这里选择release-0.14版本)

1. 下载对应的release-0.14版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#创建目录:17-prometheus是学习本章节目录,监控章节的所有文件都在该目录中完成
[root@k8s-master01 pra] mkdir -p /root/pra/17-prometheus
#进入目录
[root@k8s-master01 pra]# cd 17-prometheus/

#拉取对应版本的文件包
[root@k8s-master01 17-prometheus]# git clone -b release-0.14 https://github.com/prometheus-operator/kube-prometheus.git
Cloning into 'kube-prometheus'...
remote: Enumerating objects: 20464, done.
remote: Counting objects: 100% (3886/3886), done.
remote: Compressing objects: 100% (262/262), done.
remote: Total 20464 (delta 3715), reused 3700 (delta 3605), pack-reused 16578 (from 1)
Receiving objects: 100% (20464/20464), 12.32 MiB | 3.03 MiB/s, done.
Resolving deltas: 100% (14089/14089), done.

如果上述clone命令无法拉取也可以下载压缩包,上传到服务器的目录中:

1
2
3
4
[root@k8s-master01 17-prometheus]# git clone -b release-0.14 https://github.com/prometheus-operator/kube-prometheus.git
Cloning into 'kube-prometheus'...
fatal: unable to access 'https://github.com/prometheus-operator/kube-prometheus.git/': Failed connect to github.com:443; Connection timed out
#如果遇到网络问题无法在线拉取可以参考下图解决

进入目标目录:

1
2
3
4
5
6
7
[root@k8s-master01 17-prometheus]# ll
total 4
drwxr-xr-x 12 root root 4096 Nov 12 17:38 kube-prometheus

#进入manifests目录,所有的安装文件都在manifests目录中
[root@k8s-master01 17-prometheus]# cd kube-prometheus/manifests

2.安装Prometheus Operator:

1
2
3
4
5
6
7
8
9
10
11
12
[root@k8s-master01 manifests]# kubectl create -f setup/
customresourcedefinition.apiextensions.k8s.io/alertmanagerconfigs.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/alertmanagers.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/podmonitors.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/probes.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/prometheuses.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/prometheusagents.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/prometheusrules.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/scrapeconfigs.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/servicemonitors.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/thanosrulers.monitoring.coreos.com created
namespace/monitoring created

安装Prometheus 核心组件:

要修改镜像地址的文件包含下面所有文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
路径:~/kube-prometheus-release-0.14/manifests
[root@k8s-master01 manifests]# grep "image:" *.yaml
alertmanager-alertmanager.yaml: image: quay.io/prometheus/alertmanager:v0.27.0
blackboxExporter-deployment.yaml: image: quay.io/prometheus/blackbox-exporter:v0.25.0
blackboxExporter-deployment.yaml: image: ghcr.io/jimmidyson/configmap-reload:v0.13.1
blackboxExporter-deployment.yaml: image: quay.io/brancz/kube-rbac-proxy:v0.18.1
grafana-deployment.yaml: image: grafana/grafana:11.2.0
kubeStateMetrics-deployment.yaml: image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.13.0
kubeStateMetrics-deployment.yaml: image: quay.io/brancz/kube-rbac-proxy:v0.18.1
kubeStateMetrics-deployment.yaml: image: quay.io/brancz/kube-rbac-proxy:v0.18.1
nodeExporter-daemonset.yaml: image: quay.io/prometheus/node-exporter:v1.8.2
nodeExporter-daemonset.yaml: image: quay.io/brancz/kube-rbac-proxy:v0.18.1
prometheusAdapter-deployment.yaml: image: registry.k8s.io/prometheus-adapter/prometheus-adapter:v0.12.0
prometheusOperator-deployment.yaml: image: quay.io/prometheus-operator/prometheus-operator:v0.76.2
prometheusOperator-deployment.yaml: image: quay.io/brancz/kube-rbac-proxy:v0.18.1
prometheus-prometheus.yaml: image: quay.io/prometheus/prometheus:v2.54.1

修改alertmanager的副本数和镜像下载地址:

1
2
3
4
5
#在创建之前需要决定你集群的副本数,假设我这里是测试环境,所以只创建一个副本,如果是生产环境建议至少3个副本
#alertmanager副本数在alertmanager-alertmanager.yaml配置文件中修改
#主要是副本数和镜像下载地址的配置:
image: quay.io/prometheus/alertmanager:v0.27.0 #如果自己有镜像仓库可以改为自己的仓库地址,下图已经修改为我自己的镜像仓库地址了
replicas: 3 #根据实际情况修改副本的数量,我配置的是1

修改prometheus的副本数和镜像下载地址:

1
2
3
4
5
#在创建之前需要决定你集群的副本数,假设我这里是测试环境,所以只创建一个副本,如果是生产环境建议至少3个副本
#prometheus副本数在 prometheus-prometheus.yaml配置文件中修改
#主要是副本数和镜像下载地址的配置:
image: quay.io/prometheus/alertmanager:v0.27.0 #如果自己有镜像仓库可以改为自己的仓库地址,下图已经修改为我自己的镜像仓库地址了
replicas: 3 #根据实际情况修改副本的数量,我配置的是1

修改kubeStateMetrics-deployment.yaml配置文件中镜像的下载地址:

1
# kubeStateMetrics-deployment.yaml配置文件中的镜像地址我改为我自己的仓库地址,事先已经将镜像同步到自己的仓库中


接下来安装prometheus的技术栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#注意所在目录manifests
[root@k8s-master01 manifests]# pwd
/root/pra/17-prometheus/kube-prometheus/manifests

#安装prometheus技术栈
[root@k8s-master01 manifests]# kubectl create -f .


[root@k8s-master01 manifests]# kubectl get po -n monitoring
NAME READY STATUS RESTARTS AGE
alertmanager-main-0 0/2 Init:0/1 0 9m54s
blackbox-exporter-75c7985cb8-xkxrs 0/3 ContainerCreating 0 11m
grafana-664dd67585-mh7tb 0/1 ImagePullBackOff 0 11m
kube-state-metrics-bbcd9ff4f-8c5vq 0/3 ContainerCreating 0 11m
node-exporter-7b428 2/2 Running 0 11m
node-exporter-m2g8z 2/2 Running 0 11m
node-exporter-nvpz5 2/2 Running 0 11m
node-exporter-w7lrs 2/2 Running 0 11m
node-exporter-wwtnm 0/2 ContainerCreating 0 11m
prometheus-adapter-77f8587965-5x7bn 0/1 ImagePullBackOff 0 11m
prometheus-adapter-77f8587965-wgp55 0/1 ImagePullBackOff 0 11m
prometheus-k8s-0 0/2 Init:0/1 0 9m54s
prometheus-operator-6f9479b5f5-4zpfm 2/2 Running 0 11m

虽然上述三个配置文件修改了镜像的下载地址,但是查看pod会发现还是会有一些pod由于镜像地址的问题无法启动pod,接下继续修改无法启动pod的那些镜像地址:

思路一:通过describe查看无法启动的pod使用的镜像是什么,然后利用github同步到我自己的阿里云仓库中,在把配置文件中的镜像地址修改为我自己的阿里云仓库地址。(这里就不演示了)

1
2
3
4
5
#下面是几个pod的资源配置所在的文件
blackbox-exporter-75c7985cb8-xkxrs的镜像在blackboxExporter-deployment.yaml文件中
grafana-664dd67585-mh7tb 的镜像在grafana-deployment.yaml文件中
prometheus-adapter-77f8587965-5x7bn的镜像在prometheusAdapter-deployment.yaml文件中
node-exporter-w7lrs的镜像在nodeExporter-daemonset.yaml文件中

思路二:也可以通过在线编辑的方法直接修改镜像地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#用prometheus-adapter-77f8587965-5x7bn举例
[root@k8s-master01 manifests]# kubectl edit pod -n monitoring prometheus-adapter-77f8587965-5x7bn
#找到spec.containers.image参数,修改为自己的镜像仓库(前提是已经将镜像同步到自己的仓库中了)
42 image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/prometheus-adapter:v0.12.0

#修改后保存退出,程序会自动更新配置,再次检查pod,已经正常运行
[root@k8s-master01 manifests]# kubectl get pod -n monitoring
NAME READY STATUS RESTARTS AGE
alertmanager-main-0 2/2 Running 0 15h
blackbox-exporter-75c7985cb8-xkxrs 3/3 Running 0 15h
grafana-664dd67585-mh7tb 1/1 Running 0 15h
kube-state-metrics-bbcd9ff4f-8c5vq 3/3 Running 0 15h
node-exporter-7b428 2/2 Running 0 15h
node-exporter-m2g8z 2/2 Running 0 15h
node-exporter-nvpz5 2/2 Running 0 15h
node-exporter-w7lrs 2/2 Running 0 15h
node-exporter-wwtnm 2/2 Running 0 15h
prometheus-adapter-77f8587965-5x7bn 1/1 Running 0 15h
prometheus-adapter-77f8587965-wgp55 1/1 Running 0 15h
prometheus-k8s-0 2/2 Running 0 12h
prometheus-operator-6f9479b5f5-4zpfm 2/2 Running 0 15h


#让我们来详细解释一下这些 Pod 的功能和作用:
1.prometheus-operator-6f9479b5f5-4zpfm:这是整个 Prometheus 监控栈的控制器,负责管理和维护 Prometheus 相关的自定义资源(CRD),自动化部署和管理 Prometheus 实例、配置等

2.prometheus-k8s-0:核心的 Prometheus 服务器实例,负责收集、存储时序数据,执行数据查询和告警规则评估

3.alertmanager-main-0:负责告警管理和通知,处理来自 Prometheus 的告警,提供告警分组、抑制、静默等功能,支持多种通知方式(邮件、Slack、webhook等)

4.grafana-664dd67585-mh7tb:可视化平台,提供丰富的数据可视化界面,支持创建各种监控面板,可以展示 Prometheus 采集的数据

5.node-exporter-*(多个实例):部署在每个节点上的数据采集器,收集主机级别的监控指标,如:CPU、内存、磁盘、网络等系统层面的数据

6.kube-state-metrics-bbcd9ff4f-8c5vq:收集 Kubernetes 对象的状态指标,监控 Pod、Deployment、StatefulSet 等资源的状态,提供集群层面的监控数据

7.blackbox-exporter-75c7985cb8-xkxrs:用于探测服务的可用性,支持 HTTP、HTTPS、DNS、TCP、ICMP 等协议探测,可以监控服务的响应时间、可用性等

8.prometheus-adapter-77f8587965-*(两个实例):实现了自定义指标 API,使 Kubernetes HPA 可以使用 Prometheus 指标进行自动扩缩容,将 Prometheus 指标转换为 Kubernetes 可用的指标格式

#这些组件协同工作形成了一个完整的监控体系:
node-exporter 收集每个节点的系统级别资源的数据。
kube-state-metrics 采集 Kubernetes 资源的状态数据。
blackbox-exporter 用于探测外部服务的可用性。
Prometheus :采集和存储指标数据。
Alertmanager 处理和分发告警。
Grafana 提供指标的可视化展示。
Prometheus Operator 管理整个监控栈,管理和部署 Prometheus 及其相关组件。
Prometheus Adapter 将 Prometheus 指标数据暴露给 Kubernetes HPA,用于自动伸缩。使监控指标可用于集群的自动化运维。
#这样的架构既能监控基础设施,也能监控应用服务,同时支持告警和可视化,是一个非常完整的监控解决方案。

3.访问Grafana和Prometheus

新版本添加了NetworkPolicy,导致无法访问Grafana和Prometheus等服务,执行删除即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@k8s-master01 manifests]# kubectl delete  networkpolicy --all  -n monitoring
networkpolicy.networking.k8s.io "alertmanager-main" deleted
networkpolicy.networking.k8s.io "blackbox-exporter" deleted
networkpolicy.networking.k8s.io "grafana" deleted
networkpolicy.networking.k8s.io "kube-state-metrics" deleted
networkpolicy.networking.k8s.io "node-exporter" deleted
networkpolicy.networking.k8s.io "prometheus-adapter" deleted
networkpolicy.networking.k8s.io "prometheus-k8s" deleted
networkpolicy.networking.k8s.io "prometheus-operator" deleted

#再次查看已经没有相关资源
[root@k8s-master01 manifests]# kubectl get networkpolicy -n monitoring
No resources found in monitoring namespace.

将alertmanager-main、grafana、prometheus-k8s三个Service改成NodePort类型:

将Grafana的Service改成NodePort类型:

1
2
3
4
5
6
7
8
9
10
11
12
[root@k8s-master01 manifests]# kubectl edit svc -n monitoring  grafana
apiVersion: v1
kind: Service
...
selector:
app.kubernetes.io/component: grafana
app.kubernetes.io/name: grafana
app.kubernetes.io/part-of: kube-prometheus
sessionAffinity: None
type: NodePort #将type的原值ClusterIP改为NodePort
status:
loadBalancer: {}

查看Grafana的Service暴露的端口,通过该端口访问grafana:

1
2
3
4
#grafana的NodePort为30391
[root@k8s-master01 manifests]# kubectl get svc -n monitoring grafana
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana NodePort 10.96.250.130 <none> 3000:30391/TCP 20h

之后可以通过任意一个安装了kube-proxy服务的节点IP+32293端口即可访问到Grafana,如果浏览器无法访问执行删除网络策略:

1
2
3
4
5
6
7
8
9
10
#删除网络策略
[root@k8s-master01 manifests]# kubectl delete networkpolicy --all -n monitoring
networkpolicy.networking.k8s.io "alertmanager-main" deleted
networkpolicy.networking.k8s.io "blackbox-exporter" deleted
networkpolicy.networking.k8s.io "grafana" deleted
networkpolicy.networking.k8s.io "kube-state-metrics" deleted
networkpolicy.networking.k8s.io "node-exporter" deleted
networkpolicy.networking.k8s.io "prometheus-adapter" deleted
networkpolicy.networking.k8s.io "prometheus-k8s" deleted
networkpolicy.networking.k8s.io "prometheus-operator" deleted

Grafana默认登录的账号密码为admin/admin。

首次登录会提示更改密码,如果不修改点击skip跳过即可。

简单体验导入监控模板:

访问grafana页面,http://192.168.0.200:32293/?orgId=1

通过https://grafana.com/grafana/dashboards官方地址,输入关键字[Linux主机详情] 找适合的监控模板:

复制模板的连接,在http://192.168.0.200:32293/?orgId=1中导入模板:

复制模板连接:

在grafana控制台导入-输入模板连接后点击[加载]:


导入后监控数据显示如下:

可以创建不同类型的文件夹,在文件夹中导入监控模板:

然后相同的方式更改Prometheus的Service为NodePort:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@k8s-master01 manifests]# kubectl edit svc -n monitoring prometheus-k8s
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2024-11-12T10:34:08Z"
labels:
app.kubernetes.io/component: prometheus
...
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
type: NodePort #修改type的值为NodePort
status:
loadBalancer: {}

[root@k8s-master01 manifests]# kubectl get svc -n monitoring prometheus-k8s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
prometheus-k8s NodePort 10.96.250.138 <none> 9090:31470/TCP,8080:30887/TCP 22h

通过31470端口即可访问到Prometheus的WebUI:

默认安装完成后,会有几个告警,先忽略。

该页面默认是不需要登录的,如果需要在生产环境访问,可以利用ingress代理配置账号密码!

17.5云原生和非云原生应用的监控流程

1.Prometheus的数据来源

基于云原生理念开发的程序会暴露 /metrics接口(中文意思是度量,指标的意思),提供各项监控指标的数据

非云原生开发的程序需要安装 Exporter (中文意思是出口,输出),提供各项监控指标的数据

常用的Exporter工具

类型 Exporter
数据库 MySQL Exporter, Redis Exporter, MongoDB Exporter, MSSQL Exporter
硬件 Apcupsd Exporter,IoT Edison Exporter, IPMI Exporter, Node Exporte
消息队列 Beanstalkd Exporter, Kafka Exporter, NSQ Exporter, RabbitMQ Exporter
存储 Ceph Exporter, Gluster Exporter, HDFS Exporter, ScaleIO Exporter
HTTP服务 Apache Exporter, HAProxy Exporter, Nginx Exporter
API服务 AWS ECS Exporter, Docker Cloud Exporter, Docker Hub Exporter, GitHub Exporter
监控系统 Collectd Exporter, Graphite Exporter, InfluxDB Exporter, Nagios Exporter, SNMP Exporter
其他 Blackbox Exporter, JIRA Exporter, Jenkins Exporter, Confluence Exporter

2.Prometheus如何拿到监控数据

当云原生应用metrics接口和 非云原生exporter 提供监控数据,Prometheus是如何拿到这些监控数据的呢?

利用一个叫ServiceMonitor 的资源来拿到监控数据。下面介绍ServiceMonitor :

ServiceMonitor 是 Prometheus Operator 提供的一个自定义资源(Custom Resource Definition, CRD),专门用于在 Kubernetes 中配置和管理 Prometheus 监控目标的方式ServiceMonitor 通过声明式配置,简化了 Kubernetes 环境中的监控设置,不再需要手动修改 Prometheus 的配置文件。它可以帮助 Prometheus 自动发现 Kubernetes 中的 Service,从而采集应用的监控数据。

ServiceMonitor配置解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#下面是一个基本的配置,能满足大多数场景,让我们来解析每个参数的意思
kind: ServiceMonitor #声明这是一个 ServiceMonitor 资源对象
apiVersion: monitoring.coreos.com/v1 #指定使用 monitoring.coreos.com/v1 API 版本
metadata: #定义资源的元数据,包含一些与资源相关的基本信息,如名称、命名空间和标签。
name: es-monitor #定义这个ServiceMonitor资源的名字是es-monitor
namespace: monitoring #指定该资源将部署在 "monitoring" 命名空间中
labels: #为该ServiceMonitor添加标签
app: elasticsearch #标签的具体key和value
k8s-app: elasticsearch-exporter #标签的具体key和value
spec: # 定义了 ServiceMonitor 的详细配置,用来指定如何发现服务和采集数据。
endpoints: #定义了服务暴露的监控指标的端点配置(也就是被监控端的配置)。Prometheus 通过这些信息来获取服务的监控数据。
- port: http #指定要监控的端口名称为 "http";Prometheus 会从名为 http 的端口拉取数据。这个端口指向的是 Service 中定义的端口名称(portName)
honorLabels: true #设置为 true,表示保留原始标签,Prometheus 会保留从服务暴露的 metrics 端点拉取到的原始标签,这对于进一步的数据分析和查询非常有用,确保不会丢失重要的标签信息。
path: /metrics #指定获取指标数据的接口路径为 "/metrics",通常这是所有支持 Prometheus 格式的服务会暴露的指标路径。
scheme: http #该配置指定了访问端点时使用 HTTP 协议。如果你的服务支持 HTTPS,则可以将其设置为 https。
interval: 10s #指定 Prometheus 每次拉取指标的时间间隔。
jobLabel: es-exporter #Prometheus 使用这个标签 es-exporter 来标识这个采集任务。这对于多任务或多作业的环境中,帮助区分不同的监控任务。也可以不配置该参数
selector: #指定Prometheus 从哪些 Service 中采集数据,类似于标签选择器。
matchLabels: #标签选择器,也就是从下面定义的标签中查找service来采集数据
app: elasticsearch #
namespaceSelector: #命名空间选择器,也就是定义从哪个命名空间查找service
matchNames: #定义命名空间
- monitoring #命名空间的名字是monitoring,意思是从该命名空间匹配带标签是 app: elasticsearch 的service采集数据

3.Prometheus监控流程

第十八章、云原生监控Prometheus实践

18.1云原生应用监控-Etcd

Etcd属于云原生应用,是k8s核心组件之一,它自带了/metrics接口:

1
2
3
4
5
6
7
#在安装了etcd组件的服务器上 查看etcd服务的端口,以k8s-master01为例:
[root@k8s-master01 manifests]# netstat -lntup|grep etcd
tcp 0 0 192.168.0.200:2379 0.0.0.0:* LISTEN 1084/etcd
tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN 1084/etcd
tcp 0 0 192.168.0.200:2380 0.0.0.0:* LISTEN 1084/etcd
#etcd 目前默认使用2379端口提供HTTP API服务,2380端口和peer通信(这两个端口已经被IANA(互联网数字分配机构)官方预留给etcd)。 即etcd默认使用2379端口对外为客户端提供通讯,使用端口2380来进行服务器间内部通讯。
#如果是监控etcd指标,则需要跟2379端口通信

访问etcd的metrics接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#本地访问可以使用http,但是Prometheus不能用127.0.0.1,只能通过192.168.0.200:2379访问,所以需要带着etcd的证书访问才会有数据返回
#本地访问
[root@k8s-master01 manifests]# curl 127.0.0.1:2379/metrics
....
# HELP etcd_debugging_disk_backend_commit_write_duration_seconds The latency distributions of commit.write called by bboltdb backend.
# TYPE etcd_debugging_disk_backend_commit_write_duration_seconds histogram
etcd_debugging_disk_backend_commit_write_duration_seconds_bucket{le="0.001"} 91885
etcd_debugging_disk_backend_commit_write_duration_seconds_bucket{le="0.002"} 155332
etcd_debugging_disk_backend_commit_write_duration_seconds_bucket{le="0.004"} 215254

#证书访问
[root@k8s-master01 etcd-service-monitor]# curl -s --cacert /etc/kubernetes/pki/etcd/etcd-ca.pem --cert /etc/kubernetes/pki/etcd/etcd.pem --key /etc/kubernetes/pki/etcd/etcd-key.pem https://192.168.0.200:2379/metrics
#如何查找自己etcd的证书?
#证书的位置可以在 Etcd 配置文件中获得(注意配置文件的位置,不同的集群位置可能不同,
#Kubeadm 安装方式可能会在/etc/kubernetes/manifests/etcd.yml 中):

#二进制安装方式,执行systemctl status etcd命令,找到配置文件--config-file=/etc/etcd/etcd.config.yml
#在/etc/etcd/etcd.config.yml文件中查看证书的路径
#可以使用命令过滤出来:
[root@k8s-master01 etcd-service-monitor]# grep -E "key-file|cert-file|trusted-ca-file" /etc/etcd/etcd.config.yml
cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'
cert-file: '/etc/kubernetes/pki/etcd/etcd.pem'
key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem'
trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem'

#也可以cat配置文件查看:
[root@k8s-master01 manifests]# cat /etc/etcd/etcd.config.yml


使用带参数的指令获取etcd监控指标:

1
2
3
4
5
6
7
8
9
[root@k8s-master01 manifests]# curl  -s --cacert /etc/kubernetes/pki/etcd/etcd-ca.pem --cert /etc/kubernetes/pki/etcd/etcd.pem  --key /etc/kubernetes/pki/etcd/etcd-key.pem https://192.168.0.200:2379/metrics
#结果如下:
....
# TYPE process_open_fds gauge
process_open_fds 335
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
promhttp_metric_handler_requests_total{code="200"} 6
promhttp_metric_handler_requests_total{code="500"} 0

二进制安装的etcd没有自动为我们创建etcd的service,需要我们手动创建etcd的service:

1.创建etcd的service

针对云原生应用etcd,需要创建Service,Endpoints 和ServiceMonitor资源

创建Etcd的Service和Endpoints :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#编写资源配置
[root@k8s-master01 etcd-service-monitor]# vim etcd-service.yaml
#假如下面配置内容
apiVersion: v1 # Service的API版本
kind: Service # 定义资源的类型,这里是Service
metadata: # 定义资源的元数据
name: etcd-monitoring # Service的名称,如果需要手动配置endpoints,这个service名称必须与endpoints的名称相同
namespace: kube-system # 定义资源所在的命名空间。
labels: # 定义资源的标签,这里建议和Endpoints 资源的标签保持一致
k8s-app: etcd
component: etcd
spec: # 定义资源的具体规格
type: ClusterIP # 集群内部访问的service类型
ports: # 定义Service的端口
- name: metrics # metrics端口名称,需要和后面的 ServiceMonitor 保持一致
port: 2379 # 定义Service暴露的端口
protocol: TCP # 使用TCP协议,默认值,不加该参数也可以
targetPort: 2379 # etcd服务的实际监听端口,和Endpoints.subsets.ports.port的端口保持一致
---
# 配套的Endpoints配置(如果etcd是静态部署的(比如直接部署在主机上),需要手动配置Endpoints)
apiVersion: v1 # Endpoints的API版本
kind: Endpoints # Endpoints类型 ,创建的资源类型是Endpoints
metadata: #定义资源的元数据
name: etcd-monitoring # Endpoints的名称,必须与Service的名称相同
namespace: kube-system # Endpoints所在的命名空间 ,必须与Service的命名空间相同。
labels: # Endpoints的标签,最好与Service的标签相同
k8s-app: etcd
component: etcd
subsets: # Endpoints的子集,定义了每个Endpoint的地址和端口,必须与Service的端口相同。
- addresses: # 定义Endpoint的地址,可以是Pod的IP地址,也可以是其他服务或节点的IP地址
- ip: "192.168.0.200" # 替换为实际的etcd节点IP,有几个节点就写几个IP
- ip: "192.168.0.201"
- ip: "192.168.0.202"
ports: # 定义Endpoint的端口,必须与Service的端口相同。
- name: metrics # metrics端口名称,和service中.sepc.ports.name字段保持一致
port: 2379 # 以实际外部服务etcd监听端口为准
protocol: TCP # 使用TCP协议,默认值,不加该参数也可以


-------------------
在手动创建Service和Endpoints时需要注意以下问题:
Service.metadata.name 和 Endpoints.metadata.name 的值必须相同
Service.metadata.namespace 和 Endpoints.metadata.namespace 的值必须相同
Service.metadata.labels 和 Endpoints.metadata.labels 的值可以不相同,但是为了方便建议相同
Service.spec.ports.name 和 Endpoints.subsets.ports.name 的值必须保持一致
Service.spec.ports.targetPort 和 Endpoints.subsets.ports.port 的值必须保持一致
Service.spec.ports.protocol 和 Endpoints.subsets.ports.protocol 的值必须保持一致
Endpoints.subsets.ports.port的端口是由实际服务监听的端口号决定,例如MySQL实际监听3306端口,这个就应该配置3306
Service.spec.ports.targetPort的端口号由Endpoints.subsets.ports.port决定,所以两个保持一致
Service.spec.ports.port是自定义的service对外暴露的端口号,这个可以自己定义,也可以和targetPort保持一致
-------------------

创建该资源并查看 Service 的 ClusterIP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#创建前先看下kube-system命名空间是没有相应的资源
[root@k8s-master01 etcd-service-monitor]# kubectl get service -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 144d
kubelet ClusterIP None <none> 10250/TCP,10255/TCP,4194/TCP 2d20h
metrics-server ClusterIP 10.96.78.88 <none> 443/TCP 144d
snapshot-controller ClusterIP 10.96.85.201 <none> 80/TCP 51d
#创建资源
[root@k8s-master01 etcd-service-monitor]# kubectl create -f etcd-service.yaml
service/etcd-monitoring created
endpoints/etcd-monitoring created

#创建后可以看到在 kube-system命名空间etcd-monitoring 名字的service
[root@k8s-master01 etcd-service-monitor]# kubectl get service -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
etcd-monitoring ClusterIP 10.96.8.216 <none> 2379/TCP 32s
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 144d
kubelet ClusterIP None <none> 10250/TCP,10255/TCP,4194/TCP 2d20h
metrics-server ClusterIP 10.96.78.88 <none> 443/TCP 144d
snapshot-controller ClusterIP 10.96.85.201 <none> 80/TCP 51d

[root@k8s-master01 etcd-service-monitor]# kubectl get -f etcd-service.yaml
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/etcd-monitoring ClusterIP 10.96.8.216 <none> 2379/TCP 6s

NAME ENDPOINTS AGE
endpoints/etcd-monitoring 192.168.0.200:2379,192.168.0.201:2379,192.168.0.202:2379 6s

通过ClusterIP进行访问测试:

1
2
3
4
5
6
[root@k8s-master01 etcd-service-monitor]# curl  -s --cacert /etc/kubernetes/pki/etcd/etcd-ca.pem --cert /etc/kubernetes/pki/etcd/etcd.pem  --key /etc/kubernetes/pki/etcd/etcd-key.pem https://10.96.8.216:2379/metrics -k|tail -5
# HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code.
# TYPE promhttp_metric_handler_requests_total counter
promhttp_metric_handler_requests_total{code="200"} 2
promhttp_metric_handler_requests_total{code="500"} 0
promhttp_metric_handler_requests_total{code="503"} 0

接下来创建 Etcd 证书的 Secret(证书路径根据实际环境进行更改):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#创建etcd的secret,将这个secret挂载到prometheus的pod中,因为prometheus请求etcd的metrics接口需要证书,secret有命名空间隔离性,需要跟prometheus的pod在同一个命名空间中
[root@k8s-master01 etcd-service-monitor]# kubectl create secret generic etcd-ssl \
--from-file=/etc/kubernetes/pki/etcd/etcd-ca.pem \
--from-file=/etc/kubernetes/pki/etcd/etcd.pem \
--from-file=/etc/kubernetes/pki/etcd/etcd-key.pem -n monitoring
#命令解释:
kubectl:Kubernetes 命令行工具,用于与 Kubernetes API 进行交互。
create secret:kubectl 子命令,用于创建 Secret 资源。Secret 用于在 Kubernetes 中安全地存储敏感信息,比如密码、证书、密钥等。
generic:表示创建一个“通用”类型的 Secret(即 Opaque 类型),可以存储任意数据。
etcd-ssl:创建的Secret名称,名字是etcd-ssl。这个名称用于标识这个 Secret,后续引用这个 Secret 时可以使用该名称。
-n monitoring::指定 Secret 创建到的命名空间(namespace)。在这里,将 Secret 创建在 monitoring 命名空间下,这样只有该命名空间中的 Pod 或应用能够引用和访问此 Secret
--from-file:用于将文件中的内容作为 Secret 的数据存储。可以多次使用此参数添加多个文件。
etcd-ca.pem 文件是 etcd 的 CA(Certificate Authority,证书颁发机构)证书,用于验证证书链的可信度
etcd.pem 文件是 etcd 服务端的 SSL 证书,用于身份验证。
etcd-key.pem 文件是 etcd 的私钥,用于加密和解密与 etcd 的 SSL 通信。

将证书挂载至 Prometheus 容器(由于 Prometheus 是 Operator 部署的,所以只需要修改Prometheus 资源即可):

1
2
3
4
5
6
7
8
9
10
#Prometheus资源是 Prometheus Operator 所管理的自定义资源(Custom Resource,CR)
[root@k8s-master01 etcd-service-monitor]# kubectl get prometheus -n monitoring
NAME VERSION DESIRED READY RECONCILED AVAILABLE AGE
k8s 2.54.1 1 1 True True 3d

#编辑名字是k8s的prometheus资源
[root@k8s-master01 etcd-service-monitor]# kubectl edit prometheus k8s -n monitoring
#在spec级别下添加证书配置
secrets:
- etcd-ssl

保存退出后,Prometheus 的 Pod (prometheus-k8s-0)会自动重启,重启完成后,查看证书是否挂载(任意一个Prometheus 的 Pod 均可):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@k8s-master01 etcd-service-monitor]# kubectl get po -n monitoring
NAME READY STATUS RESTARTS AGE
alertmanager-main-0 2/2 Running 4 (12m ago) 3d3h
blackbox-exporter-75c7985cb8-xkxrs 3/3 Running 6 (12m ago) 3d3h
grafana-75dcfd79-sk29h 1/1 Running 1 (12m ago) 2d5h
kube-state-metrics-bbcd9ff4f-8c5vq 3/3 Running 7 (9m34s ago) 3d3h
node-exporter-7b428 2/2 Running 2 (11m ago) 3d3h
node-exporter-m2g8z 2/2 Running 2 (11m ago) 3d3h
node-exporter-nvpz5 2/2 Running 2 (11m ago) 3d3h
node-exporter-w7lrs 2/2 Running 2 (12m ago) 3d3h
node-exporter-wwtnm 2/2 Running 4 (12m ago) 3d3h
prometheus-adapter-77f8587965-5x7bn 1/1 Running 4 (10m ago) 3d3h
prometheus-adapter-77f8587965-wgp55 1/1 Running 2 (9m38s ago) 3d3h
prometheus-k8s-0 0/2 Init:0/1 0 2s
prometheus-operator-6f9479b5f5-4zpfm 2/2 Running 3 (9m48s ago) 3d3h

#待pod重启完成,进入prometheus-k8s-0的pod中验证证书是否挂载成功:
[root@k8s-master01 etcd-service-monitor]# kubectl exec -ti -n monitoring prometheus-k8s-0 -c prometheus -- sh
/prometheus $
/prometheus $ ls -l /etc/prometheus/secrets/etcd-ssl/ #证书已经成功挂载
total 0
lrwxrwxrwx 1 root 2000 18 Nov 15 13:39 etcd-ca.pem -> ..data/etcd-ca.pem
lrwxrwxrwx 1 root 2000 19 Nov 15 13:39 etcd-key.pem -> ..data/etcd-key.pem
lrwxrwxrwx 1 root 2000 15 Nov 15 13:39 etcd.pem -> ..data/etcd.pem

2.创建ServiceMonitor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#配置ServiceMonitor并介绍配置参数
[root@k8s-master01 etcd-service-monitor]# vim etcd-servicemonitor.yaml
#ServiceMonitor资源配置内容如下:
kind: ServiceMonitor #定义资源类型为 ServiceMonitor,这是用于 Prometheus Operator 中监控服务的资源类型。
apiVersion: monitoring.coreos.com/v1 #该字段指定了 API 的版本,monitoring.coreos.com/v1 是 ServiceMonitor 的标准 API 版本。
metadata: #定义该资源的元数据部分,用于定义资源的名称和标签命名空间等信息。
name: etcd-servicemonitor #定义该 ServiceMonitor 资源的名称为 etcd-servicemonitor。
namespace: monitoring #定义该 ServiceMonitor 资源所在的命名空间为 monitoring。
labels: #定义该 ServiceMonitor 资源的标签,用于标识该资源。
app: etcd-servicemonitor #标签的键为 app,值为 etcd-servicemonitor。Prometheus(由 Prometheus Operator 管理)通过 .spec.serviceMonitorSelector 字段来决定:“我只监控那些带有特定标签的 ServiceMonitor” 。因为在prometheus资源中"serviceMonitorSelector: {}" 定义了空选择器,空选择器匹配所有资源。(kubectl get prometheus -n monitoring k8s -oyaml|grep serviceMonitorSelector) 如果Prometheus的.spec.serviceMonitorSelector不是空选择器,那么ServiceMonitor这里定义的标签就要和Prometheus的.spec.serviceMonitorSelector中定义的标签保持一致。
spec: #定义该 ServiceMonitor 资源的具体配置。
jobLabel: etcd #指定从 Service 的标签中获取的作业名称标签,使用 Service 中 key 为 "etcd" 的标签值作为 job 名称,etcd这个值是Service中定义的标签key。
namespaceSelector: #命名空间选择器,用于指定监控哪些命名空间下的 Service。
matchNames: #名字空间匹配列表,从该列表中定义的命名空间下找目标 Service。
- kube-system #找kube-system 命名空间下的 Service。
selector: #选择器,用于指定监控哪些 Service。
matchLabels: #标签匹配器
etcd: monitoring #找标签是app=etcd的Service。也就是从namespaceSelector.matchNames中定义的命名空间下,选择标签是app=etcd的Service。
endpoints: #定义监控的目标端点。
- port: metrics #这个port字段的值对应 Service.spec.ports.name的值保持一致,必须与 Service 的定义一致。
interval: 30s #配置 Prometheus 拉取该服务指标的间隔时间,表示每 30 秒拉取一次。
scheme: https #设置请求协议为 https。如果其他服务不需要证书验证,可以设置为 http。
tlsConfig: #配置 TLS 证书验证。
caFile: /etc/prometheus/secrets/etcd-ssl/etcd-ca.pem #指定 CA 证书文件的路径, 这个路径Prometheus 容器内的路径,而不是 Kubernetes 主机的路径。
certFile: /etc/prometheus/secrets/etcd-ssl/etcd.pem #指定客户端证书文件的路径。这个路径Prometheus 容器内的路径,而不是 Kubernetes 主机的路径。
keyFile: /etc/prometheus/secrets/etcd-ssl/etcd-key.pem #指定客户端私钥文件的路径。这个路径Prometheus 容器内的路径,而不是 Kubernetes 主机的路径。
insecureSkipVerify: true #是否跳过证书验证,true 表示跳过,false 表示不跳过。如果你在开发/测试环境中使用自签名证书,这个可以设置为 true,但在生产环境中建议为 false。

----------------------------------------------
#配置ServiceMonitor资源时产生的疑问解答:
背景:prometheus相关的pod服务是部署在monitoring命名空间中,而要监控的etcd是二进制安装的服务,为etcd创建的service是在kube-system命名空间中,为etcd的service配置的ServiceMonitor资源是部署在monitoring命名空间中。

问题1:ServiceMonitor 与 Prometheus 的关系:ServiceMonitor 不需要与 Prometheus Pod 在同一个命名空间,Prometheus 可以发现并使用不同命名空间中的 ServiceMonitor,关键是要在 Prometheus CR (Custom Resource) 中正确配置,serviceMonitorNamespaceSelector 和 serviceMonitorSelector

问题2:ServiceMonitor 与被监控 Service 的关系:ServiceMonitor 不需要与被监控的 Service 在同一个命名空间,通过 ServiceMonitor资源中的namespaceSelector 字段可以指定要监控的 Service 所在的命名空间,可以监控多个命名空间中的 Service

问题3:ServiceMonitor资源的配置中spec.jobLabel的使用:
# Service 配置
apiVersion: v1
kind: Service
metadata:
name: etcd-service
labels:
etcd: monitoring # 这个标签将被用作 job 名称,标签的key作为ServiceMonitor.spec.jobLabel的名称
...
---
# ServiceMonitor 配置
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: etcd-monitor
spec:
jobLabel: etcd # 使用 Service 中 key 为 "etcd" 的标签值作为 job 名称
selector:
matchLabels:
etcd: monitoring

#这样配置在 Prometheus 中的表现为:
# 没有配置 jobLabel 时
my_metric{job="etcd-service", ...}

# 配置了 jobLabel: etcd 后
my_metric{job="monitoring", ...}

#使用场景:当你需要自定义 Prometheus 中显示的 job 名称时
# 想要使用 Service 中的特定标签作为作业标识时
# 在有多个相同类型服务时,需要区分不同实例的监控数据

问题4:ServiceMonitor中tlsConfig的作用:
#ServiceMonitor 资源中的 tlsConfig 是用来配置 Prometheus 与目标服务(例如 etcd 服务)之间的 TLS/SSL 安全连接的。具体而言,tlsConfig 用来指定 Prometheus 在抓取目标服务的 /metrics 端点时,如何处理 HTTPS 请求的证书校验和加密配置。tlsConfig中配置的证书文件是 Prometheus 容器内的路径,而不是 Kubernetes 宿主机的路径。
#caFile这是 Prometheus 用于验证 etcd 服务端证书的 CA 证书 (Certificate Authority)
#certFile这是 Prometheus 客户端使用的证书文件,用于客户端认证。
#keyFile这是 Prometheus 客户端的私钥文件,配合 certFile 来进行客户端认证。。

问题5:已经在Prometheus的pod中挂载了证书文件为什么还要在ServiceMonitor中配置tlsConfig?:
#答:在 Prometheus 中挂载了相关的证书 和 在 ServiceMonitor 中配置 tlsConfig 是两个不同的概念,虽然它们看似相关,但它们的目的和作用是不同的。让我们深入理解为什么即使证书已经挂载到 Prometheus 中,仍然需要在 ServiceMonitor 中配置 tlsConfig。Prometheus 中挂载的证书的作用:挂载的目的仅仅是将证书文件放置在 Prometheus 容器的文件系统中,供 Prometheus 使用。证书文件可以被 Prometheus 访问使用,但 Prometheus 不会自动知道每个抓取任务应该如何使用这些证书,除非你在 ServiceMonitor 中明确指定。tlsConfig 是 ServiceMonitor 的一部分,用于配置 Prometheus 在抓取 HTTPS 端点时,如何使用证书处理 TLS/SSL 协议、证书校验和客户端认证。换句话说就是当你有多个服务需要使用证书进行通信时,需要将每个服务的证书都挂载到Prometheus的容器中,这时Prometheus并不知道哪个服务应该使用哪个证书,这是就需要在ServiceMonitor定义tlsConfig来告诉Prometheus如何使用证书,所以这两个配置缺一不可:①证书挂载:提供文件访问能力;②tlsConfig:指导证书使用方式

创建这个ServiceMonitor资源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#创建资源
[root@k8s-master01 etcd-service-monitor]# kubectl create -f etcd-servicemonitor.yaml
servicemonitor.monitoring.coreos.com/etcd-servicemonitor created

#查看资源创建情况etcd-servicemonitor
[root@k8s-master01 etcd-service-monitor]# kubectl get servicemonitors.monitoring.coreos.com -n monitoring
NAME AGE
alertmanager-main 3d4h
blackbox-exporter 3d4h
coredns 3d4h
etcd-servicemonitor 14s
grafana 3d4h
kube-apiserver 3d4h
kube-controller-manager 3d4h
kube-scheduler 3d4h
kube-state-metrics 3d4h
kubelet 3d4h
node-exporter 3d4h
prometheus-adapter 3d4h
prometheus-k8s 3d4h
prometheus-operator 3d4h

通过prometheus的service暴露的端口在网页端查看是否存在etcd的监控:

点击页面的[Status]—[Targets]

按照下图的选择,能看到配置的ServiceMonitor资源名称(etcd-servicemonitor),则说明配置的正确。

3.Grafana配置etcd监控模板

接下来打开Grafana,添加 Etcd 的监控面板:

首先去https://grafana.com/grafana/dashboards找合适的模板:输入条件,在结果中找适合自己的模板。

以下图中的模板为例:打开模板复制连接(https://grafana.com/grafana/dashboards/9733-etcd-for-k8s-cn/),在grafana的控制台中添加:

在grafana中新建模板:【导入模板】-【加载模板链接】-【自定义模板名字】-【选择数据源】-点击【import】即可导入。

配置完成后可以看到下图的监控指标:

18.2非云原生监控

本节将使用 MySQL 作为一个测试用例,演示如何使用 Exporter 监控非云原生应用。

如果已经有现成的mysql就不需要创建了,我这里是没有,所以部署一个用于测试的MySQL实例来演示。

1.部署测试实例

直接部署一个MySQL服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#简单运行一个mysql的deployment服务,该命令不适用生产环境
[root@k8s-master01 ~]# kubectl create deployment mysql --image=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/mysql:5.7.44

#此时pod状态是error,pod无法重启
[root@k8s-master01 ~]# kubectl logs mysql-689b5868c8-vpqfz -c mysql
2024-11-16 13:00:02+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.44-1.el7 started.
2024-11-16 13:00:02+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2024-11-16 13:00:02+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.44-1.el7 started.
2024-11-16 13:00:02+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
You need to specify one of the following as an environment variable:
- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD

#设置mysql的密码,否则pod是不能正常启动的
[root@k8s-master01 ~]# kubectl set env deployment mysql MYSQL_ROOT_PASSWORD=mysql
deployment.apps/mysql env updated

#查看pod的状态是否正常
[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
mysql-85d75646bc-9nw68 1/1 Running 0 23s

2.为MySQL服务创建service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#可以使用命令为deployment创建一个service
[root@k8s-master01 ~]# kubectl expose deploy mysql --port 3306
service/mysql exposed
# kubectl get svc -l ap
也可以通过编写yaml文件:
kind: Service
apiVersion: v1
metadata:
name: mysql-service
labels:
app: mysql
spec:
type: ClusterIP
ports:
- name: mysql
port: 3306
targetPort: 3306
selector:
app: mysql

命令和yaml的方式二选一即可。

检查service是否可用:

1
2
3
4
5
6
7
[root@k8s-master01 etcd-service-monitor]# telnet 10.96.150.170 3306
Trying 10.96.150.170...
Connected to 10.96.150.170.
Escape character is '^]'.
J
5.7.446d0t'4OyA!&CYVE%Dmysql_native_passwordXshell
!#08S01Got packets out of orderConnection closed by foreign host.

image-20241116222249419

3.在mysql中创建一个监控用户:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#进入pod中创建监控使用的用户并授予相应的权限
[root@k8s-master01 etcd-service-monitor]# kubectl exec -ti mysql-85d75646bc-9nw68 -- bash
bash-4.2# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

#创建用户
mysql> create user 'exporter'@'%' identified by 'exporter' with max_user_connections 10;
Query OK, 0 rows affected (0.00 sec) #with max_user_connections 10参数作用是限制用户最大的连接数是10

#授权
mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES; #刷新
Query OK, 0 rows affected (0.00 sec)

4.配置 MySQL Exporter 采集 MySQL 监控数据:

方式一:使用ConfigMap形式配置MySQL账号密码

创建 MySQL Exporter 的 ConfigMap、Deployment、Service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#MySQL Exporter 的 ConfigMap只要是用来保存连接目标MySQL的一些连接信息,
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-exporter-config
namespace: monitoring
data:
.my.cnf: |
[client]
user=exporter #MySQL的连接用户
password=exporter #用户的密码
host=mysql-service.default.svc.cluster.local #mysql的主机地址
port=3306 #mysql的端口号

---
#下面是创建 MySQL Exporter的 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-exporter
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: mysql-exporter
template:
metadata:
labels:
app: mysql-exporter
spec:
containers:
- name: mysql-exporter
image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/mysqld-exporter
args:
- --config.my-cnf=/etc/mysql-exporter/.my.cnf
ports:
- containerPort: 9104
name: metrics
volumeMounts:
- name: mysql-config
mountPath: /etc/mysql-exporter
readOnly: true
livenessProbe:
httpGet:
path: /
port: 9104
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /
port: 9104
initialDelaySeconds: 10
timeoutSeconds: 5
volumes:
- name: mysql-config
configMap:
name: mysql-exporter-config

---
#创建service
apiVersion: v1
kind: Service
metadata:
name: mysql-exporter
namespace: monitoring
labels:
app: mysql-exporter
spec:
type: ClusterIP
ports:
- port: 9104
targetPort: 9104
name: metrics
protocol: TCP
selector:
app: mysql-exporter
---
#创建 ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: mysql-servicemonitor
namespace: monitoring
labels:
release: prometheus
spec:
endpoints:
- interval: 30s
port: metrics
path: /metrics
scheme: http
selector:
matchLabels:
app: mysql-exporter
namespaceSelector:
matchNames:
- monitoring

创建上述资源:(可以在一个文件中写多个资源,也可以分开写,每个资源单独一个文件)

1
2
3
4
kubectl create -f mysql-exporter-configmap.yaml
kubectl create -f mysql-exporter-deployment.yaml
kubectl create -f mysql-export-service.yaml
kubectl create -f mysql-exporter-servicemonitiort.yaml

方式二:使用Secret形式定义MySQL账号密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#配置一个secret,用来mysql exporter存储mysql的连接信息。
apiVersion: v1
kind: Secret
metadata:
name: mysql-exporter-secret
namespace: monitoring
type: Opaque
stringData:
.my.cnf: |-
[client]
host=192.168.0.117 #host定义mysql服务器的IP地址,如果mysql服务器是在k8s集群外部,直接定义为mysql服务器的IP地址即可。
#host=mysql-service.default.svc.cluster.local #mysql的主机地址,这种配置是mysql服务部署在k8s集群内部,如果mysql服务器在k8s集群内部,则需要使用服务名来定义,mysql-service是MySQL服务的service名称,default是mysql-service的命名空间
port=3306 #mysql服务的端口
user=exporter #监控使用的用户
password=wawxy1314@ #监控用户的密码

---
#配置Deployment,用于部署mysql-exporter。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-exporter
namespace: monitoring
labels: #定义该Deployment资源的标签
app: mysql-exporter
spec:
replicas: 1,
selector: #选择器,用来根据 标签 选择要管理的pod,要跟下面template.metadatalabels中配置的标签保持一致
matchLabels:
app: mysql-exporter
template: #定义pod的模板
metadata: #pod的元数据
labels: #这里定义的是pod的标签
app: mysql-exporter #定义pod的标签,要和上面的spec.selector.matchLabels中定义的保持一致
spec:
containers:
- name: mysql-exporter
image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/bitnami_mysqld-exporter:0.14.0
env:
- name: TZ
value: "Asia/Shanghai"
args:
- --config.my-cnf=/etc/mysql/.my.cnf
ports:
- containerPort: 9104
name: metrics
volumeMounts:
- name: mysql-config
mountPath: /etc/mysql
volumes:
- name: mysql-config
secret:
secretName: mysql-exporter-secret
---
#配置Service,用于将mysql-exporter暴露给集群内部的其他服务。
apiVersion: v1
kind: Service
metadata:
name: mysql-exporter
namespace: monitoring
labels:
app: mysql-exporter
spec:
selector: #这里的标签选择器是定义要关联pod的标签,作用是根据标签将流量转发到相应的pod上
app: mysql-exporter
ports:
- port: 9104
targetPort: 9104
name: metrics
---
#配置ServiceMonitor,用于Prometheus Operator发现并抓取mysql-exporter的metrics数据。
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: mysql-exporter
namespace: monitoring
labels: # 定义该ServiceMonitor资源的标签
release: prometheus
spec:
selector: #标签选择器
matchLabels: #匹配标签
app: mysql-exporter #意思是匹配具有app=mysql-exporter标签的service
namespaceSelector: #定义service所在的命名空间
matchNames: #命名空间匹配,也就是从哪个命名空间找具有上述标签的service
- monitoring
endpoints:
- port: metrics #该字段与上述service资源中的port字段对应(Service.spec.ports.name),用于指定抓取的metrics端口
interval: 30s
scheme: http
path: /metrics

检查是否能正常获取到Metrics数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[root@k8s-master01 mysql-exporter]# kubectl get po -n monitoring mysql-exporter-b8cccdfcf-h6986 -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql-exporter-b8cccdfcf-h6986 1/1 Running 0 93m 172.16.85.195 k8s-node01 <none> <none>
#通过pod的ip测试是否能拿到mysql的监控数据(172.16.85.195是mysql exporter的pod 的 ip地址)
[root@k8s-master01 mysql-exporter]# curl 172.16.85.195:9104/metrics |tail -10
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 155k 0 155k 0 0 1984k 0 --:--:-- --:--:-- --:--:-- 2018k
# TYPE process_virtual_memory_max_bytes gauge
process_virtual_memory_max_bytes 1.8446744073709552e+19
# HELP promhttp_metric_handler_requests_in_flight Current number of scrapes being served.
# TYPE promhttp_metric_handler_requests_in_flight gauge
promhttp_metric_handler_requests_in_flight 1
# HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code.
# TYPE promhttp_metric_handler_requests_total counter
promhttp_metric_handler_requests_total{code="200"} 181
promhttp_metric_handler_requests_total{code="500"} 0
promhttp_metric_handler_requests_total{code="503"} 0

#通过service的ip测试是否能拿到mysql的监控数据(10.96.212.123是mysql exporter的service 的 ip地址)
[root@k8s-master01 mysql-exporter]# kubectl get svc -n monitoring mysql-exporter
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql-exporter ClusterIP 10.96.212.123 <none> 9104/TCP 95m

#通过mysql exporter的service 的 ip地址获取监控数据
[root@k8s-master01 mysql-exporter]# curl 10.96.212.123:9104/metrics |tail -10
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 155k 0 155k 0 0 3136k 0 --:--:-- --:--:-- --:--:-- 3171k
# TYPE process_virtual_memory_max_bytes gauge
process_virtual_memory_max_bytes 1.8446744073709552e+19
# HELP promhttp_metric_handler_requests_in_flight Current number of scrapes being served.
# TYPE promhttp_metric_handler_requests_in_flight gauge
promhttp_metric_handler_requests_in_flight 1
# HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code.
# TYPE promhttp_metric_handler_requests_total counter
promhttp_metric_handler_requests_total{code="200"} 191
promhttp_metric_handler_requests_total{code="500"} 0
promhttp_metric_handler_requests_total{code="503"} 0

上述的两种配置密码的方式二选一配置即可(ConfigMap和Secret).

所有资源创建完成后在prometheus的web端查看是否有mysql的监控指标:

image-20241117212041260

可以看到已经自动发现了配置的mysql-servicemonitor,状态是up

image-20241117212130912

5.Grafana配置mysql监控模板

导入 Grafana Dashboard,地址:https://grafana.com/grafana/dashboards/14057-mysql/,https://grafana.com/grafana/dashboards/6239-mysql/ (两个模板连接二选一,)导入步骤和之前类似,在此不再演示。导入完成后,即可在 Grafana 看到监控数据:

image-20241118151826097

1.在grafana控制台配置模板前需要在Prometheus确定能发现配置mysql-servicemonitor,

image-20241118152209644

2.在grafana控制台配置模板前需要在Prometheus确定能发现mysql指标,这里的指标不能只有mysql_up或者mysqld_exporter_build_info

image-20241118152454306

如果输入mysql关键字只有下图两个指标,是不对的,表示mysql exporter并没有拿到各项指标数据,需要进一步排查错误。这里遇到的就是在mysql中创建的exporter用户密码不正确导致的。

9ec5d40554cdbdc1b6c29216a55784e

6.Service Monitor找不到监控主机排查步骤

①确认Service Monitor是否成功创建

②确认Service Monitor关联的service标签是否配置正确

③确认Prometheus是否生成了相关配置

④确认Service Monitor匹配的Service存在

⑤确认通过Service能够访问程序的Metrics接口

⑥确认Service服务配置的端口名字(Service.spec.ports.name)和Service Monitor中(ServiceMonitor.spec.endpoints.port)配置的一致

一、排查案例KubeControllerManager:

image-20241120161221084

以上图KubeControllerManagerKubeScheduler为案例讲解排查过程:

以下方法不仅仅是针对KubeControllerManager或者KubeScheduler的排查思路,所有用到Service Monitor资源的均可以按照该流程排查问题。

第一步:确认Service Monitor是否成功创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#KubeControllerManager
[root@k8s-master01 mysql-exporter]# kubectl get servicemonitors.monitoring.coreos.com -n monitoring
NAME AGE
alertmanager-main 7d22h
blackbox-exporter 7d22h
coredns 7d22h
etcd-servicemonitor 4d17h
grafana 7d22h
kube-apiserver 7d22h
kube-controller-manager 7d22h
kube-scheduler 7d22h
kube-state-metrics 7d22h
kubelet 7d22h
mysql-exporter 25h
node-exporter 7d22h
prometheus-adapter 7d22h
prometheus-k8s 7d22h
prometheus-operator 7d22h

#kube-scheduler和 kube-controller-manager是存在的

第二步:确认Service Monitor关联的service标签是否配置正确

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#检查servicemonitors资源中选择的sevice资源标签
[root@k8s-master01 mysql-exporter]# kubectl get servicemonitors.monitoring.coreos.com -n monitoring kube-controller-manager -oyaml
....
insecureSkipVerify: true
jobLabel: app.kubernetes.io/name
namespaceSelector:
matchNames:
- kube-system #匹配的命名空间是kube-system
selector:
matchLabels:
app.kubernetes.io/name: kube-controller-manager #在kube-system命名空间中匹配具有app.kubernetes.io/name=kube-controller-manager标签的service

#检查检查目标命名空间中是否有标签值是app.kubernetes.io/name=kube-controller-manager的service
[root@k8s-master01 mysql-exporter]# kubectl get service -n kube-system -l app.kubernetes.io/name=kube-controller-manager
No resources found in kube-system namespace. #没有目标service


#可以看到并没有此标签的Service,所以导致了找不到需要监控的目标,此时可以手动创建该Service和Endpoint指向自己的Controller Manager:
vim kube-controller-manager-svc.yaml
#创建yaml文件,添加下面配置
kind: Service
apiVersion: v1
metadata:
name: kube-controller-manager
namespace: kube-system
labels:
app.kubernetes.io/name: kube-controller-manager #这里定义的标签和servicemonitors保持一致

spec:
type: ClusterIP
ports:
- name: https-metrics
port: 10257
targetPort: 10257
protocol: TCP
---
kind: Endpoints
apiVersion: v1
metadata:
name: kube-controller-manager
namespace: kube-system
subsets:
- addresses:
- ip: 192.168.0.200 #这里的ip改为自己的ControllerManager的ip,有几个ControllerManager节点就写几个ip
- ip: 192.168.0.201
- ip: 192.168.0.202
ports:
- name: https-metrics
port: 10257
protocol: TCP


#创建上述kube-controller-manager-svc.yaml资源(创建Service和Endpoints)
[root@k8s-master01 kube-controller-manager]# kubectl create -f kube-controller-manager-svc.yaml
service/kube-controller-manager created
endpoints/kube-controller-manager created
[root@k8s-master01 kube-controller-manager]# kubectl get -f kube-controller-manager-svc.yaml
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kube-controller-manager ClusterIP 10.96.228.24 <none> 10257/TCP 4h31m

NAME ENDPOINTS AGE
endpoints/kube-controller-manager 192.168.0.200:10257,192.168.0.201:10257,192.168.0.202:10257 4h31m


#因为请求kube-controller-manager的接口也要使用https,所以也需要配置证书(可以参考etcd的证书配置方法,一个道理)
#首先找到证书,创建一个secret,这个secret要给prometheus-k8s-0使用,所以要个prometheus-k8s-0的pod在同一个命名空间中
kubectl create secret generic kube-controller-manager-ssl \
--from-file=/etc/kubernetes/pki/ca.pem \
--from-file=/etc/kubernetes/pki/admin.pem \
--from-file=/etc/kubernetes/pki/admin-key.pem -n monitoring

#将secret证书挂载至 Prometheus 容器(由于 Prometheus 是 Operator 部署的,所以只需要修改Prometheus 资源即可):
[root@k8s-master01 kube-controller-manager]# kubectl edit prometheus -n monitoring k8s
scrapeConfigSelector: {}
scrapeInterval: 30s
secrets: #在secrets下添加刚才创建的secret名字,是kube-controller-manager-ssl
- etcd-ssl #这个是etcd的证书
- kube-controller-manager-ssl #这个是新增的kube-controller-manager证书的名字
securityContext:
fsGroup: 2000

#保存退出后,Prometheus 的 Pod (prometheus-k8s-0)会自动重启,重启完成后,查看证书是否挂载(任意一个Prometheus 的 Pod 均可):
[root@k8s-master01 kube-controller-manager]# kubectl exec -ti prometheus-k8s-0 -n monitoring -- sh
/prometheus $ ls -l /etc/prometheus/secrets/
etcd-ssl/ kube-controller-manager-ssl/
/prometheus $ ls -l /etc/prometheus/secrets/kube-controller-manager-ssl/
total 0
lrwxrwxrwx 1 root 2000 20 Nov 20 10:27 admin-key.pem -> ..data/admin-key.pem
lrwxrwxrwx 1 root 2000 16 Nov 20 10:27 admin.pem -> ..data/admin.pem
lrwxrwxrwx 1 root 2000 13 Nov 20 10:27 ca.pem -> ..data/ca.pem

#编辑kube-controller-manager的ServiceMonitor,配置tlsConfig中证书文件部分
[root@k8s-master01 kube-controller-manager]# kubectl edit servicemonitors.monitoring.coreos.com -n monitoring kube-controller-manager
metricRelabelings:
- action: drop
regex: process_start_time_seconds
sourceLabels:
- __name__
path: /metrics/slis
port: https-metrics
scheme: https
tlsConfig: #配置证书文件在pod名字是prometheus-k8s-0中的路径
caFile: /etc/prometheus/secrets/kube-controller-manager-ssl/ca.pem #Prometheus 的 Pod (prometheus-k8s-0)中的路径
certFile: /etc/prometheus/secrets/kube-controller-manager-ssl/admin.pem ##Prometheus 的 Pod (prometheus-k8s-0)中的路径
insecureSkipVerify: true
keyFile: /etc/prometheus/secrets/kube-controller-manager-ssl/admin-key.pem ##Prometheus 的 Pod (prometheus-k8s-0)中的路径
jobLabel: app.kubernetes.io/name
namespaceSelector:
matchNames:
- kube-system
selector:
matchLabels:
app.kubernetes.io/name: kube-controller-manager

在prometheus控制台查看是否成功:

下面已经看不到之前的报错了(KubeControllerManagerDown)

image-20241121162146298

可以看到kube-controller-manager的状态也都是up,这就表示已经处理好了。

image-20241121162431079

二、排查案例KubeScheduler:

①确认Service Monitor是否成功创建

②确认Service Monitor关联的service标签是否配置正确

③确认Prometheus是否生成了相关配置

④确认Service Monitor匹配的Service存在

⑤确认通过Service能够访问程序的Metrics接口

⑥确认Service服务配置的端口名字(Service.spec.ports.name)和Service Monitor中(ServiceMonitor.spec.endpoints.port)配置的一致

第一步:排查是否有KubeScheduler的Service Monitor

image-20241122151742078

第二步:确认Service Monitor关联的service标签是否配置正确

image-20241122152201816

检查kube-system命名空间中是否存在标签是app.kubernetes.io/name=kube-scheduler的Service:

1
2
kubectl get service -n kube-system  -l app.kubernetes.io/name=kube-scheduler
#通过该命令看到没有找到相应的service资源,见下图

image-20241122152428208

接下来手动为scheduler创建Service和Endpoint,指向安装的kube-scheduler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#手动创建Service和Endpoint资源:
vim kube-scheduler-svc.yaml
#创建yaml文件,添加下面配置
kind: Service
apiVersion: v1
metadata:
name: kube-scheduler
namespace: kube-system
labels:
app.kubernetes.io/name: kube-scheduler #这里定义的标签和servicemonitors保持一致
spec:
ports:
- name: https-metrics #如果是通过ServiceMonitor资源对其进行监控,这里的name要和ServiceMonitor.spec.endpoints.port字段保持一致
port: 10259
targetPort: 10259
protocol: TCP
---
kind: Endpoints
apiVersion: v1
metadata:
name: kube-scheduler
namespace: kube-system
subsets:
- addresses:
- ip: 192.168.0.200 ##这里的ip改为自己的kube-scheduler的ip,有几个kube-scheduler节点就写几个ip
- ip: 192.168.0.201
- ip: 192.168.0.202
ports:
- name: https-metrics
port: 10259
protocol: TCP


#创建上述kube-scheduler-svc.yaml资源(创建Service和Endpoints)
[root@k8s-master01 kube-scheduler]# kubectl replace -f kube-scheduler-svc.yaml
service/kube-scheduler replaced
endpoints/kube-scheduler replaced
[root@k8s-master01 kube-scheduler]# kubectl get -f kube-scheduler-svc.yaml
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kube-scheduler ClusterIP 10.96.9.215 <none> 10259/TCP 23m

NAME ENDPOINTS AGE
endpoints/kube-scheduler 192.168.0.200:10259,192.168.0.201:10259,192.168.0.202:10259 23m

测试通过创建的service的ip是否能获取到监控数据:

1
2
curl --cacert /etc/kubernetes/pki/ca.pem --cert /etc/kubernetes/pki/admin.pem --key /etc/kubernetes/pki/admin-key.pem https://10.96.9.215:10259/metrics -k|tail -5
#通过下图可以看到通过service的ip能获取到监控数据

image-20241122165335265

因为请求kube-scheduler的接口也要使用https,所以也需要配置证书(可以参考etcd和kube-controller-manager的证书配置方法,一个道理)

1
2
3
4
5
#首先找到证书,创建一个secret,这个secret要给prometheus-k8s-0使用,所以要个prometheus-k8s-0的pod在同一个命名空间中
kubectl create secret generic kube-scheduler-ssl \
--from-file=/etc/kubernetes/pki/ca.pem \
--from-file=/etc/kubernetes/pki/admin.pem \
--from-file=/etc/kubernetes/pki/admin-key.pem -n monitoring

image-20241122165723157

将secret证书挂载至 Prometheus 容器(由于 Prometheus 是 Operator 部署的,所以只需要修改Prometheus 资源即可):

1
2
3
4
5
kubectl edit prometheus -n monitoring  k8s
secrets: #在secrets下添加刚才创建的secret名字,是kube-scheduler-ssl
- etcd-ssl #这个是etcd的证书
- kube-controller-manager-ssl #这个是kube-controller-manager证书的名字
- kube-scheduler-ssl #这个是为kube-scheduler创建的secret

image-20241122170039327

保存退出后,Prometheus 的 Pod (prometheus-k8s-0)会自动重启,重启完成后,查看证书是否挂载(任意一个Prometheus 的 Pod 均可):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#等待pod(prometheus-k8s-0)自动重启,查看证书是否挂载成功
[root@k8s-master01 kube-scheduler]# kubectl exec -ti prometheus-k8s-0 -n monitoring -- sh
/prometheus $ ls -l /etc/prometheus/secrets/
total 0
drwxrwsrwt 3 root 2000 140 Nov 22 09:04 etcd-ssl
drwxrwsrwt 3 root 2000 140 Nov 22 09:04 kube-controller-manager-ssl
drwxrwsrwt 3 root 2000 140 Nov 22 09:04 kube-scheduler-ssl
/prometheus $ ls -l /etc/prometheus/secrets/kube-scheduler-ssl/
total 0
lrwxrwxrwx 1 root 2000 20 Nov 22 09:04 admin-key.pem -> ..data/admin-key.pem
lrwxrwxrwx 1 root 2000 16 Nov 22 09:04 admin.pem -> ..data/admin.pem
lrwxrwxrwx 1 root 2000 13 Nov 22 09:04 ca.pem -> ..data/ca.pem

#编辑kube-scheduler的ServiceMonitor,配置tlsConfig中证书文件部分
[root@k8s-master01 kube-scheduler]# kubectl edit servicemonitors.monitoring.coreos.com -n monitoring kube-scheduler
metricRelabelings:
- action: drop
regex: process_start_time_seconds
sourceLabels:
- __name__
path: /metrics/slis
port: https-metrics
scheme: https
tlsConfig: #配置证书文件,证书路径是名字为prometheus-k8s-0 的 pod中的路径
caFile: /etc/prometheus/secrets/kube-scheduler-ssl/ca.pem # #Prometheus 的 Pod (prometheus-k8s-0)中的路径,不是宿主机的路径
certFile: /etc/prometheus/secrets/kube-scheduler-ssl/admin.pem #Prometheus 的 Pod (prometheus-k8s-0)中的路径,不是宿主机的路径
keyFile: /etc/prometheus/secrets/kube-scheduler-ssl/admin-key.pem # #Prometheus 的 Pod (prometheus-k8s-0)中的路径,不是宿主机的路径
insecureSkipVerify: true
jobLabel: app.kubernetes.io/name
namespaceSelector:
matchNames:
- kube-system
selector:
matchLabels:
app.kubernetes.io/name: kube-scheduler
metricRelabelings:

在prometheus控制台查看是否还存在报错:

下面已经看不到之前的报错了(KubeSchedulerDown)

image-20241122171302860

image-20241122171853802

可能存在的问题:

可能会遇到Service不通的问题,因为在集群搭建时,可能ControllerManager和Scheduler是监听的127.0.0.1就导致无法被外部访问,此时需要更改它的监听地址为0.0.0.0:

1
2
3
4
5
6
7
8
9
10
11
#查看服务监听地址:
[root@k8s-master01 kube-scheduler]# netstat -lntup|grep kube-controlle
tcp6 0 0 :::10257 :::* LISTEN 1126/kube-controlle
[root@k8s-master01 kube-scheduler]# netstat -lntup|grep kube-scheduler
tcp6 0 0 :::10259 :::* LISTEN 1125/kube-scheduler

#如果监听的地址是127.0.0.1,就需要修改对应服务的配置文件,将监听地址改为0.0.0.0,服务的配置文件路径根据自己的位置修改。例如:
sed -i "s#address=127.0.0.1#address=0.0.0.0#g" /usr/lib/systemd/system/kube-controller-manager.service
#修改后重启
systemctl daemon-reload
systemctl restart kube-controller-manager

18.3黑盒监控

黑盒监控 (Blackbox Monitoring)

  • 定义:黑盒监控指的是通过模拟用户请求来监控外部服务或系统的可用性和性能,而不是直接监控这些服务的内部指标。这种监控方式通常用于检查网络服务的健康状态,如HTTP、HTTPS、DNS、TCP等协议的响应时间、状态码等。
  • 特点
    • 从用户的视角来评估服务的可用性和性能。
    • 不需要对被监控的系统有深入的内部了解。
    • 主要关注外部表现,如响应时间、状态码、是否可达等。
    • 通常使用blackbox_exporter来实现。
  • 应用
    • 网站监控:检查网站是否可达,响应时间是否在可接受范围内。
    • DNS监控:验证DNS解析是否正常工作。
    • API监控:监控API的响应时间、状态码。
    • 网络服务监控:检查TCP连接的建立时间、丢包率等。

白盒监控 (Whitebox Monitoring)

  • 定义:白盒监控指的是直接从系统内部获取指标数据,监控系统的内部状态和性能。这种监控方式需要对被监控的系统有深入的了解,能够获取到系统的内部运行情况。
  • 特点
    • 直接监控系统的内部指标,如CPU使用率、内存使用、磁盘I/O、网络流量等。
    • 需要对系统的内部结构和运行机制有详细的了解。
    • 可以提供更详细的性能数据和问题诊断信息。
    • 通常通过Prometheus的exporter来暴露系统的内部指标。
  • 应用
    • 系统资源监控:监控CPU、内存、磁盘、网络等资源的使用情况。
    • 应用性能监控:监控应用程序的内部指标,如请求处理时间、错误率等。
    • 数据库监控:监控数据库的性能指标,如查询时间、连接数等。
    • 容器和Kubernetes监控:监控容器和Kubernetes集群的内部状态。

总结

  • 黑盒监控关注的是服务的外部表现,适用于检查服务的可用性和用户体验,但无法提供关于系统内部状态的详细信息。
  • 白盒监控则深入到系统内部,提供更详细的性能数据和问题诊断信息,但需要对系统有深入的了解。

新版Prometheus Stack已经默认安装了BlackboxExporter(黑盒监控),可以通过以下命令查看:

1
2
kubectl get po -n monitoring
#

image-20241122181129709

同时也会创建一个Service,可以通过该Service访问BlackboxExporter并传递一些参数:

1
kubectl get service -n monitoring

image-20241122181228041

可以通过blackbox-exporter的service的ip地址对网站进行探测:

比如检测下www.baidu.com(使用任何一个公网域名或者公司内的域名探测即可)网站的状态,可以通过如下命令进行检查:

1
2
3
4
5
6
7
8
9
10
11
[root@k8s-master01 kube-scheduler]# curl -s "http://10.96.69.178:19115/probe?target=www.baidu.com&module=http_2xx" | tail -5
# TYPE probe_ip_protocol gauge
probe_ip_protocol 4
# HELP probe_success Displays whether or not the probe was a success
# TYPE probe_success gauge
probe_success 1

#probe是blackbox-exporter服务的接口地址。
#target是检测的目标。
#module是使用哪个模块进行探测。
#https://github.com/prometheus/blackbox_exporter进行安装。

1.监控站点

Prometheus支持的 额外抓取配置(additionalScrapeConfigs),通过配置额外抓取配置来实现对某些网站的监控。

当 Prometheus Operator 默认生成的 scrape_configs 无法覆盖特殊场景(如黑盒监控、自定义导出器)时,additionalScrapeConfigs 提供了一种灵活扩展机制。

Prometheus Operator 会自动检测 additionalScrapeConfigs,将其内容合并到主 Prometheus 的配置中(scrape_configs 部分)。

通过prometheus的静态配置对某个网站进行监控—黑盒监控

第一步:创建一个空文件,然后通过该文件创建一个secret,那么这个secret即可作为prometheus的静态配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#创建一个空文件prometheus-additional.yaml,用它来创建secret
[root@k8s-master01 blackbox-exporter]# touch prometheus-additional.yaml

#创建secret
[root@k8s-master01 blackbox-exporter]# kubectl create secret generic prometheus-additional-config --from-file=prometheus-additional.yaml -n monitoring
secret/prometheus-additional-config created

#查看创建的secret
[root@k8s-master01 blackbox-exporter]# kubectl get secrets -n monitoring prometheus-additional-config
NAME TYPE DATA AGE
prometheus-additional-config Opaque 1 47s


#修改prometheus的配置,这里的prometheus是一个CRD(自定义资源定义),由Prometheus Operator管理,修改CRD会自动触发Operator重新配置Prometheus
[root@k8s-master01 blackbox-exporter]# kubectl edit prometheus -n monitoring k8s
#在 Prometheus 的配置中,additionalScrapeConfigs 是 Prometheus Operator 提供的一个参数,用于扩展和动态管理 scrape_configs(抓取配置)。它的作用是指定一组额外的抓取配置,这些配置通过一个 Kubernetes Secret 提供,并与 Prometheus 的默认 scrape_configs 合并
serviceMonitorNamespaceSelector: {}
serviceMonitorSelector: {}
additionalScrapeConfigs: #定义额外抓取配置
name: prometheus-additional-config #对应上述创建的secret的名称
key: prometheus-additional.yaml #key对应是的上述创建的secret时指定的文件名
optional: true #可选参数,true表示即使Secret不存在也不会报错,提供了配置的容错性便于后续增量更新
version: 2.54.1
status:
availableReplicas: 1
conditions:

主要是在prometheus资源中增加下面配置:

1
2
3
4
additionalScrapeConfigs: #定义额外抓取配置
name: prometheus-additional-config #对应上述创建的secret的名称
key: prometheus-additional.yaml #key对应是的上述创建的secret时指定的文件名
optional: true #可选参数,true表示即使Secret不存在也不会报错,提供了配置的容错性便于后续增量更新

image-20241122225600962

添加上述配置后保存退出,无需重启 Prometheus 的 Pod 即可生效。之后在prometheus-additional.yaml文件内编辑一些静态配置,此处用黑盒监控的配置进行演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@k8s-master01 blackbox-exporter]# vim prometheus-additional.yaml
#添加下面配置
- job_name: 'blackbox' # 任务名称
metrics_path: /probe # 指标获取路径
params:
module: [http_2xx] # 使用的探测模块
static_configs:
- targets: #targets模块下配置的是要监控的网站域名
- http://gaoxin.kubeasy.com # 监控目标
- https://www.baidu.com
relabel_configs: # 标签重写规则,固定写法
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:19115 #Blackbox Exporter 的地址

可以看到此处的内容,基本和命令行配置的内容一致,只需要添加对应的 job 即可。之后通过该文件热更新该 Secret:

1
2
3
#热更新secret命令
[root@k8s-master01 blackbox-exporter]# kubectl create secret generic prometheus-additional-config --from-file=prometheus-additional.yaml --dry-run=client -oyaml|kubectl replace -f - -n monitoring
secret/prometheus-additional-config replaced

检查secret是否被更新:

1
2
3
4
5
6
7
8
9
10
11
12
[root@k8s-master01 blackbox-exporter]# kubectl get secrets -n monitoring prometheus-additional-config -oyaml
apiVersion: v1
data:
prometheus-additional.yaml: I+a3u+WKoOS4i+mdoumFjee9rg0KLSBqb2JfbmFtZTogJ2JsYWNrYm94JyAgICAgICAgICAgICAgICAjIOS7u+WKoeWQjeensA0KICBtZXRyaWNzX3BhdGg6IC9wcm9iZSAgICAgICAgICAgICAgICMg5oyH5qCH6I635Y+W6Lev5b6EDQogIHBhcmFtczoNCiAgICBtb2R1bGU6IFtodHRwXzJ4eF0gICAgICAgICAgICAgICMg5L2/55So55qE5o6i5rWL5qih5Z2XDQogIHN0YXRpY19jb25maWdzOg0KICAgIC0gdGFyZ2V0czogI3RhcmdldHPmqKHlnZfkuIvphY3nva7nmoTmmK/opoHnm5HmjqfnmoTnvZHnq5nln5/lkI0NCiAgICAgICAgLSBodHRwOi8vZ2FveGluLmt1YmVhc3kuY29tICAgIyDnm5Hmjqfnm67moIcNCiAgICAgICAgLSBodHRwczovL3d3dy5iYWlkdS5jb20NCiAgcmVsYWJlbF9jb25maWdzOiAgICAgICAgICAgICAgICAgICMg5qCH562+6YeN5YaZ6KeE5YiZ77yM5Zu65a6a5YaZ5rOVDQogICAgLSBzb3VyY2VfbGFiZWxzOiBbX19hZGRyZXNzX19dDQogICAgICB0YXJnZXRfbGFiZWw6IF9fcGFyYW1fdGFyZ2V0DQogICAgLSBzb3VyY2VfbGFiZWxzOiBbX19wYXJhbV90YXJnZXRdDQogICAgICB0YXJnZXRfbGFiZWw6IGluc3RhbmNlDQogICAgLSB0YXJnZXRfbGFiZWw6IF9fYWRkcmVzc19fDQogICAgICByZXBsYWNlbWVudDogYmxhY2tib3gtZXhwb3J0ZXI6MTkxMTU=
kind: Secret
metadata:
creationTimestamp: "2024-11-22T14:40:30Z"
name: prometheus-additional-config
namespace: monitoring
resourceVersion: "18827266"
uid: efc2196d-fbc4-4425-8c05-d94963289e21
type: Opaque

可以看到上述secret已经有内容了,可以使用base64解码查看内容是否是我们配置的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@k8s-master01 blackbox-exporter]# echo """I+a3u+WKoOS4i+mdoumFjee9rg0KLSBqb2JfbmFtZTogJ2JsYWNrYm94JyAgICAgICAgICAgICAgICAjIOS7u+WKoeWQjeensA0KICBtZXRyaWNzX3BhdGg6IC9wcm9iZSAgICAgICAgICAgICAgICMg5oyH5qCH6I635Y+W6Lev5b6EDQogIHBhcmFtczoNCiAgICBtb2R1bGU6IFtodHRwXzJ4eF0gICAgICAgICAgICAgICMg5L2/55So55qE5o6i5rWL5qih5Z2XDQogIHN0YXRpY19jb25maWdzOg0KICAgIC0gdGFyZ2V0czogI3RhcmdldHPmqKHlnZfkuIvphY3nva7nmoTmmK/opoHnm5HmjqfnmoTnvZHnq5nln5/lkI0NCiAgICAgICAgLSBodHRwOi8vZ2FveGluLmt1YmVhc3kuY29tICAgIyDnm5Hmjqfnm67moIcNCiAgICAgICAgLSBodHRwczovL3d3dy5iYWlkdS5jb20NCiAgcmVsYWJlbF9jb25maWdzOiAgICAgICAgICAgICAgICAgICMg5qCH562+6YeN5YaZ6KeE5YiZ77yM5Zu65a6a5YaZ5rOVDQogICAgLSBzb3VyY2VfbGFiZWxzOiBbX19hZGRyZXNzX19dDQogICAgICB0YXJnZXRfbGFiZWw6IF9fcGFyYW1fdGFyZ2V0DQogICAgLSBzb3VyY2VfbGFiZWxzOiBbX19wYXJhbV90YXJnZXRdDQogICAgICB0YXJnZXRfbGFiZWw6IGluc3RhbmNlDQogICAgLSB0YXJnZXRfbGFiZWw6IF9fYWRkcmVzc19fDQogICAgICByZXBsYWNlbWVudDogYmxhY2tib3gtZXhwb3J0ZXI6MTkxMTU="""|base64 -d  #可以看到解密出来的配置是我们配置的内容
#添加下面配置
- job_name: 'blackbox' # 任务名称
metrics_path: /probe # 指标获取路径
params:
module: [http_2xx] # 使用的探测模块
static_configs:
- targets: #targets模块下配置的是要监控的网站域名
- http://gaoxin.kubeasy.com # 监控目标
- https://www.baidu.com
relabel_configs: # 标签重写规则,固定写法
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:19115

检查Prometheus的Web 界面中查看是否存在该配置:

通过下图可以看到Prometheus已经成功看到该配置,状态也是up,接下来就可以配置监控模板了。

image-20241122233458899

在grafana控制台中配置监控模板(模板连接地址https://grafana.com/grafana/dashboards/13659-blackbox-exporter-http-prober/):

导入网站监控模板:

image-20241122235718600

image-20241122235838353

image-20241123000037260

最后可以看到监控界面即可:

image-20241123000117347

如果需要新增加站点监控,直接编辑prometheus-additional.yaml文件,然后再次执行热更新secret的命令即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#例如,要新增加www.ibstd.cn站点的监控,在targets模块下增加监控目标即可
[root@k8s-master01 blackbox-exporter]# vim prometheus-additional.yaml
#添加下面配置
- job_name: 'blackbox' # 任务名称
metrics_path: /probe # 指标获取路径
params:
module: [http_2xx] # 使用的探测模块
static_configs:
- targets: #targets模块下配置的是要监控的网站域名
- http://gaoxin.kubeasy.com # 监控目标
- https://www.baidu.com
- https://www.ibstd.cn #这是新增加的监控目标网站
relabel_configs: # 标签重写规则,固定写法
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:19115 #Blackbox Exporter 的地址

修改prometheus-additional.yaml文件后保存退出,执行热更新的命令即可:

1
2
#通过下面的命令热更新secret
kubectl create secret generic prometheus-additional-config --from-file=prometheus-additional.yaml --dry-run=client -oyaml|kubectl replace -f - -n monitoring

18.4Prometheus监控外部windows主机

监控 Linux主机 的 Exporter 是:https://github.com/prometheus/node_exporter,

监控 Windows主机的 Exporter 是:https://github.com/prometheus-community/windows_exporter。

首 先 下 载 对 应 的 Exporter 至 Windows 主 机 ( MSI 文 件 下 载 地 址 :https://github.com/prometheus-community/windows_exporter/releases):

image-20241123193108702

下载后直接在要监控的windows主机上安装,Windows Exporter 会暴露一个 9182 端口,可以通过该端口访问到 Windows 的监控数据。

image-20241123193222251

接下来在静态配置文件中添加以下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@k8s-master01 blackbox-exporter]# cat prometheus-additional.yaml
#添加下面配置
- job_name: 'blackbox' # 任务名称
metrics_path: /probe # 指标获取路径
params:
module: [http_2xx] # 使用的探测模块
static_configs:
- targets: #targets模块下配置的是要监控的网站域名
- http://gaoxin.kubeasy.com # 监控目标
- https://www.baidu.com
- https://www.ibstd.cn
relabel_configs: # 标签重写规则,固定写法
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:19115
#下面部署是新增加对windows主机监控的部分,
- job_name: 'WindowsMonitor'
static_configs:
- targets:
- "192.168.0.103:9182" #这里是被监控电脑的ip地址,如果有多个参考上述站点的监控格式写多个即可
labels:
server_type: 'windows'
relabel_configs:
- source_labels: [__address ]
target_label: instance

#Targets 配置的是监控主机,如果是多台 Windows 主机,配置多行即可,当然每台主机都需要配置 Exporter。

对该静态文件进行热更新:

1
2
#通过下面的命令热更新secret
kubectl create secret generic prometheus-additional-config --from-file=prometheus-additional.yaml --dry-run=client -oyaml|kubectl replace -f - -n monitoring

之后可以在 Prometheus Web UI 看到监控数据表示配置正确:

image-20241123195031682

image-20241123195108307

上述都显示没问题了在grafana中导入监控模板:https://grafana.com/grafana/dashboards/12566-3-windows-exporter-0-7-0-for-prometheus-windows/

image-20241123195856082

18.5PromQL语法初体验

PromQL Web UI 的 Graph 选项卡提供了简单的用于查询数据的入口,对于 PromQL 的编写和校验都可以在此位置,如图所示:

image-20241123204524648

输入 up,然后点击 Execute,就能查到监控正常的 Target:

image-20241123204600634

通过标签选择器过滤出job 为node-exporter 的监控,语法为:**up{job=”node-exporter”}**:

image-20241123204644766

注意此时是 **up{job=”node-exporter”}**属于绝对匹配,PromQL 也支持如下表达式:

  • !=:不等于;
  • =~:表示等于符合正则表达式的指标;
  • !:和=类似,=表示正则匹配,!表示正则不匹配。

如果想要查看主机监控的指标有哪些,可以输入 node,会提示所有主机监控的指标:

image-20241123205448196

假 如 想 要 查 询 Kubernetes 集 群 中 每 个 宿 主 机 的 磁 盘 总 量 , 可 以 使 用node_filesystem_size_bytes

image-20241123205611716

查询指定分区大小 **node_filesystem_size_bytes{mountpoint=”/“}**:

image-20241123210440620

或者是查询分区不是/boot,且磁盘是/dev/开头的分区大小(结果不再展示):

1
node_filesystem_size_bytes{device=~'/dev/.*',mountpoint!='/boot'}

image-20241123211025623

查询主机 k8s-master01 在最近 5 分钟可用的磁盘空间变化:

1
node_filesystem_avail_bytes{instance="k8s-master01",mountpoint='/',device='/dev/mapper/centos_k8s--master01-root'}[5m]

image-20241123211517683

目前支持的范围单位如下:

  • s:秒
  • m:分钟
  • h:小时
  • d:天
  • w:周
  • y:年

查询10分钟之前磁盘可用空间,只需要指定offset参数即可:

1
node_filesystem_avail_bytes{instance="k8s-master01",mountpoint='/',device='/dev/mapper/centos_k8s--master01-root'}offset 10m

image-20241123212210704

查询 10 分钟之前,5 分钟区间的磁盘可用空间的变化:

1
node_filesystem_avail_bytes{instance="k8s-master01",mountpoint='/',device='/dev/mapper/centos_k8s--master01-root'}[5m] offset 10m

image-20241123212704991

18.6PromQL操作符

通过 PromQL 的语法查到了主机磁盘的剩余空间数据,查询结果如下:

image-20241123213752970

可以通过以下命令将字节转换为 GB 或者 MB:

1
node_filesystem_avail_bytes{mountpoint='/'}/1024/1024/1024

也可以将 1024 / 1024 / 1024 改为**(1024 ^ 3)**:

可以看到5个节点的/分区剩余空间都不足5G

1
node_filesystem_avail_bytes{mountpoint='/'}/(1024^3)

image-20241123213900692

image-20241123214024587

上述使用的“/”为数学运算的“除”,“^”为幂运算,同时也支持如下运算符:

  • +: 加
  • -: 减
  • *: 乘
  • /: 除
  • ^: 幂运算
  • %: 求余

查询 k8s-master01 根区分磁盘可用率(剩余空间/总空间=可用率),可以通过如下指令进行计算:

1
2
node_filesystem_avail_bytes{mountpoint='/',instance='k8s-master01'}/node_filesystem_size_bytes{mountpoint='/',instance='k8s-master01'}
#通过下图可以看到可用率大概22%左右

image-20241123214802056

在宿主机上执行df -h 可以看到 Use%使用率78%,所有可用率22%,上面计算的准确

image-20241123214926598

查询所有主机根分区的可用率:

1
node_filesystem_avail_bytes{mountpoint='/'}/node_filesystem_size_bytes{mountpoint='/'}

image-20241123215205685

也可以将结果乘以 100 直接得到百分比:

1
(node_filesystem_avail_bytes{mountpoint='/'}/node_filesystem_size_bytes{mountpoint='/'})*100

image-20241123215608619

找到集群中根分区空间可用率小于25%的主机:

1
(node_filesystem_avail_bytes{mountpoint='/'}/node_filesystem_size_bytes{mountpoint='/'})*100 <25

image-20241123215814451

PromQL也支持如下判断:

  • ==: (相等)
  • != :(不相等)
  • >:(大于)
  • < :(小于)
  • >= :(大于等于)
  • <= :(小于等于)

磁盘可用率大于 25%小于等于 60%的主机:

1
25 < ((node_filesystem_avail_bytes{mountpoint='/'}/node_filesystem_size_bytes{mountpoint='/'})*100)<=50

也可以用 and 进行联合查询:(磁盘可用率大于 25%小于等于 60%的主机:)

1
node_filesystem_avail_bytes{mountpoint='/'}/node_filesystem_size_bytes{mountpoint='/'}*100>25 and node_filesystem_avail_bytes{mountpoint='/'}/node_filesystem_size_bytes{mountpoint='/'}*100<=50

除了支持 and 外,也支持 orunless

  • and:并且,条件都满足
  • or:或者,满意一个条件即可
  • ubless:排除

查询主机磁盘剩余空间,并且排除掉shm和tmpfs的磁盘:

1
node_filesystem_size_bytes unless node_filesystem_size_bytes{device=~'shm|tmpfs'}

18.7PromQL常用函数

使用 sum 函数统计当前监控目标所有主机根分区剩余的空间:

1
sum(node_filesystem_size_bytes{mountpoint='/'})/1024^3

image-20241123230931637

也可以用同样的方式计算所有的请求总量:以grafana_http_request_duration_seconds_count指标为例

1
2
#统计请求总数
sum(grafana_http_request_duration_seconds_count)

image-20241123232922853

根据 statuscode 字段进行统计请求数据:

1
sum(grafana_http_request_duration_seconds_count) by (status_code)

image-20241123232909425

根据 statuscode 和 handler 两个指标进一步统计:

1
sum(grafana_http_request_duration_seconds_count) by (handler,status_source)

image-20241123233137226

根据上述的结果,找到排名前五的:topk

1
topk(5,sum(grafana_http_request_duration_seconds_count) by (handler,status_source))

image-20241123233433862

取最后三个数据:bottomk

1
bottomk(3,sum(grafana_http_request_duration_seconds_count) by (handler,status_source))

找出统计结果中最小的数据:

1
min(node_filesystem_avail_bytes{mountpoint="/"})

最大的数据:

1
max(node_filesystem_avail_bytes{mountpoint="/"})

平均值:

1
avg(node_filesystem_avail_bytes{mountpoint="/"})

四舍五入,向上取最接近的整数,2.79 3:

1
ceil(node_filesystem_files_free{mountpoint="/"} / 1024 / 1024)

向下取整数, 2.79 ==》 2:

1
floor(node_filesystem_files_free{mountpoint="/"} / 1024 / 1024)

对结果进行正向排序:

1
sort(sum(http_request_total) by (handler, statuscode))

对结果进行逆向排序:

1
sort_desc(sum(http_request_total) by (handler, statuscode))

函数 predict_linear 可以用于预测分析和预测性告警,比如可以根据一天的数据,预测 4 个小时后,磁盘分区的空间会不会小于 0:

1
predict_linear(node_filesystem_files_free{mountpoint="/"}[1d], 4*3600) < 20

除了上述的函数,还有几个比较重要的函数,比如 increase、rate、irate。其中 increase 是计算在一段时间范围内数据的增长(只能计算 count 类型的数据),rate 和 irate 是计算增长率。比如查询某个请求在 1 小时的时间增长了多少:

1
increase(grafana_http_request_duration_seconds_count{handler="/api/datasources/uid/:uid/resources/*", method="GET"}[1h])

将 1h 增长的数量除以该时间即为增长率:(除以3600秒,即每秒增长率)

1
increase(grafana_http_request_duration_seconds_count{handler="/api/datasources/uid/:uid/resources/*", method="GET"}[1h])/3600

相对于 increase,rate 可以直接计算出某个指标在给定时间范围内的增长率,比如还是计算1h 的增长率,可以用 rate 函数进行计算:

1
rate(grafana_http_request_duration_seconds_count{handler='/api/health'}[1h] )

irate :长尾效应

第十九章、云原生Alertmanager告警

待补充