软件从业者在基本工程能力上的欠缺,过去被高速增长的业务数据所掩盖,不被当成一个问题。但是潮水一旦落下,我们就看到一个又一个裸泳的屁股。对此,我们没有其他建议,只有一个:老老实实地补课,不要再吹牛逼了。
11月27日滴滴出行出了故障,至今没有发布一个官方的时间线,没人知道故障是什么时候开始的和什么时候彻底恢复的。目前最为详细的故障时间线,是一家财经媒体雷达财经发布的《[1]滴滴崩溃原因找到了!并非网络攻击 而是底层系统软件故障[2]》[3]。尽管和滴滴没有任何利益关系,我都感觉到一种从业者的行业羞耻感:“我这个行业怎么这么业余?还需要记者来帮我们整理时间线?”。
滴滴第一次沟通和第二次沟通间隔八个小时,这段时间内,一个猜测“滴滴被网络攻击了”成了最有说服力的解释,以至于第二天滴滴要专门澄清:“没有被攻击”。如果滴滴第一时间就坦诚的和客户沟通是技术原因,并且指出数据不受影响,可以减少很多混乱和恐慌。关于这一点,我建议滴滴团队学习一下 Atlassian的故障沟通最佳实践[4]的如下部分:
Regular updates during the incident
在故障恢复后,滴滴用很含糊的词语把故障原因解释为:“底层系统软件发生故障”。利益相关方既不清楚这个故障软件是第三方的还是滴滴自研的,也不知道滴滴是否启动了对这个软件的替换/修复。只得到了一个空洞的无法验证的承诺:“深入开展技术风险隐患排查和升级工作”。
由于滴滴不披露,大家只能自行挖掘。滴滴10月17日发布的一篇技术分享文章《滴滴弹性云基于 K8S 的调度实践》被挖出来,大家特别摘抄出三个点:
k8s 版本的升级:介绍到从 k8s 1.12 到 1.20 跨版本升级的方案。
Kubernetes 1.12是2018年7月发布的,在2019年7月8日就终止支持了。也就是说在2023年10月的时候,滴滴在生产环境使用一个社区已经废弃4年多的老版本。不论是看可靠性,还是看安全性,这都是非常草台班子的做法。
在五年没有升级版本的历史债务下,滴滴团队决定孤注一掷,直接从1.12 升级到 1.20。但是 Kubernetes Deprecation Policy[5] 很清楚地说了 Beta API 有可能在三个小版本之后就被删除。一次性升8个版本,风险完全不可控,也完全没有必要。
从方案可落地以及成本角度最终选取了原地升级。
修改原生的kubelet 实现,按hash值是否变化来决定是否重建容器的策略。
在冒险跨版本升级的前提下,还进一步选择原地升级,断绝 Plan B 的可能性,是一个更加费解的策略。实际上 Kubernetes 集群的蓝绿升级非常成熟,出问题的时候也更容易挽救。原地升级除了可以节约几个机器资源之外,没有其他好处。而升级Node不重建容器的做法,极容易引入兼容性问题,给自己的安全/调试/性能都带来极大的困难。
集群体量大,最大集群规模已经远远超出了社区推荐的5千个 node 上限,有问题的爆炸半径大;
Kubernetes 的多集群管理工具已经非常成熟了,而且滴滴其实有多集群,所以维护超大集群没有任何意义。作者自己也清楚“爆炸半径大”,那么合理的做法就是把集群拆成合理大小的。比如把两个一万节点的集群拆成十个两千节点的集群,管理成本没有增加,而运行风险和爆炸半径得到极大的降低。
这三个策略都有一致的特征:本来没有问题,但是滴滴硬是要跟社区的建议反着来,制造一些高风险的问题,然后用自己的各种杂耍技巧去踩钢丝。所谓的“有困难克服困难要上,没困难创造困难也要上”。
这不像是一个正规的工程团队的行为模式,更像是新加入公司的实习生想要一炮打响采取的策略。由于这种杂耍技巧很难改正,我们可以合理的质疑,这个定时炸弹目前是不是还在滴滴机房滴答作响?