目录

k8s-eventer和bark联动

概述

众所周知 k8s 的 Event 存活的时间是有 ttl 控制的,因为都会存到 Etcd 里的,所以不能一直存着。如果在排查问题的时候,想找找之前的 Event,那就必须有旁路的组件逻辑去采集,或者说把 Event 按照等级进行告警,并且把具体的 Event 接入到企业的告警链路,这样价值就很大了,毕竟现在大部分告警都是基于指标,也就是 Prometheus 的那一套,但是指标归指标,有时候容器真正出现什么问题了,在指标上很难进行转换并且告知到相关负责人,但是 Event 就不一样了,Event 有具体 message 的信息,在触发产生 Warning 等级的 Event 的时候,可以作为告警信息发送出去。

本文主要介绍一下 kube-eventer 和 bark 的在 Kubernetes 事件告警的场景中的联合使用。

Event数据结构

可以看到,其实一个 Event 的信息并不太详细,如果写入 Kafka/ES 之类的,并且作为平台呈现给用户的时候,那么用户怎么去查对应的事件呢?有点麻烦,当然可以用 involvedObject 这个字段去检索,但是里面的字段其实不太丰富,如果这样直接入库,似乎检索的场景有点有限。于是很正常的,会想到能不会给 event 也打些标签呢,比如说通过 watch 事件,然后 onAdd 的时候给他打上 pod 的一些 label?问题不大,但是可能要考虑一下,如果集群是比较忙的,会产生很多 event 的,如果每个 event 都这么粗暴的加上一堆 label,那么存入 etcd 肯定会有额外的压力的,相对来说,这可能不是一个特别好的方法。

当我们在设计事件中心的时候,其实可以在采集或者写入到目标地址前,通过一次 k8s 的客户端的查询,来获取一些 pod 或者其他类型资源对象的 label,或者一些如 ip 之类的信息,组合到即将入库的 event 中,当然这个时候 event 可能是一个 json 或者是事件中心进程内存里的一个对象,加多少 label 也不会对 k8s 集群有什么压力的,当然了,因为需要再查一次 pod 或者 deployment 之类的,这里肯定也会有一些网络开销,但是基本可以忽略不计吧。

 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
{
    "apiVersion": "v1",
    "items": [
        {
            "apiVersion": "v1",
            "count": 109050,
            "eventTime": null,
            "firstTimestamp": "2022-01-09T06:26:12Z",
            "involvedObject": {
                "apiVersion": "policy/v1beta1",
                "kind": "PodDisruptionBudget",
                "name": "zk-pdb",
                "namespace": "zookeeper",
                "resourceVersion": "5087419",
                "uid": "36509393-7b93-4cd6-b3bc-bfde71c1e7ca"
            },
            "kind": "Event",
            "lastTimestamp": "2022-02-16T03:11:21Z",
            "message": "No matching pods found",
            "metadata": {
                "creationTimestamp": "2022-01-09T06:26:12Z",
                "name": "zk-pdb.16c8862865eaa160",
                "namespace": "zookeeper",
                "resourceVersion": "26938703",
                "selfLink": "/api/v1/namespaces/zookeeper/events/zk-pdb.16c8862865eaa160",
                "uid": "4380614c-7167-495a-bc07-2edb87fea660"
            },
            "reason": "NoPods",
            "reportingComponent": "",
            "reportingInstance": "",
            "source": {
                "component": "controllermanager"
            },
            "type": "Normal"
        }
    ],
    "kind": "List",
    "metadata": {
        "resourceVersion": "",
        "selfLink": ""
    }
}

bark私有化部署

bark 是 IOS 上比较流行的消息组件,为了数据安全,可以选择私有化部署 bark 的服务端,可以参考 官方文档

1
docker run -dt --restart=always --name bark -p 8680:8080 -v `pwd`/bark-data:/data finab/bark-server

这里可以注意的是,不是非要公有云服务器才能实现的,只是 APP 端会有报错,但是消息还是照常推送的,如果是懒得做 https 等安全措施,直接在局域网内部署即可,另外 bark 在 APP 端还支持重置 key,后者恢复之前的 key,这样即使 Docker 部署的 bark server 被删除了,APP 端也可以恢复之前的 key。

k8s-eventer和bark

kube-eventer 是阿里开源的一个 Kubernetes 事件采集器,支持多种 sink 的输出方式,比如说 Kafka、ElasticSearch、Webhook 等等。我们这里主要是使用 Webhook 的方式来实现 bark 的推送,部署的方式参考 官方文档 即可,因为本文给的例子是对接 bark,这个在 kube-eventer 没有详细说明,这里做个介绍。对于 bark 在 kube-eventer 里可以理解成 general 的 webhook,主要是通过 HTTP 的方式来发送消息,关于对接 bark 主要还是通知模板的编写,下面是结合 bark Post 消息和 kube-eventer 的模板提供的例子。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-body
  namespace: kube-system
data:
  content: '{
   "title": "☸️kube-eventer",
   "icon": "https://runzhliu.cn/images/avatar.png",
   "body":  "EventType:  {{ .Type }}\nEventKind:  {{ .InvolvedObject.Kind }}\nEventObject: {{ . }}\nEventReason:  {{ .Reason }}\nEventTime:  {{ .LastTimestamp }}\nEventMessage:  {{ .Message }}"
   }'

下面就是具体的效果了。

/k8s-eventer%E5%92%8Cbark%E8%81%94%E5%8A%A8/img.png

另外如果有需要的话,还可以手动创建一个 Event 测试一下这个功能。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Event
metadata:
  name: my-warning-event
  namespace: default
involvedObject:
  apiVersion: v1
  kind: Pod
  name: my-pod
  namespace: default
type: Warning
reason: HighCPUUsage
message: "The CPU usage has exceeded 80%."
source:
  component: custom-controller
firstTimestamp: "2025-04-16T10:00:00Z"
lastTimestamp: "2025-04-16T10:00:00Z"
count: 1

关于Event watch channel closed

issues#175,也记录过这个问题。

总结

笔者早年在前司也写过类似 Kubernetes 事件采集器,也是可以选择不同的 sink 把时间发送出去或者存储起来,年代有点久远了,且当时也没有开源。阿里开源的 kube-eventer 也很多年没有什么大的改动了,毕竟这并不是十分复杂的事情,主要还是对 Kubernetes 事件的处理和存储,当然也可以选择其他的存储方式,比如说 Kafka、ElasticSearch 等等。最后还是要考虑团队、公司使用的一些告警方式,是否需要私有化部署,是否需要公网入口等问题。本文就 kube-eventer 和 bark 的结合做了一个简单的介绍,当然也可以选择其他的告警方式,比如说钉钉、企业微信等,都是可以的。

参考资料

  1. bark文档