滴滴不专业的故障沟通
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特性。我在故障发生之前恰好发了几篇文章,试图帮助云厂商提高服务质量。
但是正如冯若航所说,“深度使用云厂商提供的AK/SK/IAM不仅会让自己陷入供应商锁定中,更是将自己暴露在云基础设施单点的问题里”,我不得不承认,在你无法确认云厂商能力之前,暂停使用RAM 是一个明智的工程决策。
草台班主的哀叹
HelloJava的主理人据说曾经是阿里最优秀的架构师之一。他撰文《稳定性,难的不是技术,而是》向大家讲解了一些可靠性的经验。但是,非常抱歉,我认为这篇文章恰好反映了阿里技术团队的非常业余的一面。
我对专家的期望是,他能推荐一个有效的可靠性模型,然后给出可以落地的工具推荐。实际上,作者只是零零碎碎分享一些私人经验,像个散文家一样想到哪里说到哪里,别说没有模型,连个结构都没有。
有些地方甚至有明显的错误。比如作者主张:
不管什么情况,以保障代码能正常运转是最重要的。
这是一个非常非常非常糟糕的建议。对于绝大多数业务来说,服务的可用性(Availability)的优先级应该低于数据的完整性(Integrity)。如果维持服务在线会导致数据泄露或者数据损毁,那么应该毫不犹豫地牺牲可靠性。这个很好理解,对大多数用户来说,一天不能上钉钉和丢失钉钉联系人之间,显然后者损失更大。
他下面这个建议本身是非常正确的,但是工程师可以用一个词语精炼地概括他的建议:追求故障平均修复时间(Mean Time To Recovery[8])。MTTR是一个有精确定义的概念,与之相关的概念还有MTBF以及SLO。
在故障出现时尽快恢复,而不是解决故障,在保留一定的现场的基础上,尽快的恢复问题比查问题重要得多,例如大家很多时候看到最有效处理故障的方法可能是重启,有同城双活、异地多活的通常最有效的处理方法是切流量等。
另外,作者使用稳定性这个词,是非常外行的。在工程学中,可靠性(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服务白名单的快速恢复能力。
加强云产品侧的联动恢复能力。
建议
软件从业者在基本工程能力的欠缺,过去被高速增长的业务数据所掩盖,不被当成一个问题。但是潮水一旦落下,我们就看到一个又一个裸泳的屁股。对此,我们没有其他建议,只有一个:老老实实补课,不要再吹牛X了。
参考资料:
[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),作者:马工在瑞典