!! 大家好,我是乔克,一个爱折腾的运维工程,一个睡觉都被自己丑醒的云原生爱好者。
作者:乔克
公众号:运维开发故事
博客:www.jokerbai.com
Kubernetes中的事件监控
随着微服务以及云原生的发展,越来越多的企业都将业务部署运行到Kubernetes中,主要是想依托Kubernetes的可扩展、可伸缩、自动化以及高稳定性来保障业务的稳定性。
然而,Kubernetes本身是一个复杂的管理系统,它既然是作为企业业务的基础设施,其本身以及运行在集群内部的业务系统对于企业来说都变得非常重要。为此,在实际工作中,我们会借助需要的监控手段来提升Kubernetes本身以及业务的可观测性,常见的有:
- 使用cAdvisor来获取容器的资源指标,比如cpu、内存;
- 使用kube-state-metrics来获取资源对象的状态指标,比如Deployment、Pod的状态;
- 使用metrics-server来获取集群范围内的资源数据指标;
- 使用node-exporter等一系列官方以及非官方的exporter来获取特定组件的指标;
在大部分的监控场景中,我们都是对特定资源进行特定监控,比如Pod,Node等。但是,在Kubernetes中还有一些场景是无法通过资源来表述的,就是说它们不是特定的资源,比如Pod调度、重启,在Kubernetes中,这类场景主要称之为事件
。
在Kubernetes中,存在两种事件:
- Warning事件,事件的状态转换是在非预期的状态之间产生。
- Normal事件,期望达到的状态和目前的状态是一致的。
在这里,我们用Pod来进行说明。当创建Pod的时候,会先进入Pending状态,然后再进入Creating状态(主要是在拉取镜像),再进去NotReady状态(主要是应用启动并且等待健康检测通过),最后进入Running状态,这整个过程就会生成Normal事件。但是,如果在运行过程中,如果Pod因为一些异常原因进入其他状态,比如节点驱逐、OOM等,在这个状态转换的过程中,就会产生Warning事件。在Kubernetes中,我们可以通过其他办法来保障业务的稳定性,比如为了避免Pod调度到一个节点或者同可用区等而采用亲和性以及反亲和性调度,为了避免节点驱逐导致某个单个Pod不可用而采用的PDB等,也许某个Warning事件并不会对整个业务的稳定性带来致命的影响,但是如果能够通过监控事件的手段来感知集群的某个状态变化是有助于进行查漏补缺的,也有助于我们感知一些容易忽略的问题。
在Kubernetes中,所有事件都通过事件系统记录到APIServer中,并且最终存入在Etcd中,我们可以通过API或者kubectl进行查看,比如:
也可以查看某个对象的事件,比如:
事件包含了时间、类型、对象、原因以及描述等,通过事件我们能够知道应用的部署、调度、运行、停止等整个生命周期,也能通过事件去了解系统中正在发生的一些异常。在Kubernetes各个组件的源码中都会定义该组件可能会触发的事件类型,比如在kubelet的源码中定义了许多的事件类型,如下:
Kubernetes事件最终是存在Etcd中,默认只保存1小时,由于Etcd本身并不支持一些复杂的分析操作,只能被动地存在Etcd中,并不支持主动推送到其他系统,通常情况下只能手动去查看。
在实际中,我们对Kubernetes事件还有其他的需求,比如:
- 希望对异常的事件做告警处理;
- 希望查询更长事件的历史事件;
- 希望对集群事件进行灵活的统计分析;
为此,我们需要单独对Kubernetes事件进行收集,以便适用于查询以及告警。
在社区中,有很多工具来做事件的收集以及告警,我常用的两个工具是:
- kube-eventer:阿里云推出的事件收集工具;
- kube-event-exporter:Github上另外一个事件收集工作;
在实际工作中,可以选择使用其中一个,基本都能满足收集以及告警功能。在这里,我将同时使用上面两个插件,用kube-eventer来进行告警,用kube-event-exporter将事件收集到ES中进行查看和分析。
使用kube-eventer进行事件告警
kube-eventer的告警通道可以是企业微信、钉钉以及webhook。可以根据需要进行选择,每个组件的具体使用方法在项目的docs/en
目录中,这里选择使用webhook将告警发送到企业微信中。
(1)首先需要在企业微信群里创建一个webhook机器人,然后获取webhook地址。
(2)在Kubernetes集群中部署kube-eventer。
在webhook的配置中增加了level=Warning
,表示只要Warning事件才会告警通知,除此之外,还可以通过namespaces字段来过来需要告警的命名空间,通过kinds字段来过滤需要告警的对象,比如只需要发送Node的Warning事件,则可以写成level=warning&kinds=Node
。再比如,如果不想产生非常多的告警风暴,只发送某些特定原因的告警,比如系统OOM的事件,可以增加reason=SystemOOM
等待。
当kube-eventer的Pod启动完成后,企业微信即可收到满足条件的事件告警,比如:
使用kube-event-exporter收集集群事件
上面使用kube-eventer进行事件告警,本质上并没有存储历史事件,而实际中可能需要查询历史事件并且对其做一些事件分析,而ES是常用于进行内容收集并通过kibana进行查看和分析,所以这里我们将使用kube-event-exporter收集Kubernetes事件到ES中。
kube-event-exporter可以直接将事件存入ES,也可以将事件发送到kafka,然后再通过Logstash消费Kafka中的数据将其存入ES。在这里,我基于环境现状,将事件发送给Kafka,然后再消费收集到ES。
(1)部署kube-event-exporter
当kube-event-exporter的Pod启动过后,可以在kafka中查看到收集的事件,如下:
(2)部署logstash将事件存入ES
部署之前,先在ES中创建template,可以在kibana中的dev tools中进行操作,语句如下:
然后再在Kubernetes集群中部署Logstash。然后就可以在Kibana上查看收集到的事件了,如下:
只要数据有了,不论是查询还是做分析,都变得简单容易了。比如最简单得统计今天事件原因为Unhealthy
所发生的总次数,可以在Kibana中创建图表,如下:
以上就是在Kubernetes中对集群事件进行收集和告警,这是站在巨人的肩膀上直接使用。在企业中还可以对其进行二次开放以将功能更丰富,比如支持对事件告警增加开关,可以任意开启或者关闭某个事件告警。
链接
[1] https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/events/event.go?spm=a2c6h.12873639.article-detail.7.c8585c576FGh7o&file=event.go
[2] https://github.com/AliyunContainerService/kube-eventer
[3] https://github.com/resmoio/kubernetes-event-exporter
最后,求关注。如果你还想看更多优质原创文章,欢迎关注我们的公众号「运维开发故事」。
如果我的文章对你有所帮助,还请帮忙点赞、在看、转发一下,你的支持会激励我输出更高质量的文章,非常感谢!
你还可以把我的公众号设为「星标」,这样当公众号文章更新时,你会在第一时间收到推送消息,避免错过我的文章更新。
我是 乔克,《运维开发故事》公众号团队中的一员,一线运维农民工,云原生实践者,这里不仅有硬核的技术干货,还有我们对技术的思考和感悟,欢迎关注我们的公众号,期待和你一起成长!