转载自:https://www.qikqiak.com/post/prometheus-monitor-k8s-job-trap/

昨天在 Prometheus 课程辅导群里面有同学提到一个问题,是关于 Prometheus 监控 Job 任务误报的问题,大概的意思就 CronJob 控制的 Job,前面执行失败了,监控会触发报警,解决后后面生成的新的 Job 可以正常执行了,但是还是会收到前面的报警:


这是因为一般在执行 Job 任务的时候我们会保留一些历史记录方便排查问题,所以如果之前有失败的 Job 了,即便稍后会变成成功的,那么之前的 Job 也会继续存在,而大部分直接使用 kube-prometheus 安装部署的话使用的默认报警规则是kube_job_status_failed > 0,这显然是不准确的,只有我们去手动删除之前这个失败的 Job 任务才可以消除误报,当然这种方式是可以解决问题的,但是不够自动化,一开始没有想得很深入,想去自动化删除失败的 Job 来解决,但是这也会给运维人员带来问题,就是不方便回头去排查问题。下面我们来重新整理下思路解决下这个问题。 CronJob 会在计划的每个执行时间创建一个 Job 对象,可以通过 .spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit 属性来保留多少已完成和失败的 Job,默认分别为3和1,比如下面声明一个 CronJob 的资源对象: apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date;
restartPolicy: OnFailure 根据上面的资源对象规范,Kubernetes 将只保留一个失败的 Job 和一个成功的 Job: NAME COMPLETIONS DURATION AGE
hello-4111706356 0/1 2m 10d
hello-4111706356 1/1 5s 5s 要解决上面的误报问题,同样还是需要使用到 kube-state-metrics 这个服务,它通过监听 Kubernetes APIServer 并生成有关对象状态的指标,它并不关注单个 Kubernetes 组件的健康状况,而是关注内部各种对象的健康状况,例如 Deployment、Node、Job、Pod 等资源对象的状态。这里我们将要使用到以下几个指标: kube_job_owner:用来查找 Job 和触发它的 CronJob 之间的关系
kube_job_status_start_time:获取 Job 被触发的时间
kube_job_status_failed:获取执行失败的任务
kube_cronjob_spec_suspend:过滤掉挂起的作业 下面是一个指标示例,其中包含 CronJob 触发运行的hello 任务生成的标签: kube_job_owner{job_name="hello-1604875860", namespace="myNamespace", owner_is_controller="true", owner_kind="CronJob", owner_name="hello"} 1
kube_job_status_start_time{job_name="hello-1604875860", namespace="myNamespace"} 1604875874
kube_job_status_failed{job_name="hello-1604875860", namespace="myNamespace", reason="BackoffLimitExceeded"} 1
kube_cronjob_spec_suspend{cronjob="hello",job="kube-state-metrics", namespace="myNamespace"} 0 要想做到监控报警准确,其实我们只需要去获取同一个 CronJob 触发的一组 Job 的最后一次任务,只有该 Job 在执行失败的时候才触发报警即可。 由于 kube_job_status_failed 和 kube_job_status_start_time 指标中并不包含所属 CronJob 的标签,所以第一步需要加入这个标签,而 kube_job_owner 指标中的 owner_name 就是我们需要的,可以用下面的 promql 语句来进行合并: max(
kube_job_status_start_time
* ON(job_name, namespace) GROUP_RIGHT()
kube_job_owner{owner_name != ""}
)
BY (job_name, owner_name, namespace) 这里我们使用 max 函数是因为我们可能会因为 HA 运行多个 kube-state-metrics,所以用 max 函数来返回每个 Job 任务的一个结果即可。假设我们的 Job 历史记录包含 2 个任务(一个失败,另一个成功),结果将如下所示: {job_name="hello-1623578940", namespace="myNamespace", owner_name="hello"} 1623578959
{job_name="hello-1617667200", namespace="myNamespace", owner_name="hello"} 1617667204 现在我们知道每个 Job 的所有者了,接着我们需要找出最后执行的任务,我们可以通过按 owner_name 标签聚合结果来实现这一点: max(
kube_job_status_start_time
* ON(job_name,namespace) GROUP_RIGHT()
kube_job_owner{owner_name!=""}
)
BY (owner_name) 上面这条语句会找到每个 owner(也就是 CronJob)最新的任务开始时间,然后再和上面的语句进行合并,保留开始时间相同的记录即为最新执行的 Job 任务了: max(
kube_job_status_start_time
* ON(job_name,namespace) GROUP_RIGHT()
kube_job_owner{owner_name!=""}
)
BY (job_name, owner_name, namespace)
== ON(owner_name) GROUP_LEFT()
max(
kube_job_status_start_time
* ON(job_name,namespace) GROUP_RIGHT()
kube_job_owner{owner_name!=""}
)
BY (owner_name) 结果将显示每个 CronJob 最后执行的作业,并且仅显示最后一个: {job_name="hello-1623578940", namespace="myNamespace", owner_name="hello"} 1623578959 为了增加可读性我们还可以将 job_name、owner_name 标签替换为 job 和 cronjob,这样更容易看明白: label_replace(
label_replace(
max(
kube_job_status_start_time
* ON(job_name,namespace) GROUP_RIGHT()
kube_job_owner{owner_name!=""}
)
BY (job_name, owner_name, namespace)
== ON(owner_name) GROUP_LEFT()
max(
kube_job_status_start_time
* ON(job_name,namespace) GROUP_RIGHT()
kube_job_owner{owner_name!=""}
)
BY (owner_name),
"job", "$1", "job_name", "(.+)"),
"cronjob", "$1", "owner_name", "(.+)") 现在将会看到类似于下面的结果: {job="hello-1623578940", cronjob="hello", job_name="hello-1623578940", namespace="myNamespace", owner_name="hello"} 1623578959 由于上面的查询语句比较复杂,如果每次报警评估的时候都去进行一次实时计算会对 Prometheus 产生非常大的压力,这里我们可以借助记录规则来实现类离线计算的方式,大大提高效率,创建如下所示的记录规则,用来表示获取每个 CronJob 最后执行的作业记录: - record: job:kube_job_status_start_time:max
expr: |
label_replace(
label_replace(
max(
kube_job_status_start_time
* ON(job_name,namespace) GROUP_RIGHT()
kube_job_owner{owner_name!=""}
)
BY (job_name, owner_name, namespace)
== ON(owner_name) GROUP_LEFT()
max(
kube_job_status_start_time
* ON(job_name,namespace) GROUP_RIGHT()
kube_job_owner{owner_name!=""}
)
BY (owner_name),
"job", "$1", "job_name", "(.+)"),
"cronjob", "$1", "owner_name", "(.+)") 现在我们知道了 CronJob 最近开始执行的 Job 了,那么想要过滤出失败的,则再使用 kube_job_status_failed 指标就可以了: - record: job:kube_job_status_failed:sum
expr: |
clamp_max(job:kube_job_status_start_time:max, 1)
* ON(job) GROUP_LEFT()
label_replace(
(kube_job_status_failed > 0),
"job", "$1", "job_name", "(.+)"
) 这里使用 clamp_max 函数将 job:kube_job_status_start_time:max 的结果转换为一组上限为 1 的时间序列,使用它来通过乘法过滤失败的作业,得到包含一组最近失败的 Job 任务,这里我们也添加到名为 kube_job_status_failed:sum 的记录规则中。 最后一步就是直接为失败的 Job 任务添加报警规则,如下所示: - alert: CronJobStatusFailed
expr: |
job:kube_job_status_failed:sum
* ON(cronjob, namespace) GROUP_LEFT()
(kube_cronjob_spec_suspend == 0) 为避免误报,我们已将挂起的任务排除在外了。到这里我们就解决了 Prometheus 监控 CronJob 的任务误报的问题,虽然 kube-prometheus 为我们内置了大量的监控报警规则,但是也不能完全迷信,有时候并不一定适合实际的需求。

Prometheus 监控 Kubernetes Job 资源误报的坑的更多相关文章

  1. 第15章: Prometheus监控Kubernetes资源与应用

    Prometheus监控Kubernetes资源与应用 目录 1 监控方案 2 2 监控指标 4 3 实现思路 4 4 在K8S中部署Prometheus 4 5 在K8S中部署Grafana与可视化 ...

  2. Kubernetes集群部署史上最详细(二)Prometheus监控Kubernetes集群

    使用Prometheus监控Kubernetes集群 监控方面Grafana采用YUM安装通过服务形式运行,部署在Master上,而Prometheus则通过POD运行,Grafana通过使用Prom ...

  3. Prometheus监控学习笔记之解读prometheus监控kubernetes的配置文件

    0x00 概述 Prometheus 是一个开源和社区驱动的监控&报警&时序数据库的项目.来源于谷歌BorgMon项目.现在最常见的Kubernetes容器管理系统中,通常会搭配Pro ...

  4. 部署prometheus监控kubernetes集群并存储到ceph

    简介 Prometheus 最初是 SoundCloud 构建的开源系统监控和报警工具,是一个独立的开源项目,于2016年加入了 CNCF 基金会,作为继 Kubernetes 之后的第二个托管项目. ...

  5. Kubernetes容器集群管理环境 - Prometheus监控篇

    一.Prometheus介绍之前已经详细介绍了Kubernetes集群部署篇,今天这里重点说下Kubernetes监控方案-Prometheus+Grafana.Prometheus(普罗米修斯)是一 ...

  6. 监控 -- kubernetes -- prometheus

    1.但是Heapster无法做Kubernetes下应用的监控.现在,Heapster作为Kubernetes下的开源监控解决方案已经被其弃用,Prometheus成为Kubernetes官方推荐的监 ...

  7. Kubernetes学习之路(二十四)之Prometheus监控

    目录 1.Prometheus概述 2.Prometheus部署 2.1.创建名称空间prom 2.2.部署node_exporter 2.3.部署prometheus-server 2.4.部署ku ...

  8. [转帖]Prometheus+Grafana监控Kubernetes

    原博客的位置: https://blog.csdn.net/shenhonglei1234/article/details/80503353 感谢原作者 这里记录一下自己试验过程中遇到的问题: . 自 ...

  9. Prometheus Operator 监控Kubernetes

    Prometheus Operator 监控Kubernetes 1. Prometheus的基本架构 ​ Prometheus是一个开源的完整监控解决方案,涵盖数据采集.查询.告警.展示整个监控流程 ...

随机推荐

  1. Oracle 用户密码中包括了“@”字符串的错误提示解决方法

    Oracle 用户密码设置了带有"@"符号,正常登陆总是无法登陆,提示无法解析的连接字符串错误 解决办法:1:修改密码:修改密码使密码中不包括@符号:2:增加转义即可,在密码前后增 ...

  2. JDBCToolsV2:利用ThreadLocal保证当前线程操作同一个数据库连接对象。

    JDBCToolsV2:     利用ThreadLocal保证当前线程操作同一个数据库连接对象. package com.dgd.test; import com.alibaba.druid.poo ...

  3. ReentrantLock 公平锁源码 第2篇

    Reentrant 2 前两篇写完了后我自己研究了下,还有有很多疑惑和问题,这篇就继续以自问自答的方式写 如果没看过第1篇的可以先看看那个https://www.cnblogs.com/sunanka ...

  4. 一个思维导图,带你深入理解 Linux 网络

    说明 思维导图 目录 内核接收网络包 内核与用户进程协作 内核发送网络包 TCP 连接 网络性能优化 GitHub 项目 说明 经朋友推荐发现一本好书:<深入理解 Linux 网络>,本文 ...

  5. zenmap安装

    发现最新版的KALI不带zenmap了,下面是安装步骤: 安装包转换工具:sudo apt-get install alien fakeroot -y 下载并转换:https://nmap.org/d ...

  6. error: cannot open .git/FETCH_HEAD: Permission denied

    可能原因:该操作的执行者对该目录没有写权限 解决:1.类Unix平台,使用chown将目录改为自己: 2.Windows平台,取消只读选项,给everyone用户所有权限:

  7. Kafka入门实战教程(7):Kafka Streams

    1 关于流处理 流处理平台(Streaming Systems)是处理无限数据集(Unbounded Dataset)的数据处理引擎,而流处理是与批处理(Batch Processing)相对应的.所 ...

  8. Vue 父组件传递给子组件,设置默认值为数组或者对象时

    在vue 父子组件传参过程中,传递对象或者数组时,设置默认值为{}或者[] 错误写法: props: { pos: { type: [Object, Array], default: []//这是错误 ...

  9. [BJDCTF2020]Cookie is so stable-1|SSTI注入

    1.打开之后在各个界面查看源代码,未发现很明显的有用信息,仅发现了提示,结果如下: 2.尝试输入数据,结果就是输入什么就回显什么,也未进行过滤,尝试进行sql注入失败,结果如下: 3.那就根据提示抓包 ...

  10. Yii项目知识搜集

    [['rId','advertiser_id','image_file'], 'unique','targetAttribute'=>['rId','advertiser_id','image_ ...