序言
见过的人越多,就越喜欢狗。
感觉没有秋天,突然一下就凉凉的,偶尔还下个雨。
k8s事件和for循环
人人都爱for循环,无论是开发还是运维,经常随便来个for循环来执行一些脚本,例如进行一个测试。
for i in `seq 1000`;do curl -I http://example.com;done
for循环是最简单的一种调用方式,但是也有巨坑,在一些特别的场景之中。
1 k8s事件
在k8s的集群中,总是会有各种自己写的代码,来监听k8s的事件,然后来做一些对应的操作,例如将pod注册到注册中心,例如将pod的状态同步到注册中心,例如使用pod来进行监控。
当收到了pod创建事件之后,然后将pod注册到注册中心;当收到了pod删除事件之后,将pod从注册中心下线;当pod进行rolling update的时候,将pod从注册中心又要下线,又要上线。
这个时候就要for循环出现了,一个for循环进行处理对应的操作,在正常情况下,这种处理机制好像没啥问题,直到。。。
在运维k8s集群的时候,最常出现的两种操作:第一种,k8s的node机器宕机,从而造成大量的pod进行重新调度,可能是10个pod,也可能是200个pod,这在于node上的pod数量;第二种,当进行集群升级的时候,那么风险最小的做法就是将新建节点池,然后将老的pod进行驱逐,此时也是有大量的pod立刻处于terminating状态,然后会新建pod,最终老的pod被delete掉。
那么如果这种情况一旦发生,对于for循环来说,卧槽,处理不过来了,而且极度依赖for循环里面每个事件的处理,如果一个事件处理出现延迟,那么整体的服务都会有问题。
2 如何发现这种问题
for循环的阻塞问题,怎么发现有问题的呢?其实也是比较难,尤其是对于代码新手。
没事的时候,在测试环境进行一下演练,找个机器,上面跑几百个pod,然后进行一下宕机,就会收到业务那边的反馈,怎么出现了各种各样的报错,然后去查各种事件的日志,有的处理了,有的没处理,而没处理的都是反馈了问题的。
操作日志,你值得拥有,你会发现事件最长的延迟时间是8个小时。虽然开始说fuck了,但是也毫无办法。。。
在生产环境中,node机器宕机,也是稀松平常的事儿,一般都不会怎么太大关注,除非有业务在那叫,才开始进行排查。。。
在进行排查这种事件问题的时候,一定要关注每个细节的时间点,例如代码在什么时间捕获到了时间,什么时候注册到了注册中心,什么时间点从注册中心下线了,什么时间点在注册中心变成了健康状态,从发生到结束,到底耗时多久。。。
如果出现了上面的问题,那么你就会有两种疑问:一种怀疑是是不是丢失了事件,我们的事件捕获的不全?还有一种是大量的事件积压,处理不过来了,从而有延迟,但是最终能处理好。
如果是屎上雕花,那么就先看看代码吧,特别是在事件处理的时候,如果用的是for循环,用for循环其实也没问题,更大的问题是每个事件是不是单独的一个协程来进行处理的,从而当同时到达几百个事件的时候,事件的处理不是串行的,而是并行的,而不是相互之间阻塞的。
狗屎一样的代码也就算了,写代码的人还不查问题,简直是个垃圾。。。信誓旦旦说没问题,简直就是狗屎。
3 事件监听需要注意的点
Q1:监听事件的时候,有的时候需要选择,例如有的时候,你是监听pod的事件,但是如果是监控,那么在rolling update的时候,可能会造成监控数据的丢失,这个时候,如果你的服务都有svc,那么你可以试试监听endpoint的事件,完美解决监控数据丢失的问题。
Q2:监听事件的时候,如果你要非常快速的能摘除节点,其实endpoint也比pod好,因为在宕机的场景中,pod的状态在默认情况下,5分钟还是running,这种一般都开始fuck了,但是如果你改成endpoint,就能做到妙级进行摘除了。
Q3:监听事件的时候,关注极端场景下的测试,例如机器宕机的时候,其实pod的状态一直会保持5分钟状态为running,然后才会变成terminating,再进行重新调度,而node的感知到not ready状态是差不多45秒,3个健康检查周期一过,node是最先感知到的。
Q4:监听事件的时候,如果要演练,驱逐的风险比宕机的风险要小很多,因为驱逐是直接整个机器上的pod状态立刻从running变成terminating,然后立刻进行重新调度,从而也能看到大量事件,对于大部分的应用来说,基本无损。
Q5:监听事件的时候,如果每个事件的处理速度比较慢,不能达到秒级或者毫秒级,那么可能还是会依赖老的pod进行处理流量,那么可以尽量将老的pod的terminationGracePeriodSeconds设置的长一点,例如一分钟,例如五分钟,尽可能的让事件处理完成,让流量无损过度。风言风语
屎上雕花其实蛮烦的,代码的组织结构混乱,代码日志、日志格式混乱,这就是让人无法接手的代码,致命的玫瑰。
很难预见能碰到什么问题,但是一般遇到问题解决问题也就差不多了,也不用过分焦虑,风险无时不在,只是时机未到而已。
运维有的时候也是看运气,运气好呢,不会出故障,运气不好呢,卧槽,再牛逼也是一个故障接着一个故障,不过,该来的总是会来的,只是早与晚而已。
碰到恶心的人的话,只能祝福他碰到的人以后都和他自己一样。。。以子之矛攻子之盾
Good Luck for you