摘要

软件从业者在基本工程能力的欠缺,过去被高速增长的业务数据所掩盖,不被当成一个问题。但是潮水一旦落下,我们就看到一个又一个裸泳的屁股。对此,我们没有其他建议,只有一个:老老实实的补课,不要再吹牛逼了。

滴滴不专业的故障沟通

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的多集群管理工具已经非常成熟了,而且滴滴其实有多集群,所以维护超大集群没有任何意义。作者自己也清楚“爆炸半径大”,那么合理的做法就是把集群拆成合理大小的。比如把两个一万节点的集群拆成十个两千节点的集群,管理成本没有增加,而运行风险和爆炸半径得到极大的降低。
这三个策略都有一致的特征:本来没有问题,但是滴滴硬是要跟社区的建议反着来,制造一些高风险的问题,然后用自己的各种杂耍技巧去踩钢丝。所谓的“有困难克服困难要上,没困难创造困难也要上”。
这不像是一个正规的工程团队的行为模式,更像是新加入公司的实习生想要一炮打响采取的策略。由于这种杂耍技巧很难改正,我们可以合理的质疑,这个定时炸弹目前是不是还在滴滴机房滴答作响?

阿里云摧毁客户信心

11月12日,阿里云出现了一次影响所有区域的全局大故障。作为云厂商的一哥,阿里云发布了详细的故障时间线[6],但是发布的故障报告语焉不详,我建议大家参考冯若航的非官方复盘文章我们能从阿里云史诗级故障中学到什么,目前为止这篇文章是对这次故障最为权威的分析。
这个故障离谱的是,尽管阿里云一再宣称自己有多区域,但是显然他们的 RAM 没有做到区域的隔离。
这个故障还是对我个人的一巴掌。我和我的朋友王明松一直鼓吹大家使用 IAM, 在《云原生王四条》[7]中,我们特意详述了使用 IAM 的 Role 特性。我在故障发生之前恰好发了几篇文章平台软件应该像数学一样严谨 --- 和阿里云RAM团队商榷云为什么留不住客户 — 以腾讯云 CAM 为例,试图帮助云厂商提高服务质量。
但是正如冯若航所说,“深度使用云厂商提供的 AK/SK/IAM 不仅会让自己陷入供应商锁定中,更是将自己暴露在云基础设施单点的问题里”,我不得不承认,在你无法确认云厂商能力之前,暂停使用RAM 是一个明智的工程决策。

草台班主的哀叹

HelloJava的主理人据说曾经是阿里最优秀的架构师之一。他撰文稳定性,难的不是技术,而是向大家讲解了一些可靠性的经验。但是,非常抱歉,我认为这篇文章恰好反映了阿里技术团队的非常业余的一面。
我对专家的期望是,他能推荐一个有效的可靠性模型,然后给出可以落地的工具推荐。实际上,作者只是零零碎碎的分享一些私人经验,像个散文家一样想到哪里说到哪里,别说没有模型,连个结构都没有。
有些地方甚至有明显的错误。比如作者主张:
不管什么情况,以保障代码能正常运转是最重要的
这是一个非常,非常,非常糟糕的建议。对于绝大多数业务来说,服务的可用性(Availability)的优先级应该低于数据的完整性(Integrity)。如果维持服务在线会导致数据泄漏或者数据损毁,那么应该毫不犹豫的牺牲可用性。这个很好理解,对大多数用户来说,一天不能上钉钉和丢失钉钉联系人之间,显然后者损失更大。
他下面这个建议本身是非常正确的,但是工程师可以用一个词语精炼的概括他的建议:追求故障平均修复时间(Mean Time To Recovery[8])。MTTR是一个有精确定义的概念,与之相关的概念还有MTBF以及SLO。
3.在故障出现时尽快恢复,而不是解决故障,在保留一定的现场的基础上,尽快的恢复问题比查问题重要的多,例如大家很多时候看到最有效的处理故障的方法可能是重启,有同城双活、异地多活的通常最有效的处理方法是切流量等。
另外,作者使用稳定性这个词,是非常外行的。在工程学中,可靠性(Reliability)是一个专业术语,国家标准GB3187-1982《可靠性基本名词术语及定义》把这一套术语都涵盖了。而稳定性(Stability)则是计量系统的一个词汇,指一个衡器多次衡量同一个样品,应该输出一个稳定的值。淘宝用户或者特大号小编把这两个词汇搞混淆是可以原谅的,但是技术专家应该要知道这两者完全不是一回事。
作者在文章中号称可靠性其实“技术上真的没有那么难”,只不过:
这意味着的是大量的投入,能不能在稳定性这件事上保持持续的一定的投入,甚至当成做业务功能实现一样的必须的投入,这才是真正做好稳定性最难的。
然后作者把可靠性的锅抛给了管理者,指责:
很多做过稳定性这事的人都知道,做这个事情最麻烦的是很难被认可,做的好,不出问题,不懂的人不知道你做了什么,出了问题的时候觉得你到底做了什么
不客气的说,这是一种非常典型的大妈牢骚。工程师都应该知道,一个工程项目的资源总是有限的,工程师的任务永远都是在给定时间和成本的多重限制下,满足既定的质量要求。如果一个目标需要“大量的投入”,那么决策者在衡量投入产出比之后,降低该目标,是非常正常的项目管理动作,没有任何值得抱怨的。
值得抱怨的是这两种情况:项目本来要求A级可靠性,但是最终依照C级可靠性施工。或者,项目只需要C级可靠性,却花费大量的资源用于追求A级可靠性。你把银行存款业务跑在一台树莓派上,属于前者。你把公司内部论坛在亚洲欧洲北美三个region部署,属于后者。两者都是不可取的。
那么依据项目的资源和需求,制定一个可行的(Feasible)可靠性目标,是谁的责任呢?在其他行业,答案很简单,这属于可行性研究(Feasibility Study)的一部分,也是一个非功能需求的技术问题,是工程团队的责任。机械工程师们和土木工程师们非常熟悉这个任务了。如果你在可靠性目标制定上有这么多牢骚,很可能问题不在于管理者,要么你制定的目标确实不合理,要么你能力有限,无法向利益相关人有力的证明目标的合理性。
一篇文章读下来,我的印象就是:这位阿里技术一哥可能是个聪明人,也有一些不错的经验,但是整体上来说,没有接受过正规工程培训,严重欠缺工程理论常识,以前走野路子可能做了一些项目,但是个人经验几乎不具备可复制性。这样薄弱的底子,写文章参与可靠性讨论的结果,正如评论区一个读者说的:
好像什么都说了,又好像什么都没说

天生不良的教育欠缺

软件工程是一门工程学科,从业者首先是个工程师,其次才是个软件工程师/硬件工程师/Java工程师。但是很可惜,由于教育的缺失,很多顶着很高头衔的从业者,其实不能算现代工业的工程师,更像一群家庭作坊的手工业者。
可靠性工程作为一个非常成熟的工程学科,是机械工程/土木工程的必修课。中南大学土木工程学院本科生就被要求必修《工程结构可靠度》[9]
Reliability of Engineering Structures 课程简介:荷载是工程结构设计的一个重要方面,也是着手一项工程设计要解决的一个重要问题,而概率可靠度方法已成为各类工程结构(房屋、桥梁、地下建筑、道路等)设计的理论基础。本课程全面、系统地介绍工程结构各类荷载的基本概念及其确定方法,以及结构可靠度分析与设计理论。
作为成熟的工程学科,他们有专门的可靠性教材:
作为对比,全国的软件工程系/计算机系还没看到给本科生开这门课程的,更不用说作为必修课。我翻了几本《软件工程》课本,没有一本覆盖了可靠性。
当然,即使软件工程课程覆盖了可靠性理论,也不一定能触及学生。在上海交大计算机科学与技术系的课程表[10]中,《软件工程》竟然是选修课程,也就是说,一个优秀大学热门计算机专业的优秀毕业生,有可能会《移动互联网》或者《大数据处理》这些热门技能,但是很可能没有接受过最基本的工程教育。

后天不足的持续学习

尽管高等教育落后,但是工程界并没有自暴自弃,做了很多努力去提升从业者的可靠性能力。就以很多家庭主妇为了户口落户而去考证的软考为例,可靠性是考试大纲中的一部分。
系统的可靠性分析与设计
● 系统的故障模型和可靠性模型
● 系统的可靠性分析和可靠度计算
● 提高系统可靠性的措施
● 系统的故障对策和系统的备份与恢复
国标GB/T29832 《系统与软件可靠性》有三个部分,虽然内容不一定及时更新,但是至少规定了一些基本术语和基本方法。
——— 第1部分:指标体系;
——— 第2部分:度量方法;
——— 第3部分:测试方法。
如果偏好看书,教材也有很多,中英文的都有。如果你嫌弃软件可靠性开山鼻祖John D. Musa 的《Software Reliability Engineering: More Reliable Software Faster and Cheaper 2nd Edition》是英文的,也可以读徐仁佐的《软件可靠性工程》[11]
如果有从业者学习能力实在差,不能考试,也不愿意读标准,甚至读书都会头痛,行业也提供了很多视频,比如波兰 nobl9 公司的学习园地[12]就有大量的关于可靠性的音频视频材料。该公司还主办 SLOConf 会议[13],免费提供很多可靠性演讲。
如果有人连音频视频都懒得看,我甚至可以找出可靠性的动画片来。但问题是,提供再多的材料,从业者会去学习吗?用我的朋友王明松的话说:“有些从业者的软件工程理论水平,连考软考拿落户的家庭主妇都不如。” 这一点我毫无异议,因为家庭主妇至少不会搞混稳定性和可靠性。

空洞承诺

如果一个行业的从业者既没有得到正规的工程教育,也没有得到妥善的在职教育,而是凭着朴素的常识处理工程问题,就像农民工凭着朴素的常识去工地搬砖一样,虽然也能在包工头的带领下修起高楼大厦,但是可靠性恐怕要大打折扣。
当故障过后,滴滴给出的空洞承诺
后续我们将深入开展技术风险隐患排查和升级工作,全面保障服务稳定性,尽最大努力避免类似事故再发生。
这个承诺基于一个错误的假设:只要把现有的技术风险排查一遍,就可以全面保障服务稳定性了。但是用任何一个可靠性模型都会指出:预防故障只是可靠性的一部分工作,而技术风险也只是故障来源的一部分。至少从本次故障来看,滴滴的故障中处理流程非常不规范不严谨。如果我们上面的猜想成立,(鉴于滴滴没有公开复盘材料,上述猜想是目前最有解释力的)那么滴滴平时的基础设施技术选型的决策流程也有严重问题。单单只是排查技术风险隐患,恐怕不能提升滴滴的服务水平。
而阿里云给出的改进措施就更勉强了,几乎就是头痛医头脚痛医脚。
增加AK服务白名单生成结果的校验及告警拦截能力。
增加AK服务白名单更新的灰度验证逻辑,提前发现异常。
增加AK服务白名单的快速恢复能力。
加强云产品侧的联动恢复能力。

建议

软件从业者在基本工程能力的欠缺,过去被高速增长的业务数据所掩盖,不被当成一个问题。但是潮水一旦落下,我们就看到一个又一个裸泳的屁股。对此,我们没有其他建议,只有一个:老老实实的补课,不要再吹牛逼了。

参考资料

[1]《: http://www.leidacj.com/yuanchuang/show-36978.html
[2]滴滴崩溃原因找到了!并非网络攻击 而是底层系统软件故障: http://www.leidacj.com/yuanchuang/show-36978.html
[3]》: http://www.leidacj.com/yuanchuang/show-36978.html
[4]Atlassian的故障沟通最佳实践: https://www.atlassian.com/incident-management/incident-communication#:~:text=Part%202%3A%20Regular%20updates%20during%20the%20incident
[5]Kubernetes Deprecation Policy: https://kubernetes.io/docs/reference/using-api/deprecation-policy/
[6]阿里云发布了详细的故障时间线: https://status.aliyun.com/#/historyEvent
[7]《云原生王四条》: https://github.com/lipingtababa/cloud-native-best-practices/blob/main/%E4%BA%91%E5%8E%9F%E7%94%9F%E7%8E%8B%E5%9B%9B%E6%9D%A1.md
[8]Mean Time To Recovery: https://en.wikipedia.org/wiki/Mean_time_to_recovery
[9]《工程结构可靠度》: https://civil.csu.edu.cn/bksjy/kcjs/kcjs.htm#:~:text=%E5%B7%A5%E7%A8%8B%E7%BB%93%E6%9E%84%E5%8F%AF%E9%9D%A0-,%E5%BA%A6,-%E8%8B%B1%E6%96%87%E5%90%8D%E7%A7%B0%EF%BC%9AReliability
[10]上海交大计算机科学与技术系的课程表: https://bjwb.seiee.sjtu.edu.cn/bkjwb/info/13371.htm
[11]《软件可靠性工程》: http://www.tup.com.cn/upload/books/yz/016476-01.pdf
[12]波兰 nobl9 公司的学习园地: https://www.nobl9.com/explore/learning-center
[13]SLOConf 会议: https://www.sloconf.com/speakers
源 | 瑞典马工(ID:cloudshotgun
作者 | 马工在瑞典;编辑 | 呼呼大睡
内容仅代表作者独立观点,不代表早读课立场
继续阅读
阅读原文