滴滴不專業的故障溝通
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 了。