持續反饋如何反作用於持續交付和持續集成?

【原創 】2018-01-25 大梁 DevOps時代

作者簡介:

梁定安

騰訊織雲負責人,目前就職於騰訊社交網路運營部,開放運維聯盟委員,騰訊雲佈道師,騰訊學院講師,EXIN DevOps Master講師,鳳凰項目沙盤教練,復旦大學客座講師。

導言

很高興參與DevOps時代社區的拆書聯盟第一季活動,有幸能與幾位DevOps大牛一起解讀《DevOps Handbook》一書,這本書作者牛,內容也很牛,就連著名的培訓機構把這本書作為DevOps認證培訓教材。

書中不僅方法論和實踐豐富,而且所有案例都是取自於矽谷互聯網企業的DevOps最佳實踐,很值得我們研讀。

《DevOps Handbook》的拆書活動,共分成七部分,我負責的內容是「DevOps三步工作法」的第二部分:反饋實踐。

《DevOps Handbook》把持續反饋的內容分成三部分:

  • 第一是持續反饋的技術與案例,介紹在持續交付之後構建持續反饋體系的方法,主要是監控和告警能力的建設。

  • 第二部分會介紹優秀的持續反饋如何反作用於持續交付和持續集成。

  • 第三部分介紹實現持續反饋的非技術要素,包括組織、人員等軟文化。

第一部分:DevOps 三步工作法之持續反饋的技術與案例

本文將介紹後續兩部分內容

二、讓發布更可靠&安全

2.1、部署pipeline中的監控

持續反饋的技術,聊一下怎麼在Pipeline中部署監控,開展監控,在Pipeline中應該監控什麼東西。

講一個案例,Right Media是一個在線廣告的公司,他們的廣告庫存是動態的,一旦有客戶需求,他就馬上要擴容,客戶說我要投一個廣告,要上線一個遊戲,這個遊戲會有很多人來玩,他就馬上要擴容。

這時候遇到一個問題,運維人員部署很慢,開發人員甚至嘲笑運維人員,說你們連最本質的工作都做不好,你們為什麼會害怕部署。

當他們CTO把這個職責放給開發團隊的時候,開發團隊發現部署自己的代碼的時候一樣部署不起來。

為什麼,我們拋開架構問題時,其實還有一個很主要的問題,我們拋開部署難易度、部署配置管理的問題,還一個很重要的問題,在部署的每一個環節里其實是缺失了監控,他沒辦法知道我這個部署動作是正常還是異常。

所以Right Media後面做了一個很大膽的改革,他要求每一個步驟動作有由開發、測試、運維共同參與,這個其實也是DevOps提供的,甚至是開發都可以去部署。

通過這樣的一些方法去把我們的代碼質量提高,去完善我們的自動化測試,逐步去把一個很大的變更變成若干個很小的變更,變更量、變更代碼越小,變更頻繁增加,通過一個指標的監控,讓整體的發布文化走向完善。

Etsy的案例,黑色線是部署PHP,部署完之後,16點過一點,在這個點部署部署完,PHP告警馬上陡增,馬上再發布一個東西,然後告警下降,修復了,用更頻繁的部署,他每次部署就10分鐘,更頻繁的部署換來影響更小,我們可以做得更快更可控。

整個案例都沒有強調說是誰的過錯,關鍵是我們團隊怎麼樣去針對這個過錯去修改我們的流程,去共同進步。騰訊的實踐方法也類似,通過CMDB把我們的變更跟我們的監控關聯起來,然後我們對這個變更對象操作變更的時候,我們的CMDB會有一條變更記錄,然後監控系統發現異常的時候,它就會馬上直接告警告出來,說我有一個業務告警,這個業務告警發生時這個功能正在變更,請及時處理,讓告警更精準,推送到具體的人,實現了MTTI最短的時間,而不是我們收到一個告警還要去分析究竟是什麼問題引起的。

要落後這樣的發布文化,沒辦法迴避一點,必須要推進我們的非功能規範,無論是我們的監控指標、覆蓋度,這些跟業務邏輯無關,你的日誌要輸出什麼能夠,你的部署是不是支持獨立部署的,是不是具備獨立發布的,是不是高可用的等等,都是非功能規範。

在書中給了幾個實踐的方法,大家可以討論一下在中國是不是可以推行得起來,因為這些全是矽谷的做法。

要求開發和運維都是要oncall,輪流值班,今天是你值班,你可能是開發,你值班你來發布或者說發布的告警全部跑到你這,他就有主觀能動性,你要降低你的oncall成本,就必須去優化你的代碼。

還提到了一點,讓開發在下游工作,下游就是讓開發來干運維的活,讓開發自己維護自己的產品。

這裡我特別想跟大家分享一個騰訊織雲實踐的案例,騰訊SNG運營部在2008、2009年推行織雲標準化,要求所有的開發上線的時候都必須遵循運維的一些非功能的規範,當時運維團隊提出了軟體包必須要遵循一個包規範,一旦運維發現有開發沒有按照這個包規範去發布它的應用程序,當時真實的情況是讓開發同學發現這個問題,把不按照規範操作的那個開發人員抓到運維團隊去做兩周真實工作,這個是真實的案例,這個案例跟谷歌的SRE的實踐,不謀而合。

非功能規範,織雲也有一些實踐案例,運維對應用程序的整個生命周期分成四個階段,在不同階段做不同事情,要把非功能規範落實到地,例如運維在開發前會提出的日誌標準化格式要求,如JAVA程序、C程序、PHP程序,對應的目錄結構、日誌存放等。

去規範企業內的web服務,盡量集中統一用Nginx。

在服務投產上線前會驗收,在測試或者持續集成、持續交付的過程中,用織雲的運維體系去支持運維的標準化落地,並在運營中持續度量。

甚至運維會聯合質量管理的QA同學,對研發質量定義出不同緯度的非功能考核的項目,讓大家更好的去執行運維標準化的要求,保障每個新應用上線都能有很好的運維支持保障。

投產評審內容,書中提出了一些可供參考的點,如在做發布時應該遵守什麼東西,在持續交付的過程中,代碼缺陷數量和嚴重程度到達一定的值,其實這個發布是不允許去投產的。

例如在測試過程中或在壓測過程中,應用的告警是沒辦法處理的、沒辦法看得懂的,不給投產等等,如圖內容。

這是發布過程中我們必須遵循的技術上的一些考量的點,一些關鍵的因素。

除此之外,站在業務的角度,技術團隊還需要去考量一些內容,還需要去關注這個交付、這個部署、這個變更動作會不會影響業務的收入,會不會影響業務的用戶量,如果會的話,請在指標上體現這個變更的影響。

這個變更會不會有一些高危的風險,會不會有一些監管的風險,像很多金融同行,變更操作必須要符合銀監會、證監會、保監會的一些要求等等這些東西。

為什麼提這種評審的內容,因為DevOps很強調的一個觀點,歡迎有存在價值的流程,而不歡迎那些官僚的流程,不歡迎那些為了刷存在感而存在的流程。

例如在做發布時,是開發團隊和運維團隊的事情,但是審批流程需要走到另一個無關緊要的團隊來授權,這個無關緊要的團隊可能對項目的細節一無所知,這其實就是為了審批而審批,這種流程在DevOps裡面,如果用老外的觀點,是要嚴格刪除的,這是妨礙組織進步、技術發展的,是業務日益增長的部署效率的需求和落後的審批效率之間的矛盾。

2.2、谷歌SRE的運維實踐

讓發布變得更可靠,Google的案例可以跟大家探討一下。

去年有一本書很火,Google SRE那本書,同樣《DevOps Handbook》也是拿Google SRE的案例來舉例的。

可以這麼說,如果按照谷歌對他們應用程序投產的質量要求,可能一個你不要求技能很強的人都能把這個工作做得挺好,因為他的技術文化也好,保障體系也好,其實做了很多這種要求。

當然谷歌肯定是招了很優秀的人,但是如果單是從保障這個服務的可靠性來看,不需要很強的技能,都可以把這個服務運維得很好,因為谷歌提出了兩個在應用程序或者在產品投產之前的很重要的環節,LRR和HRR,LRR是投產/發布準備就緒審查。

審查什麼,谷歌SRE團隊會給一個檢查清單,裡面列出了這個程序要投產,必須得符合,書中沒有具體描述要符合怎麼樣的東西,只給了一些舉例,假設你一定要高可用,不能寫本地硬碟,一定要有狀態等等,就是前面所說的非功能規範的要求,跟業務邏輯無關的,但是必須要求開發提前做好。

LRR做不好是沒辦法走到HRR的,LRR其實是一個投產前供開發、測試和產品團隊去自檢的流程,是一個軟的流程。

當走完LRR節可以走到發布投產的環節,發布投產的環節就要走HRR,HRR是什麼,用國內的話就是開發把這個服務交接給運維,交接的過程SRE就要來評審,開發是不是符合運維規定的非功能規範,全部做到了,可以進行Hand-off交接,就是開發放手交給運維。

然後運維接管維護職責,走到第三個階段,運維的一段過程中,開發對這個程序有變更,有新的發布,一旦運維發現開發的發布又不符合HRR的要求,這時候運維有權這個應用程序交回給開發,就是一個Hand-back的過程,以這樣來制約DevOps經常提的開發要自己吃自己的狗糧,既然你開發的東西難運維、不可運維,那你就自己去運維。

這時候開發又要去自己維護,Self-Run,他覺得改進足夠了,他又走一次LRR的環節,然後再Hand-off給運維,整個文化在谷歌就是一個很強的文化,你可以認為SRE在谷歌是一個很強勢的團隊,整個谷歌有超過一百萬台物理伺服器,他們的SRE團隊只有1200人,這是2013年的數據。

這是一個DevOps文化的趨勢,也很符合讓開發自己維護開發的代碼,開發在下游工作,你自己體會一下運維的痛苦,如果開發可以通過改一下代碼就解決的事情,那千萬不要把這個包袱丟給運維。

在騰訊的運維實踐也做得有點類似,但是終究還是沒有像SRE這麼強勢,所有不標準的發布定奪大部分還是會按產品優先的原則,但是會要求開發在後續工作中修改到標準,是通過考核保障的。

三、提升質量的更多方法

3.1、假設驅動開發與A/B測試

怎麼樣基於監控告警的能力進一步提升業務的質量。

這裡提到一個假設驅動開發的方法,要把監控能力運用在A/B測試這裡,這裡也有一個案例,Intuit公司,北美的一個專門做中小型企業財務管理方案的公司,這個公司悶聲發大財,2012年利潤就有45億美元,整個公司有8500人。

公司CEO和管理團隊都很提倡一個文化,他們從來不相信老闆和產品經理拍腦袋想出來的產品需求,而是在工程實踐、產品實踐里和提倡一個文化就是要做A/B測試,Intuit會以最小的產品(MVP)的顆粒度給到他們的用戶或者一些重點客戶,然後用戶來告訴產品經理哪個功能是最想要的,讓產品保持迭代,從而去贏得市場,這也是Intuit能夠成為這個領域的獨角獸的核心能力之一。

A/B測試很早前就有了,電子郵件時代就有一些媒體會發這樣的傳單給用戶,用戶來選這個傳單裡面的這個產品是我需要的,從而來論證這個產品是ok的,那個產品是不ok的,做這樣一個A/B測試。

A/B測試有一個好處,就像這個圖舉例,我們對我們的用戶群體來做一些樣本測試,就像上面這個圖,我們是左邊放圖片還是右邊放圖片,左邊放圖片,業務的指標提升了50%,右邊放圖片只提升了10%,很明顯要用左邊這個方案。

A/B測試今天我們不展開講,A/B測試同樣是依賴於一些技術的要求,業務架構必須滿足一些能力,我們才可以開展A/B測試和指標監控,首先我們要能夠把我們的用戶分群,這一批用戶能訪問我A服務,這一批用戶能訪問B服務,這是最基本的,這個其實對業務架構會有一定要求的,這裡不展開。

《DevOps Handbook》里為什麼提到假設驅動開發,因為他認為傳統的開發方法,如瀑布流開發,往往需要一年或者極端情況的幾年,才完成一個產品的開發。

這個產品無論產品質量和體驗做得再好,如果不是用戶要的,其實這一段時間是浪費的。

這是精益和敏捷的思想,如果產品要做十個零部件,那精益思想希望每個零部件都能獨立出來,結合敏捷方法快速實現交付給用戶看一下。

devops方法提出在做特性監控的時候,能不能有A/B測試的方案,讓產品直接交付給用戶。

在發布版本的時候要用灰度發布的方案,加入遇到用戶不買單的情況,那就直接別發布了,停止灰度並全部回滾。

換成另一個方案,在特性計劃的時候,產品經理規劃一個新特性,一定要考慮A/B測試的因素在,這個其實是一個市場營銷、用戶體驗、用戶設計等範疇。《DevOps Handbook》推薦了一本《精益創業》,如果大家有負責產品規劃,推薦要看一下這本書,講到了很多方法論,做toc產品怎麼做,做tob產品怎麼做。

假設驅動開發還有一種做法,這種做法也是業界很通用的叫做漏斗模型,有些地方也叫漏斗獲取用戶模型的方法,最核心的是怎麼樣通過用戶測試的方法去一層一層看到用戶是如何使用產品功能進來的,每跳轉一次用戶流失了多少,最終註冊和付費。

之前有個笑話,你看一個網站怎麼樣去做用戶註冊的過程,如果你註冊一個賬號需要五步,那你可能每跳轉一步就流失20%的用戶,到最後一步可能你的流失率是95%,太多了。

但是你看看色情網站是怎麼註冊的,可能一步就行了。

這雖然只是一個玩笑,但如果監控能力能夠覆蓋這一部分的需求,這個其實就實現了DevOps所提倡的,所有IT團隊的工作都是為了實現業務價值,獲取用戶,這是一種實現業務價值的方法,在定義監控能力的時候也可以去考慮一下,是不是可以幫助到公司的產品人員,幫助公司的市場營銷人員,去更好的識別用戶的留存率。

3.2、優化部署流程中的評審與協調

第三部分最後一個環節,提升質量的方法還是要去不斷優化部署流程中評審的過程、協調的過程。

書中給了一個方法,這個方法就是GitHub公司真實的案例。GitHub公司對外的產品是GitHub,內部也是嚴格踐行DevOps,其實GitHub很多特性都是他們實踐出來的。

他們怎麼實踐出來的,講一個笑話,GitHub的CIO提過一個笑話,如果我們在提交代碼的時候,這個代碼的變動只有十行,我們要求另一個程序員給我們做代碼審核,十行的代碼很有可能給你提出十個問題,但是如果你提交一個變更,這個變更改動了五六百行代碼,你還是找回他,同一個同行的程序員給你做代碼的交叉審核,他會跟你說,你的代碼寫得不錯,找不到一個問題。

這個其實反映了一個問題,我們需要保證我們每次變動它的變化都是最小的,怎麼樣可以做到最小,其實就是持續交付的一些原則,你必須每天都得提交一次你的代碼,或者你一天提交幾次,確保你的代碼變動量是最小的,這樣你才可以去做交叉審查,去做測試驅動開發等等。

GitHub公司自己實踐出來的,這個特性也在很多GitLab、GitHub都有這種形式,GitHub flow,標準代碼提交的過程,應該是什麼樣子的,首先它是定期的,提交這個代碼分支一定要有版本的說明,當他提交完之後會有一個拉請求,去做自動化的編譯、測試等等。

合到主幹分支的時候會有相應的必須的審批流程,審批完之後,合到主幹就馬上會部署,部署到准生產環境也好,部署到測試環境也好,測試就去測,冒煙測試、集成測試、系統測試,甚至是UI測試,來確保這個代碼是ok的,功能提醒是ok的。

這裡提到一點,拉請求(pull request),如果大家有用GitHub的經驗或者有用Jenkins的經驗,pull request大家都應該知道,這個在我們講DevOps精益文化時,我們提到要怎麼樣減少浪費,裡面提到很重要一點,代碼搬運的過程是一個浪費的過程,如果我們不是拉的一個請求,是一個推的請求。

假設大梁寫完代碼了,我給小明提一個需求,我去告訴他說你什麼時候有時間去幫我測一下代碼,或者我的代碼要構建了,這個會有等待的時間,我的代碼寫出來一直不被人家集成、測試、編譯、交叉檢查,這時候提出拉請求,很重要一點特徵,如果是在GitHub的實現形式,它就是用webhook那種方法,當我的代碼上去,這個分支自動就會調用一些自動化的工具。

如果是最常見的Jenkins,Pipeline設計好的話,它馬上就會去編譯或者馬上就會調測試工具去測,去降低等待時間,這其實就是pull request。

我們先不討論拉請求怎麼樣去自動化,《DevOps Handbook》提出了並不是所有的pull request都是pull request,他認為一定要擁有足夠充足的上下文信息,它才算是一個pull request,就像右邊的這個截圖,你必須要寫清楚你為什麼要變化,你是為了做這樣的一個新特性還是為了修復一個bug,還是純粹為了代碼更優雅,變化了什麼,改動了哪裡,你為什麼這樣改動,改動完之後有可能影響什麼服務,是不是有收入的服務會被影響,你的風險,部署完能不能回滾,怎麼回滾,等等,這樣才是一個良好的pull request所攜帶的信息。

這裡講到一個案例,騎士資本,一家做VC業務的投資公司。當年他們有一個很經典的發布,因為一個發布的失敗,影響了15分鐘,導致他們15分鐘交易損失了4.4億美金。

在此之間運維團隊在服務部可用的時候是蒙圈的,因為運維沒辦法回滾,沒辦法將這個影響降到最低,這個就是因為在運維做變更時,開發人員沒把風險說好。

這個問題可以有兩個角度的看法:

  • 第一,怎麼樣能夠更好的去監測到風險與故障,這個是上述剛剛花了很大的篇幅討論的。

  • 第二,能不能在發布過程中,無論是用灰度還是用審批還是用信息共享等等這種方法,讓大團隊發現這個問題,然後讓這個問題不要出現。

書中還給了一個最簡單直接的方法,當運維發布的時候,面對如此重要的一個影響交易的發布,應該有一個聊天群或微信群,周知和共享信息,讓所有相關的團隊都可以standby的去應對可能遇到的問題,或者開發跟大家說一下有什麼樣的風險,讓大家提一下建議,他認為這種流程是很有必要的。

這本書提到的一些變更控制的環節,要慎防過度的控制,對變更的控制一定是要把錢都花在刀刃上,怎麼樣算刀刃上的一些控制呢?這裡舉了一些方法,書中認為所有對代碼質量的控制都是過度的控制,它認為開發人員完成代碼開發並提交給測試,測試發現代碼質量不高,打回來,然後開發人員再開發。

這樣一個反覆的動作其實都應該在編碼環節去解決。

參考右邊這個圖,下面橫軸X軸,往左邊看是一些審批流程,往右邊看是同行開發,代碼的質量可以通過一些結對編程的方法,或者說自己研發團隊可以解決的一個問題,不應該放在測試環節去解決。

這是一個谷歌的案例,這個案例有一條藍線,往左邊的黑點代表審批環節,往右邊的黑點代表同行交叉檢查環節,越採用交叉檢查的代碼質量越高,IT的效能越高,這遠比走一個僵化的審批流程來得要快,況且很多審批流程,其實又是康威定律作用的,組織架構決定軟體架構,既然設立了這樣的一個組織,它就必然要去發揮它的價值(刷存在感),就一定要去審批,因為該組織存在就是為了審批的東西。

我和很多DevOps同行都有交流,大家往往都會糾結一個問題,究竟企業要實施DevOps,是不是應該推動一些組織結構的變化,這個答案毋庸置疑都是「是的」,但是組織不變同樣也能實施,只是實施的沒有這麼優雅。

看了好多北美企業的DevOps實踐,他們更容易接納這種文化,可能國內有很多傳統的企業,沒辦法一蹴而就的接受這種變化,這也是國內DevOps社區想做的,怎麼樣致力推進DevOps在中國的落地,找到對口中國企業的devops方法很有意義和價值。

怎麼樣去改進外部審批流程,書中給出了結對編程,下面有兩個圖,結對編程不是配對編程,不是一男一女的編程,往往是兩個男人的編程。

書中對結對編程提出了幾種不同的方法,有不同的模式,有駕駛員、領航員的模式,駕駛員是主要的寫代碼的人,領航員負責檢查他的代碼,但是有一個原則,不要駕駛員寫了幾千行上萬行再給這個領航員去看,而是你每變動一點都要給他去看,這樣不僅僅可以促進代碼文化標準化的落地,還可以彼此的,相當於也是技能培訓。

另外領航員也可以旁觀者清,他可以更好的根據我們未來規劃業務架構所需要的一些技術的方案,他可以給到寫代碼的人更多的建議。

還有Over-the-shoulder這種編程,一個人在寫,後面一個人在看,這樣你也不能寫寫代碼聊聊微信了,不知道具體歐美怎麼執行的。

還有一種跟pull request類似,利用一些工具,GitHub等這樣一些工具,提交完代碼,他就會把變數的那部分帶上你的備註,發給郵件審批人,審批過了再去做。可以通過這個過程的度量,去把它做到足夠輕量化。

還有一些做法,結合我們的檢查工具,例如代碼提交,提交到代碼庫之後,分支之後,會有一些代碼靜態掃描工具去掃描一下,有控制空函數,也沒有野指針,註釋量是多少,你有沒有引用高維函數等等,都可以把我們研發的流程或者研發質量的一些要求變成一些工具,給他去掃。

當然,這裡能覆蓋一點,但是不能解決所有的問題。還有一些是加強型的TDD,駕駛員寫代碼,領航員寫測試用例,你們同時寫,我先寫完測試用例,你一提交,馬上調用測試用例來測。谷歌在很多場合很多技術分享的時候都表明自己的工程師文化是嚴格執行TDD的。

結對編程文化有很多好處,也有很多規則,他要求大家一定要提交到主幹之前都要交叉檢查,你的代碼環境有沒有什麼依賴變化,有沒有一些衝突等,一定要定義清楚你是不是有高風險的,如果你認為你這個代碼有安全問題,其實是應該有安全專家評審過的。

他認為這些在代碼階段所有的問題都是必要的一個流程,我們要結合工具去簡化這類流程,但是代碼生產出來,所有的風險不要讓它遺留在測試階段,不要讓它遺留在投產階段和運營階段,必須把影響最小化的扼殺在萌芽階段。

這裡有谷歌的案例,X軸表示代碼變化的大小,Y軸是評審的耗時,如果我們每次變更就是十行,可能一個人5分鐘就可以評審完,如果變更一萬行,他需要一個月甚至是幾個月,強調了幾點。

第一,你每次變更要足夠小,頻繁去提交你的代碼,頻繁讓別人去看,然後你的代碼可讀性一定要強,這個自然而然會形成我們團隊或者整個企業代碼的文化,然後我們的分支管理許可權必須要針對這種代碼的文化去設計,還有代碼的透明度,跨團隊的代碼管理能力。

我印象最深的是當年去矽谷跟他們交流很深的一個印象,當年那個同學他也是在國內工作了一段時間,然後技術移民去了美國,在矽谷工作,我去那邊跟他聊,國內外企業的文化差異是什麼,他提到一點,你在矽谷入職,你拿到的電腦裡面,你打開谷歌的chrome瀏覽器,裡面就已經給你收藏了所有谷歌業務指標的信息,包括業務的關鍵數據,谷歌認為每個員工都是善良的,既然你成為谷歌團隊的一員,你有必要去了解整個公司業務的發展。

這個其實挺震撼的,在國內大部分公司相信還做不到這一點,很多老闆都擔心業務指標被無關的人看到會有機密泄漏或影響估值等風險。挺多這種中西文化的差異,但是我們還是要朝先進的互聯網企業去學習。

書中很嚴肅的提到一點,除了所有有必要的流程,DevOps團隊成員應該勇敢的站出來,勇敢的剔除官僚的流程。

我也號召大家勇敢的站出來,去給你老闆彙報下,對現行不好的流程提出優化方法,運維對生產故障的總結思考能不能夠通過代碼的階段去解決,而不是說默默的背了這個鍋,這是DevOps不提倡的。

最後歡迎大家後續繼續關注DevOps時代社區的拆書活動,一起探討DevOps落地中國的最佳實踐方法。

聲明

本文系作者授高效運維/DevOps時代,

經許可,不得轉載、摘編。違者必究。

如需轉載請聯繫高效運維社區

你可能會喜歡