写点什么

kube-prometheus 监控系统使用与总结

作者:CTO技术共享
  • 2022 年 9 月 20 日
    广东
  • 本文字数:6085 字

    阅读完需:约 20 分钟

kube-prometheus 监控系统使用与总结

本文介绍了如何基于 kube-prometheus 设计一个监控系统, 以灵活简单的方式对 kubernetes 上的应用进行指标采集,并实现监控报警功能。

本文提供了作者的应用示例,另外还记录了作者在学习、使用 Prometheus 过程中的一些笔记,如 arm 版镜像获取、一些工具的使用等。

前言

衆所周知,大数据産品作为底层平台,其运维监控一直是生産实践的痛点难点,且在稳定运行的基础之上,往往还需要对性能进行评估优化,所以其监控系统的建设显得尤为重要。

Prometheus 作为云原生时代最火的监控软件,很多大数据组件或原生或以第三方插件 / exporter 的形式对 Prometheus 做了支持。

我使用的大数据平台是基于 kubernetes 运行的,有部署灵活管理方便的优点,更容易与 Prometheus 进行结合。

下面将对设计思路和技术实现进行阐述探讨。

设计思路

监控系统的核心任务是将暴露出来的指标数据进行抓取,在此之上进行分析、告警 所以有以下几个要明确的问题:

  1. 监控对象是什么

  2. 监控对象如何暴露指标数据

  3. 监控系统如何对指标进行抓取

  4. 如何实现告警规则动态配置、管理

监控对象

以 pod(容器)形式运行在 kubernetes 集群上的各个大数据组件。

指标暴露方式

各组件根据对 Prometheus 的支持程度,可分为 3 种类型的指标暴露方式:

  1. 直接暴露 Prometheus 指标数据 (直接,拉)

  2. 主动将指标数据推送到 prometheus-pushGateway,由 pushGateway 暴露数据(间接,推)

  3. 自定义 exporter 将其他形式的指标数据转换为符合 Prometheus 标准的格式进行暴露(exporter,直接,拉)

个别组件同时支持多种方式,如 flink 支持直接和间接方式,spark 支持直接方式而且也有第三方 exporter。大部分组件都有官方 / 第三方的 exporter,极少数需要自己开发。

一般情况下直接方式就可以了。

需要注意的是,像 flink(spark) on yarn 模式运行的时候,flink 节点是跑在 yarn 容器里面的。这种情况下 Prometheus 很难对其直接进行抓取,这种时候就只能用间接方式,主动将数据推送到 pushGateway。

另外那些短暂生命周期的组件也建议用主动 push 到 pushGateway。

指标抓取方式

不管是 exporter 还是 pushGateway,到最后必然是由 Prometheus 主动对这些目标进行抓取。

Prometheus 主要通过 Pull 的方式来抓取目标服务暴露出来的监控接口,因此需要配置对应的抓取任务来请求监控数据并写入到 Prometheus 提供的存储中,目前 Prometheus 服务提供了如下几个任务的配置:

  • 原生 Job 配置:提供 Prometheus 原生抓取 Job 的配置。

  • Pod Monitor:在 K8S 生态下,基于 Prometheus Operator 来抓取 Pod 上对应的监控数据。

  • Service Monitor:在 K8S 生态下,基于 Prometheus Operator 来抓取 Service 对应 Endpoints 上的监控数据。

参考:https://cloud.tencent.com/document/product/1416/55995

既然都上了 kubernetes 环境了,一般当然是推荐直接用 podMonitor。配置更简洁易懂。podMonitorSelector 的过滤在 prometheus-prometheus.yaml 配置。

prometheus-prometheus.yaml 是核心配置文件,不宜频繁修改 (会导致 Prometheus 重启)。

主要配置项为:serviceMonitorSelector,podMonitorSelector,ruleSelector,alertmanagers。

其中 service 监控选择器和 pod 监控选择器默认选择所有,这里建议把 ruleSelector 也修改为选择所有。

不过一个 podMonitor 一般只对应一种类型的 pod,在已有 pod 类型较多的情况下,还可以考虑一种更取巧的方法就是 Prometheus 的 kubernetes 服务发现功能。即 kubernetes_sd_config。这种属于原生 Job 配置,建议使用 additional-scrape-config[1] 进行配置。

kubernetes_sd_config[2] 赋予了 Prometheus 通过 kubernetes rest api 感知 kubernetes 资源的功能,利用该能力,可以使用原生 Job 配置自动发现 pod,将其作为监控目标。再利用 Prometheus 的 Relabel 功能[3]可以改写发现的标签,进行前置处理、转换。实现 pod 筛选,修改抓取配置的效果。而自动发现的 pod 的标签的来源又可以是 pod 资源的 label/annotation 等。

最终实现的效果如下:

这是一个 pushGateway 的 pod 的配置 , 则 Prometheus 会通过其 19091 端口访问 /metrics 路径获取其指标数据

  annotations:    prometheus.io/scrape: "true"    prometheus.io/scheme: "http"    prometheus.io/path: "/metrics"    prometheus.io/port: "19091"
复制代码

这部分的内容主要参考:

  • https://godleon.github.io/blog/Prometheus/Prometheus-Relabel

  • https://yunlzheng.gitbook.io/prometheus-book/part-iii-prometheus-shi-zhan/readmd/service-discovery-with-kubernetes

podMonitor 是官方支持,简洁易懂。kubernetes_sd_config+relabel 的方案较复杂,难度较高,但不用写那么多的 podMonitor。自行抉择就行,也可以一起用。

告警设计

告警流程

prometheus 的监控告警基本流程是:

  1. 服务发生异常

  2. 触发 prometheus 服务器发出告警信息(alert)

  3. alertmanager 收到告警信息

  4. alertmanager 根据预配置的规则对告警信息进行处理,实现业务逻辑,如分组、抑制、触发短信邮箱等

当然具体的流程没那么简单,有很多细节需要注意,特别是触发告警时机,是个重点。

这些属于 Prometheus 的机制实现,这里就不展开赘述,推荐阅读以下文章:

  • Prometheus 一条告警的触发流程、等待时间[4]

  • AlertManager 何时报警[5]

后边会给出一个本人实际应用测试的例子,可供参考,会直观一些。

告警的动态配置

kube-prometheus 的告警规则分两部分:

  1. alertmanager: 即对告警信息的处理策略

    配置参考:https://yunlzheng.gitbook.io/prometheus-book/parti-prometheus-ji-chu/alert/alert-manager-config

    核心是 alertmanager-secret.yaml 配置文件,该文件以 secret 的形式被 Alertmanager 读取。Alertmanager 会自动读取 secret 中的配置进行更新。

  2. alertRule: 即具体的告警规则

    配置参考:https://yunlzheng.gitbook.io/prometheus-book/parti-prometheus-ji-chu/alert/prometheus-alert-rule

    在 kubernetes 中是以 PrometheusRule 类型操作,所以管理起来跟 pod 一样,直接使用 kubelet 增删改即可。

接入自定义告警平台

从个人实践的角度来看,AlertManager 处理 web hook 之外的告警接收插件,如短信、邮箱等只适合测着玩。生産使用还是要通过 web hook 将告警信息发送到自己的告警平台。可以根据业务需要对告警信息做高度定制化处理、记录等。另外可以在告警信息中携带具体告警规则等信息指导告警平台进行处理。

这里要做个区分,AlertManager 是告警信息的前置处理,负责非业务性前置操作,如告警信息分组、平抑等。而自定义告警平台则负责告警信息的业务处理,如记录、去敏、发送到多终端等。

AlertManager 可能收到 1w 条告警信息,经过处理最终只发了 1 条到自定义告警平台。而自定义告警平台可以将这 1 条告警信息记录起来,修改内容,同时使用邮箱、短信通知到多个负责人。

告警层级标签设计

监控对象的粒度决定告警的层级,体现在配置上则是告警规则的分组。分组信息决定 alertManager 的处理方式。

alertManager 对告警信息的路由策略是树状的,所以可通过多个分组标签实现多层级路由处理。

具体设计应结合业务需求,不在这里展开,感兴趣的可以看我下面的实现举例。

技术实现

技术实现主要分以下几部分:

  1. kubernetes 环境下 prometheus 的部署 (kube-prometheus)

  2. kube-prometheus 的增强配置 : 即 kubernetes_sd_config+relabel 方案的实现

  3. bigdata-exporter 的实现

  4. 告警设计实例

kubernetes 环境下 prometheus 的部署

1) kube-prometheus vs prometheus-operator

github 上 coreos 下有两个项目:kube-prometheus 和 prometheus-operator,两者都可以实现 prometheus 的创建及管理。

需要注意的是,kube-prometheus 上的配置操作也是基于 prometheus-operator 的,并提供了大量的默认配置,故这里使用的是 kube-prometheus 项目的配置。

另外使用前需注意 k8s 版本要求,找到对应的 kube-prometheus 版本,弄清楚对应的 prometheus-operator 版本。如:k8s1.14 版本最高可使用 kube-prometheus 0.3,对应的 prometheus-operator 版本是 0.32,阅读文档时注意对应版本。

2) kube-prometheus 使用前说明

kube-prometheus 使用 jsonnet 编写配置模板文件,生成 k8s 配置清单。已提供默认清单文件,在 manifests 文件夹下。如果需要修改默认清单配置,需要在 go 环境下使用 jp 编译清单。

下面都以默认配置为例

3) 安装教程

参考官方说明即可

1、git clone 项目 并切换到指定分支

2、kubectl create

清单文件中各配置已附带 namespace 信息,故执行时不需要指定 namespace,否则可能出错。

官方命令如下:

#Create the namespace and CRDs, and then wait for them to be availble before creating the remaining resources   $ kubectl create -f manifests/setup$ until kubectl get servicemonitors --all-namespaces ; do date; sleep 1; echo ""; done$ kubectl create -f manifests/
复制代码

kubernetes_sd_config+relabel 方案的实现

见:https://github.com/linshenkx/kube-prometheus-enhance

bigdata-exporter 的实现

hdfs、yarn、hbase、yarn 等组件都提供了 web 获取 jmx 指标的方式。

这里的思路是使用一个 bigdata-exporter,去采集多个组件多个节点的指标数据,并进行转换,然后以 Prometheus 规定的格式对外公开。

指标数据的转换规则可以查看 github 上的一些项目,要注意版本,也可以像我一样自己写,更可靠。

bigdata-exporter 如何感知到采集目标?

除了部署 ip 不同,不同组件不同角色的指标对外端口、路径、内容(解析规则)也都不一样。

这里可以参考上面 kubernetes_sd_config+relabel 的方案,做得优雅一些:

  1. 授予 bigdata-exporter 调用 kubernetes app 的能力,

  2. 利用 label 和 annotations 进行筛选和信息传递,确定捕捉目标和途径。

  3. 使用 role 代表解析内容的类型,根据 role 确定解析规则

  labels:    bigData.metrics.object: pod  annotations:    bigData.metrics/scrape: "true"    bigData.metrics/scheme: "https"    bigData.metrics/path: "/jmx"    bigData.metrics/port: "29871"    bigData.metrics/role: "hdfs-nn,common"
复制代码

告警设计示例

这里以实例两个维度为例,用 groupId 和 instanceId 表示。

1) alertManager 配置示例

以下是 alertmanager 的规则配置,有两个接收者,其中 test.web.hook 指向自定义告警平台。default 是空白接收者,不做处理。路由策略是根据 groupId,instanceId 分组,对节点磁盘使用率、kafka 队列堆积两个组处理,instanceId 还没有展开。

旧版本是用 secret 的 data 字段,需要将配置内容转成 base64 编码格式。新版本直接用 stringData 字段。推荐用 stringData 字段配置。其实只要看一下 kube-prometheus 的 alertmanager-secret.yaml 文件就知道怎么回事了。

使用 data 字段的配置方法:写好 config 文件,以 alertmanager.yaml 命名(不能使用其他名称)。执行以下命令 , 即可更新 secret。

$ kubectl -n monitoring create secret generic alertmanager-main --from-file=alertmanager.yaml --dry-run -o yaml  |  kubectl -n=monitoring apply -f -
复制代码


global:  resolve_timeout: 5mreceivers:  - name: 'default'  - name: 'test.web.hook'    webhook_configs:      - url: 'http://alert-url'route:  receiver: 'default'  group_wait: 30s  group_interval: 5m  repeat_interval: 2h  group_by: [groupId,instanceId]  routes:    - receiver: 'test.web.hook'      continue: true      match:        groupId: node-disk-usage    - receiver: 'test.web.hook'      continue: true      match:        groupId: kafka-topic-highstore
复制代码

2) alertRule 配置示例

组代表一个类型的所有目标:即所有节点。实例则代表具体的某个节点。

disk-usage.yaml 磁盘使用率告警配置示例如下:

注意:${path} 为监控的磁盘路径,${thresholdValue} 为使用率阈值,需自行替换。labels 中的 userIds 和 receivers 为传递给自定义告警平台的参数,以指导告警平台如何操作。

在这个任务中,我们的目标是组粒度的(所有节点),所以不需要设置 instanceId。

apiVersion: monitoring.coreos.com/v1kind: PrometheusRulemetadata:   creationTimestamp: null   labels:      role: alert-rules   name: node-disk-usage   namespace: monitoringspec:   groups:      - name: node-disk-usage        rules:           - alert: node-disk-usage             expr: 100*(1-node_filesystem_avail_bytes{mountpoint="${path}"}/node_filesystem_size_bytes{mountpoint="${path}"} ) > ${thresholdValue}             for: 1m             labels:                groupId: node-disk-usage                userIds: super                receivers: SMS             annotations:                title: "磁盘警告:节点{{$labels.instance}}的 ${path} 目录使用率已达到{{$value}}%"                content: "磁盘警告:节点{{$labels.instance}}的 ${path} 目录使用率已达到{{$value}}%"
复制代码

kafka-topic-highstore.yaml kafka 队列消费堆积告警配置示例如下:

我们只关心个别队列的消费情况,所以这里的粒度为 instance。

注意:${uniqueName} 为队列名,${consumergroup} 为消费组名称,${thresholdValue} 为堆积数量阈值。

apiVersion: monitoring.coreos.com/v1kind: PrometheusRulemetadata:  creationTimestamp: null  labels:    role: alert-rules  name: kafka-topic-highstore-${uniqueName}  namespace: monitoringspec:  groups:    - name: kafka-topic-highstore      rules:      - alert: kafka-topic-highstore-${uniqueName}        expr: sum(kafka_consumergroup_lag{exporterType="kafka",consumergroup="${consumergroup}"}) > ${thresholdValue}        for: 1m        labels:          groupId: kafka-topic-highstore          instanceId: ${uniqueName}          userIds: super          receivers: SMS        annotations:          title: "KAFKA警告:消费组 ${consumergroup}的堆积数量达到:{{$value}}"          content: "KAFKA警告:消费组 ${consumergroup}的堆积数量达到:{{$value}}"
复制代码


发布于: 刚刚阅读数: 4
用户头像

学如逆水行舟,不进则退 2022.08.05 加入

大型企业CTO,专注大数据、架构框架、集群、中间件、分布式、数据库、监控、开源、基础架构等技术分享,助力数字化转型。

评论

发布
暂无评论
kube-prometheus 监控系统使用与总结_CTO技术共享_InfoQ写作社区