目录

让子弹飞一会儿

近期互联网故障频发,各大公众号各抒己见,指点江山,激扬文字,颇有百花齐放,百家争鸣的味道。一众吃瓜群众也是对此乐此不疲,津津乐道。

大家能够积极的从故障中去学习,这本身是一件好事,再加上一众业界大佬们颇有深度的观点和经验分享,可以让我们看到大佬们的思维方式,认识到和大佬们的差距。问渠那得清如许,为有源头活水来,向优秀者学习是提升自己的一个有效途径。

在这个过程中我也看到了一些现象,想和大家一起探讨探讨。笔者之前曾有幸参加了滴滴弹性云平台的建设工作,对里面的情况还算有一定的了解,虽然已经离开了两年多的时间。

这里笔者并不会介绍真实原因,也不会涉及到什么技术问题,单纯就目前看到的一些文章表达一下自己的观点,可以理解为本篇并不是阐述从滴滴的故障中我们能学到什,已经有众多大佬分析过了,也已经比较全面了。这里主要想跟大家一起探讨下我们究竟从公众号或者自媒体的文章里面学到了什么,或者当我们看到这些内容的时候有哪些是需要特别注意的地方。

脱离实际

先不说故障原因是否真的如网上所说,假设事故原因就是升级造成的,里面的一些分析也有值得商榷的地方。想就两点来探讨:

  1. 选择原地升级方案就是草台班子吗?
  2. 爆炸半径太大了吗?

原地升级就是"草台班子"吗?

Kubernetes 1.12是2018年7月发布的,在2019年7月8日就终止支持了。也就是说在2023年10月的时候,滴滴在生产环境使用一个社区已经废弃4年多的老版本。不论是看可靠性,还是看安全性,这都是非常草台班子的做法。

在五年没有升级版本的历史债务下,滴滴团队决定孤注一掷,直接从1.12 升级到 1.20。但是 Kubernetes Deprecation Policy[5] 很清楚的说了 Beta API 有可能在三个小版本之后就被删除。一次性升8个版本,风险完全不可控,也完全没有必要。

在冒险跨版本升级的前提下,还进一步选择原地升级,断绝 Plan B 的可能性,是一个更加费解的策略。实际上 Kubernetes 集群的蓝绿升级非常成熟,出问题的时候也更容易挽救。原地升级除了可以节约几个机器资源之外,没有其他好处。而升级Node不重建容器的做法,极容易引入兼容性问题,给自己的安全/调试/性能都带来极大的困难。

脱离滴滴的实际情况去谈 k8s 升级的话,笔者非常认同上述说法。但如果考虑到实际情况的话,就显得有些站不住脚了。

首先,滴滴内部对 k8s 做了大量的定制化工作,一来是为了兼容之前物理机时代业务(用户)的使用习惯,降低上云过程中引入的体验上的差异,套用俞军老师的公式:产品价值 =(新体验 - 旧体验)- 迁移成本;二来是因为 k8s 提供的更多的是一些通用能力,而在具备一定规模的公司在使用过程中或多或少会有一些既有功能无法满足存量需求的情况。

滴滴内部的一些定制比如为 Pod 固定宿主机,固定容器 IP 等功能(这些都可以在网上搜索到,之前已经有不少的相关分享)在很大程度上限制了升级方案的选型,甚至影响了故障恢复方案的选型。倒不是说不能采用社区的蓝绿,而是也需要做一些相关准备,不是单纯新搭建一套集群直接就能去迁移业务过去的,我相信这一点大佬们应该也是对比了两个方案,做了充分评估之后才选择的原地升级方案。而且在更老的版本升级的时候也才用过过原地升级的方案。如果了解了现状之后,可能就会觉得原地升级的方案也是存在一定的可取之处的,虽然风险确实高,但这个风险是相对的,跟人的能力有关,只要风险可控,那选择原地升级也无可厚非。

当然积累这么多个版本不升级,确实可以算一个问题,但如果有节奏的升级,升级次数多了即使单次升级出问题的概率变小了,但是乘以升级次数之后得到的从某个初始版本到最终版本的出问题的期望值是否真的会变小呢,这不好衡量,唯一可以确定的是这样做的话单次升级的风险更低了。

看过火影忍者的小伙伴可能会有印象,作为医疗忍者体系的开创者,纲手定下了医疗忍者必须遵守的三项铁律,但是纲手是可以打破这三项铁律的,因为她还立下了第四条规则,那就是学会了百豪之术的医疗忍者,可以打破以上所有的规则。

方案选型,风险大小都是相对的,既要考虑常规做法,也要考虑人员能力,最重要的还是要结合现状,切忌脱离实际的空谈。官网给出的指导,业界的通用方案是怎么做的,那些都是基础,如果忽略实际情况完全按照这些来那就有点主观主义的味道了,完全按照官方文档来,那就是教条(本本)主义,按照经验来,那就是经验主义,主观主义的两个极端。实践是检验真理的唯一途径,虽然出了问题,但并不是在升级过程中出现的,从 1.12 直接升级 1.20 也不是不可行的,已经在客观实践中得到了检验证明这是行得通的,只是需要更加完善的流程,先把三板斧做好再上线。来自苏联的德国军事顾问李德指挥的第五次红军反围剿失利,损失惨重,倒是一直被打压,被嘲讽的人站了出来挽狂澜于既倒,扶大厦之将倾。

爆炸半径

Kubernetes的多集群管理工具已经非常成熟了,而且滴滴其实有多集群,所以维护超大集群没有任何意义。作者自己也清楚“爆炸半径大”,那么合理的做法就是把集群拆成合理大小的。比如把两个一万节点的集群拆成十个两千节点的集群,管理成本没有增加,而运行风险和爆炸半径得到极大的降低。

首先,笔者作为 karmada member,之前也在公司内做过一些多集群管理的实践和落地的工作,对"多集群管理工具已经非常成熟“这个结论持保守态度,还是要看内部需求,再成熟的软件也是去为了满足需求,解决问题的。业界开源的多集群管理工具里面,karmada(CNCF首个多云容器编排项目) 算是做的很好的了,其他还有例如 clusternet(CNCF sandbox 项目),OCM 等,笔者在落地过程中也遇到了一些功能和性能方面的问题,当然这与所在公司实际业务场景有关,也感谢 karmada 社区小伙伴的积极响应和支持。

滴滴其实有多集群” 这个结论可能也是受到了网上那些公众号的影响了,不能说没有,但可能和我们认知里面的多集群管理不一样。顶多是支持业务部署到多个集群里面而已,在没有这些多集群管理工具的时候,业务做部署/变更时只要选择多个集群,也是可以部署到多个集群里面的,这是"伪"多集群。这里就不得不再提一下国内的技术氛围,充斥着 PPT 实现,笔者之前在被面试和面试别人的时候都遇到过这些,比如早些年很多公司对外宣称的在 3 系内核上已经支持了 buffer io 隔离和限速的能力,大部分是 PPT 实现而已。

维护超大集群没有任何意义",这个结论有待商榷,从事调度和资源利用率提升相关工作的小伙伴们应该会对此深有感触,统一资源池有利于资源的统筹规划,提升资源利用效率,从而降低成本。我们需要辩证的去看问题,即使是有了多集群管理能力了,目前的多集群实现方案,无论哪个,在遇到根据集群剩余资源调度时有一个共通的技术问题:多集群管控面的调度只是到了集群维度,或者说对应的集群里面需要扣减一定的资源,但调度本身是和集群每个节点的资源有关的,从工作负载在控制面调度完下发到业务集群,到工作负载在业务集群完成调度的这段时间内发生在控制面的其他调度行为,其决定是有潜在问题的,因为这段时间在控制面看到的业务集群的真实资源还没有完全扣减了被下发的工作负载的消耗。类比集群内的调度,单集群的调度器通过 assume 的机制来解决这个问题,即单集群调度完就已经知道容器对应的宿主机了,他提前在调度器缓存内为对应的宿主扣除这个容器所占用的资源,而不用等真正的 Bind 完成,调度器收到 pod update 事件后更新完 cache 再去调度;多集群的调度就没法这么做了,因为控制面的调度决策完全不知道最终业务集群的调度结果,他需要等到业务集群里面真的调度完才能才能知道业务集群资源分布情况。

拆成合理大小的集群,这一点非常认同,关键就在合理二字。但多少算合理,还是得按照实际的业务规模和管理需求看。早些年阿里的对外分享动辄上万节点,也经常会有人提问,为什么要搞这么大的集群,普遍的回答就是这是根据内部业务规模评估得到的结论。所以多大合适,这个问题不光涉及到 k8s 管理人员,还和上面所承接的业务规模密切相关,这会涉及多方合作问题,不是平台自己就能搞定的,但无论如何,评估合理的可以接受的集群规模仍然是一件值得做的事情。

相比控制爆炸半径,一个更亟需解决的事情是管控面和业务的故障域隔离。把一些运维系统或平台与业务从一个集群中拆出去,即使业务集群挂了,控制面的平台至少还活着,还可以做一些操作,当然这个还是建立在那些运维平台本身功能正常的前提下的,如果他们本身实现就有问题,那就是另外的话题了。

有趣的现象

在大家讨论相关问题的时候,有一个有意思的现象。SRE 和运维似乎在吐槽开发,而开发似乎又在吐槽 SRE 和运维。

工程师都应该知道,一个工程项目的资源总是有限的,工程师的任务永远都是在给定时间和成本的多重限制下,满足既定的质量要求。如果一个目标需要“大量的投入”,那么决策者在衡量投入产出比之后,降低该目标,是非常正常的项目管理动作,没有任何值得抱怨的。

笔者非常认同这个观点,不管什么方案,谁出的方案,很多时候都是在一定限制,或者一定条件下做的决定,这些限制可能是暂时的,也可能是长期的,可能是和人有关,也可能和组件功能有关。我们经常站在当前的时间点,以现状去评估和衡量早前的方案,得出方案有问题的结论。这有一部原因是随着时间推移,之前做方案时的那些限制条件或者约束已经不存在或者微乎其微了,但我们并没有及时的去调整这个方案,这本身也是需要决策者保持关注的。但公司里面普遍的现象就是"能跑就别动”,“人和程序有一个能跑就行”。久而久之就会积重难返,直到一个大故障的爆发,或者幸运的话可能会安享晚年,亦或者在不为人知的地方悄然逝去。

很多方案是折中的产物,似乎每个方案的制定者或者决策者都有不得不做妥协的地方,好一点的可能还会列一下排期,按优先级分期实现。但有意思的是连最初的方案制定都因为各种原因而折中处理,更别提上线后的迭代了,有几个能把历史的坑去填了的。之后就会进入大家熟悉的流程里面,就看哪个倒霉蛋接手了。

最后

在看了各位大佬们的分析后感觉认知又得到了提升。由于笔者也在发一些东西出来做分享,自己深知在互联网自媒体井喷式发展的时代,自媒体,尤其技术类的,保持自身的专业性,严谨性理因是享受自媒体红利这项权利时应尽的义务。同样作为吃瓜群众,面对众说纷纭的消息,提升我们辨别是非,去伪存真的能力,保持自己不迷失在乱花渐欲迷人眼的自媒体世界里面,权当做韭菜的自我修养吧。

为什么会发这篇,可能和作为技术人员爱钻牛角尖有关吧,也是借机表达自己的一些看法,如果能得到大佬们的指点,和更多小伙伴交流,就更好了。最近又有一个有关数据库是否应该容器化的话题火了,又开始了神仙打架,战况激烈。还有一篇 k8s 越来越复杂的文章,然后有的人开始拿别人的一些文章在那里断章取义,诱导读者。

以上内容基于笔者已有认知所阐述,可以看到几乎都在针对特别具体,细节的地方阐述观点,没有扩散,因为笔者清楚的知道自己在某些方面仍然是个菜鸡,不敢高谈阔论。针对以上内容如果有问题,欢迎讨论互喷(我假装听不见)。