Overview Link to heading
Kubernetes events 提供了丰富的信息来源。这些对象可以用来监控应用程序和集群状态、反映故障原因(reason)以及进行诊断。当集群的资源如:Pod、Deployment 或 Node 状态发生变化时,就会生成 events。Event 的保留时间有限,触发器和消息可能会随着时间的推移而演变。事件消费者不应假定给定原因的事件的时间所反映的是一致的下层触发因素,或具有该原因的事件的持续存在(简单来说,event 就是过去某个时间点集群某个资源发生的变动,这个记录的存在并不代表这个变动一直在持续,这个变动在发生时就被记录下来存储在 etcd 中,但它不会长时间保存(默认保存 1 小时),过期的 event 会被轮转淘汰掉)。 Events 应被视为通知性质的、尽最大努力而提供的补充数据。
由于 events 的保存时间有限,对于一些需要向后长时间追述某事件内容的场景(比如故障复盘、集群运行报告),默认的保留时长无法满足这一需求,而直接延长 events 保留时长会导致 etcd 负载增加。因此一个可靠的 events 持久化保存方案是非常有必要的,同时 events 持久化保存方案应该提供查询接口,以便我们可以方便的查询到需要的事件内容,并对事件进行实时监控同时不增加 etcd 负载。
现有方案 Link to heading
业界有不少 events 持久化方案,比如:
- KubeCon 2019 San Diego 上展示的 kubernetes-event-exporter。这个工具允许将常被忽视的 Kubernetes 事件导出到各种输出格式,以便用于可观察性或警报目的。它可以将采集到的 events 导出到 Elasticsearch、File、Stdout、Kafka、Slack 等。
- kube-eventer。一个事件发射器,用于将 Kubernetes 事件发送到接收器(例如,dingTalk、SLS、kafka 等)。Kubernetes 的核心设计理念是状态机。因此,当转移到所需状态时,将出现正常事件,而当转移到意外状态时,将出现警告事件。kube-eventer 可以帮助诊断、分析和警报问题。
这些工具都是非常优秀的 events 持久化方案,可以看作是 events 持久化保存的最佳实践之一。其工作原理基本一致:请求 Kubernetes Events API(“k8s.io/api/events/v1”),获取当前最新的 events 并通过序列化为指导输出插件的输出格式,将 event 内容发送到输出插件中,再由输出插件将 event 内容输出到数据库、文件、消息队列、Kafka、及时通讯工具等中。
这两个工具都是云解决方案供应商开源的,最近更新频率较低,kubernetes-event-exporter 已停止维护,kube-eventer 最新版本为发布于 2023 年 5 月 31 日的 v1.2.7。可见这两个工具的维护情况并不乐观,其可靠性和安全性难以保证。
一种最新的且通用的方案 Link to heading
接下来介绍一种新的通用方案,该方案不单独开发 events 数据采集工具,而是利用已有的 kubernetes events API 和通用且成熟的集群日志采集工具:FluentBit,来实现 events 数据采集、输出,同时使用 VictoriaLogs 来持久化保存 events 数据并提供方便的查询接口。
原理 Link to heading
- Kubernetes 通过 API server 暴露 events;
- FluentBit 的 Inputs 插件:Kubernetes Events将这些事件作为日志检索并通过管道对其进行处理;
- FluentBit 的 Outputs 插件:HTTP将检索到的事件数据发送到 HTTP 服务器;
- HTTP 服务器即 VictoriaLogs 将通过其 insert 接口接收到的事件数据持久化保存到 VictoriaLogs 集群中。
收集事件| C[FluentBit Processor] C -->|格式化/过滤数据| D[FluentBit Output] D -->|HTTP插件
发送数据| E[VictoriaLogs
/insert 接口] E -->|数据持久化| F[VictoriaLogs Cluster] classDef k8s fill:#326CE5,color:white; classDef fluentbit fill:#00B8D9,color:white; classDef victorialogs fill:#FF6B6B,color:white; class A k8s; class B,C,D fluentbit; class E,F victorialogs;
实现 Link to heading
0. 准备一个 VictoriaLogs 集群; Link to heading
可以参考 VictoriaLogs 官方文档,部署 VictoriaLogs 集群。
对于测试和演示环境,也可以使用 atompi 的 container-labs 项目中的 victorialogs 子项目,通过 docker-compose 一键启动本地 VictoriaLogs 服务。
1. 集群中部署 FluentBit; Link to heading
所有部署 FluentBit 所需的 manifest 文件已发布到 atompi/kind-tour。这里讲解其中的几个关键文件:
- clusterrole-fluentbit-read.yaml 为 FluentBit 创建一个 ClusterRole,用于访问 Kubernetes API Server 中的 events 资源。
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fluentbit-read
rules:
- nonResourceURLs:
- /metrics
verbs:
- get
- apiGroups: [""]
resources:
- namespaces
- pods
- pods/logs
- nodes
- nodes/proxy
- events
verbs: ["get", "list", "watch"]
- clusterrolebinding-fluentbit-read.yaml 将 ClusterRole fluentbit-read 绑定到 FluentBit 的 ServiceAccount(这里是:kube-event)上。
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: fluentbit-read
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: fluentbit-read
subjects:
- kind: ServiceAccount
name: kube-event
namespace: default
- serviceaccount-kube-event.yaml 为 FluentBit 创建一个 ServiceAccount,用于访问 Kubernetes API Server 中的 events 资源,对应上面的 clusterrolebinding。
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: fluentbit
name: kube-event
- externalservice-victorialogs.yaml 为 FluentBit 创建一个 ExternalService,用于访问 VictoriaLogs 集群中的 VictoriaLogs API。
---
apiVersion: v1
kind: Service
metadata:
name: victorialogs
labels:
app: victorialogs
spec:
type: ClusterIP
clusterIP: None
ports:
- name: victorialogs
port: 9428
targetPort: 9428
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: victorialogs
labels:
app: victorialogs
subsets:
- addresses:
- ip: 192.168.220.128
ports:
- name: victorialogs
port: 9428
protocol: TCP
-
deployment.yaml 为 FluentBit 的工作负载 manifest。
-
configmap-fluentbit-config.yaml 为 FluentBit 的配置文件 manifest。
---
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentbit-config
labels:
app: fluentbit
data:
fluentbit.conf: |
[SERVICE]
flush 1
log_level info
[INPUT]
name kubernetes_events
tag k8s_events
kube_url https://kubernetes.default.svc
[OUTPUT]
Name http
Match k8s_events
host victorialogs
port 9428
uri /insert/jsonline?_stream_fields=stream&_msg_field=message&_time_field=date
format json_lines
json_date_format iso8601
这里需要注意的是:
victorialogs
:FluentBit 输出到 VictoriaLogs 的地址,对应我们上面创建的 external service。uri
: FluentBit 输出到 VictoriaLogs 的接口地址,对应 VictoriaLogs 的 insert 接口,这里_msg_field
表示 VictoriaLogs 中_msg
字段(日志内容)对应的传入的字段名,根据 Kubernetes events API 的文档,_msg_field
为message
。
Tips: FluentBit 采集到的 events 数据格式为:
{
"kind": "Event",
"apiVersion": "v1",
"metadata": {
"name": "fluentbit.18380b7267724f60",
"namespace": "default",
"uid": "9fdd45b2-88e5-4760-944c-da5c3e54715b",
"resourceVersion": "43949",
"creationTimestamp": "2025-04-20T13:57:21Z"
},
"involvedObject": {
"kind": "Deployment",
"namespace": "default",
"name": "fluentbit",
"uid": "4f8d6ecd-c6c9-4320-a36a-220f88c20a0a",
"apiVersion": "apps/v1",
"resourceVersion": "43940"
},
"reason": "ScalingReplicaSet",
"message": "Scaled down replica set fluentbit-64fdc795fb to 0 from 1",
"source": {
"component": "deployment-controller"
},
"firstTimestamp": "2025-04-20T13:57:21Z",
"lastTimestamp": "2025-04-20T13:57:21Z",
"count": 1,
"type": "Normal",
"eventTime": null,
"reportingComponent": "deployment-controller",
"reportingInstance": ""
}
部署后集群中仅运行了一个 FluentBit pod,非常轻量化!
- 通过 vmui 查询 events 数据。
vmui 是 VictoriaMetrics 家族的一个可视化工具,可以查看 VictoriaMetrics 家族中 Metrics 集群和 Logs 集群中的所有数据,这里我们通过 vmui 查询 events 数据。
结语 Link to heading
该方案的亮点在于:不依赖单独开发的专用的 events 数据采集工具,而是利用已有的 kubernetes events API 和通用且成熟的集群日志采集工具:FluentBit,来实现 events 数据采集、输出,同时使用 VictoriaLogs 来持久化保存 events 数据并提供方便的查询接口。
整个方案所依赖的工具均为当前开源社区活跃度高的开源社区项目,且已稳定运行在多个生产环境,因此非常值得推荐。