2022,你的团队距离持续部署还有多远?
簡介:2022,你的團隊距離持續部署還有多遠?持續部署這個詞我們經常聽到,可是到底怎樣才是做到了持續部署?如何才能做到持續部署?本文將為你逐層拆解持續部署的內涵和實施路徑。
編者按:持續部署這個詞我們經常聽到,可是到底怎樣才是做到了持續部署?如何才能做到持續部署?本文將為你逐層拆解持續部署的內涵和實施路徑。
策劃&編輯|雅純
云研發時代,主流的發布形態變成了服務化的發布形態,這種發布形態讓持續發布有了現實的基礎。發布的前提是把待發布制品部署到生產環境,所以持續發布的前提是持續部署。
持續部署的4個要求
持續部署要求持續地提供一個穩定可預期的系統服務。有時候發布過程當中會停機,停機更新的這段時間系統不可用,這就是非持續的部署形態。
我們希望的持續部署:
首先應該是準確的——部署結果準確可預期的;
第二,應該是可靠的——整個持續部署過程中線上服務不受影響;
第三,應該是持續的——隨著持續部署的發生,有可持續部署的軟件增量;
第四,過程成本低——持續部署過程是低成本和高效的。
如何做到這4點呢?
1、準確、可預期的部署結果
準確地部署依賴三個前提:明確的待發布制品及配置、明確的運行環境、明確的發布過程及發布策略。
下面是一個簡單的發布示例:
發布首先有明確的image,即上游過來的構建產物。同時包含很多配置,如啟動配置、容器的配置等。另一個是環境,我們會在部署工具中配置k8s,這個配置最后會形成一個環境,而這個環境會在DevOps過程中被用到。最后我們把制品和配置發布到這個環境上,就完成了發布。
所以,發布的過程是把制品和配置的集合應用到環境的集合上的過程。首先要有明確的待發布制品和運行環境,其次通過相應的描述,把制品、配置和環境都描述清楚,形成發布的內容,才可以進入下一步。
最簡單的發布就是kubectl apply,但這種發布方式存在著一些問題。
第一,結果不確定。kubectl之后pod可能并沒有起來,deployment可能是不能用的,服務可能有失敗,發布之后可能會遇到pod不夠,資源沒有,這些都是未知的。所以發布是否成功,發布成功了多少都不確定,這是不可預期的。
第二,狀態不可見。發布不是一蹴而就的,是逐步的過程。發了多少,有多少問題,哪些流量已經切過來,這些情況都是未知的。
第三,過程不可控。在這個發布過程中,一條命令下去之后是無法撤回的。
如果版本有問題,有嚴重的Bug,全部的流量跌零,是無法反悔的,非常危險。所以在真正的發布過程中,我們要有干預手段,比如當我發現流量會導致可用性的大量下降,需要能夠馬上停止發布。
無論采用何種部署方式,我們都希望盡量減少對線上服務的影響,這種影響降到極致,即部署過程完全不影響線上服務。這是我們的第二個原則。
2、部署過程不影響線上的服務
要做到不影響線上服務,有4個要求:
第一,滾動式部署
采取灰度的方式,將絕大多數服務滾動地部署上去,當確認沒有問題再把流量切過去,做到線上的服務不中斷。滾動有可能會過快,需要保證每一個批次的間隔足夠監控發現問題,有足夠時間收集到足夠數據做判斷。
第二,部署可觀測
部署本身可能會產生一些告警,比如部署導致一些服務節點水位下降,而非整個服務的水位下降。所以部署與監控需要打通,首先要避免無意義的告警,其次要讓監控及時發現部署產生的問題,比如部署兩臺節點,流量如何?服務情況如何?延時是否增加?這些都需要去監控。
第三,隨時可干預
部署過程中可能會有很多不確定的問題突然出現,這時需要一些干預手段,比如分流的操作,進行相應的切流,避免問題影響到整個系統。
第四,隨時可回滾
如果你的干預不能快速解決掉問題,這時就需要回滾了。要做到隨時可回滾,是因為部署過程中有一些失敗情況相應的修復成本特別高,快速回滾,才能保證服務不會受到影響。
常見發布模式舉例
這里介紹幾種常見的發布策略。
(一)灰度發布
灰度發布常見的架構如上。首先有一個負載均衡,負載均衡下面的服務版本當前是V1,要發布新的版本是V2,可以從里面摘一個節點,五分之一的流量用V2。
這種情況下,原來所有的Pod都在Deployment1上,但是有一個新的Pod會在Deployment2上,從Loadbalancer到Service路由的時候就會有一部分流量路由到新的Deployment2上。
有時候,為了更精細的控制流量,也會通過ingress或者mesh這樣的手段,將特定的流量,比如5%的包含grey的cookie標的流量路由到Deployment2上。
我們期望deployment2逐步替換掉deployment1,deployment1的流量慢慢被替換、被下線。整個的過程當中用戶是無感知的,請求是正常的,各類監控,基礎監控,應用監控,業務監控都正常,這是我們期望的結果。
灰度發布最常見的做法是生成一個新的deployment,關聯新版本的Pod,在一段時間內同時存在兩個deployment版本,通過不斷調整兩邊的的Pod數量達到灰度發布的目的。這個是最常見的部署策略,成本也比較低,缺點是無法做很精細的流量控制,但服務量不大可以考慮這種方式。
這種發布形式對服務有要求,首先要求對于某一個具體的service,最多只有一個進行中的發布,因為需要有流量的不斷切換做驗證的過程。
第二,對某一個service發布完之后只能有一個版本的deployment運行,不允許兩個同時存在。
第三,在整個過程當中存在兩個版本的deployment,有兩個版本的服務在提供,要保證這兩個版本服務都能夠正確提供,不管上游是什么,下游是什么,都可以正確處理業務需求。
第四,整個發布過程不能造成服務的中斷。如果普通的短連接服務,要保證一個session不會因為發布導致前后斷開或前后不連續。如果是長連接要保證這個連接能夠自動地遷移到新的服務上。
最后,整個發布過程不會造成用戶請求的錯誤,而是會有一個優雅下線機制保證它處理完之后不接受新的請求,在這種情況下才能夠保證達到期望的灰度發布的效果。
所以整個灰度發布的過程不僅僅是對發布的工具,發布的策略有一些要求,對應用程序本身也有不少的要求,才能達到非常平滑的灰度發布。
基于此,我們總結了幾點針對灰度發布實踐的建議供大家參考。
第一,我們建議應用需要保證對前一個(或數個)版本的兼容。這個版本的兼容數量取決于應用的線上情況,有時線上會同時存在幾個版本的應用,我們需要保證對這幾個版本的兼容性。
第二,創建一個新的deployment,提供同樣的service,通過調整pod數或者ingress流量來進行灰度,這種灰度的情況下可以很精細地控制它,所建議通過流量控制。
第三,定義灰度批次以及每一批的比例和觀察時間。灰度批次要設計合理,保證每個批次之間的間隔足夠我們去發現問題并做處理。如果灰度間隔特別短,有可能監控還沒有來得及告警就進入下一個更大的批次,可能帶來非常大的風險。
第四,除了關注基礎監控和應用監控外,也需要關注業務監控數據。監控是一個很大的范疇,但是從發布的角度講,我們的最終目的是要避免發布帶來的業務損失,發布可能會導致業務不可用,或業務出現錯誤,更嚴重的是發布造成業務某一些觀測指標產生大的變化,比如說用戶轉化率或者是用戶登錄成功次數等數據異常。這些異常的數據應該及時被發現,并且立即暫停。
第五,當發布過程完成之后,應該先做流量切換進行觀察,而不要急于清理pod,保證將來做回滾的時候更高效。如果這個pod還在,很快就能把流量切過來,可以縮短線上服務受影響的時間。
第六,記錄下發布的版本,方便進行回滾。除了具體的版本我們還要知道在哪里部署過,這樣才方便回滾。記錄下相應的版本,如果合規檢查自動化做得比較好,也可以做到一鍵回滾。
第七,回滾與重新發布不同。回滾與發布的策略不同,不可能和發布一樣每次批次很小,為了解決問題需要做到減小批次、縮短時間、快速回滾。
最后,如果系統支持多租戶,建議基于租戶做流量隔離和AB測試,尤其是AB測試的時候比較方便。
(二)藍綠部署
另外一個常見的部署方式是藍綠部署:
藍綠部署和灰度相似,只是所需要的資源更多一點。這個取決于軟件的部署形態,以及機器資源的數量。藍綠比灰度對軟件的要求會更低,可以保證所有的業務都部署好之后再去切,但是灰度不行,要能夠持續部署。但是藍綠的風險也是比較高的,一旦出問題就是全局性的。
要做到不影響線上的服務,除了部署策略外,也會有其他問題,比如軟件只開發了一半,或者服務部署上去希望和別的服務配合在一起才能作為一個完整的系統服務提供給用戶,這時需要用到特性開關方式。
特性開關本質上是一類特殊的配置,一般以動態配置的形式下發。平時可以做持續部署,但開關保持關閉,等到客戶端或者前端發布上去之后,再將開關打開。所以嚴格來說特性開關的打開本身也是一次發布,特性開關本身也需要版本管理。
我們希望達到的終極目標,是任何時候任何人都可以放心的發布軟件。這意味著,你的服務任何時候都能發,任何人都可以放心地發,發布的操作是非常簡單的,不需要特殊的技能,且發布之后不會出現什么大問題,即便出現問題也能很快解決。
因此,我們的愿景是:任何時候,任何應用都可以發布上線。
對阿里巴巴來說可以具象化為:雙11不封網,雙11的時候想發就發。實際在雙11的過程當中,也是有很多緊急發布的,這里需要有非常完整的技術保障,保證發布的安全性和可靠性,因為如果一旦出現問題可能就是輿情故障。而且越是這個時候就越可能會產生一些雪崩效應,可能會帶來一系列的故障和問題,最后整個系統會癱瘓掉。
3、可持續部署的軟件增量
做持續部署,持續是關鍵。圖中上面的一組,蒙娜麗莎的微笑每次都是一小塊,最后做成了第5塊,但是1、2、3、4每個都是不完整的,而下面的1、2、3、4、5每一個都是完整的,但是在不斷地豐富細節。它想表達的是:
(1)我們的軟件增量應該對應一個明確的需求價值點,有一個明確的需求價值點可以交付。
(2)第二,軟件的增量應該是完整的,是可以獨立發布的單元。
(3)第三,軟件的增量要能夠被獨立驗證。
KentBeck說過一句話:
也就是說集成是一件非常重要的事情,因為我們在絕大多數軟件開發協作過程當中都是把問題拆分解決再集成的過程。
集成有以下三個步驟:代碼提交,打包部署,驗證。這3個步驟非常簡單。
集成的目的是為了驗證完整性,驗證合并后的代碼能夠構建,能夠完成相應的功能性測試的驗證,幫助我們盡早發現風險。因此要做到盡早集成,每次集成的批量應該很小。
兩個單元:一個從部署的角度來說是可部署的單元;另外一個從集成的角度是可集成的單元。
部署的單元是可發布到可測試,是需求的視角。增量是一個需求,一個特性,用戶可以看得到的,可以用到的功能。另一個是可集成的單元,即許多可構建的單元,從邏輯上能夠構建在一起,完成單元測試,然后再去做代碼級別的驗證,這是代碼的視角。
代碼提交后,代碼分析,編譯構建,都是在做代碼的質量檢查。編譯成功很多時候就是給我們第一手的反饋。編譯器在構建的過程幫助我們發現在寫代碼過程當中的一些問題。構建本身,如果速度比較快,程序員是特別喜歡用的,一旦編不過他就知道有什么問題,然后再單元測試,集成測試,功能測試,最后進入待發布的狀態。所以前半部分藍色的是做持續集成,以達到待發布狀態。
4、低成本、高效地部署發布
有了待發布的制品,如何可以低成本高效地部署發布?
首先看一些常見的問題。最常見的就是延遲集成,比如一個月集成一次,一個月批量提交一把。第二種是累積負債,主干上面一直不穩定,有很多的問題,永遠測不通過,這就是累積負債。
第三個是無測試自動化,整個測試完全靠手工來保證,或者是有測試自動化但是不穩定,沒有辦法依賴,這時就完全靠人去判斷這個測試是否OK。第四個是返工,經常因為質量的問題或者是缺陷導致發布活動經常反復,帶來大量的時間浪費。
還有一個是耗時的活動,比如人工查代碼,人工做每一個階段的審批,人工看每一階段的質量情況,這些都會耗費大量的時間,從而導致整個發布比較低效。當軟件完成某一項工作之后進入一個狀態,要進入下一個狀態時是通過人工的方式判斷狀態遷移,這時耗時就很長,因為存在反饋等待,導致在整個發布的時候相對來說很難做的很高效。
上圖兩個應用的發布統計,上面是A應用,下面是B應用,每個點表示一次發布,綠色的點表示發布成功,黃色的點表示發布被取消了,紅色表示發布失敗。縱軸是這次發布的耗時。橫軸表示的是在哪一天完成了發布,所以縱軸表示的是時長,橫軸表示時間點。
其實這兩個應用都做的不是很好。第一個應用的問題是發布的頻率非常低,很多時候一個月就發一兩次,但是發布的成功率還比較高。第二個應用發布頻率比較高,可能幾天就有一次發布,但是失敗率非常高,失敗的次數遠遠大于成功的次數。
所以兩個各有問題,并且這兩個應用整個發布時間都比較長,經常是要24小時甚至更多。如果發布超過了8小時就意味著在一天中搞不定,需要加班,因為發布是比較高危的事情,很多公司發布的時候都需要盯盤,不可能還沒有發完就先離開。這種情況下如果發布需要耗時超過一天,假設兩個人輪流也需要12個小時。
舉一個例子,有很多企業把他們集成的時間放在周二,發布時間放在周四,因為默認發布要加班,而且周四那天搞不定,周五還要繼續發,所以如果放在周五的話,就需要周六加班。很多情況下,就算放到周四,絕大部分情況下發到周五晚上或者周六才能發上去,發到周日的也不少。
從這兩張圖里面看,我們發現A應用發布頻率很低,很長時間才發一次,另外B應用里面很多發布失敗,確實有相應的一些風險,比如說時間很長,又很容易出錯的話,就很難做到按需發布。
仔細觀察一下B應用,如果接近的時間連續有多次紅點再加一個綠點,往往意味著連續地發布失敗,需要緊急修復再發布。這意味著這個軟件很有可能在緊急修復中間出現風險。想要持續快速高質量,放心大膽地發布上去,就要提到集成和發布的能力。
快速集成的手段包括減小批量和保持順暢。因為集成的粒度和資源利用率以及周期時間是有相關性的,小批量周期時間比較短,大批量周期時間一般來說比較長,資源利用率相對來說比較接近,不會有太大的問題,所以通過減小批量可以讓周期時間盡可能地變短,變短之后頻率就會提高,頻率多反饋又快,對于應用的修復或者相應的問題響應就會變的更快。第二,保持順暢。把里面的問題解決掉之后,才能讓這條道順暢起來。
第一,減小批量,剛剛我們已經提到從需求的粒度和代碼的粒度,需要可發布單元,可測試單元盡可能地少,可構建單元,可單測單元代碼粒度盡可能的小。
從保持順暢的角度來說,我們有很多的實踐,最常見的是各種自動化,比如測試能夠做到自動化,構建的自動化,部署自動化,整個流程串起來能夠自動化,狀態遷移能夠自動化等。
第二,要管理異常,即發布過程當中避免車輛追尾,應該把異常先修復掉,再讓整個過程順暢起來。當發布的這條流水線里面出現問題,這時應該先停下來,先不要checkin,不要觸發,先把問題解決掉。先讓主干變好,然后繼續剩下的工作,要先保證把主干修復掉,剩下的時間再做剩下的集成。有一些企業會要求誰提交代碼誰負責解決掉問題,如果在半小時或者限定時間內解決不掉,系統會自動把代碼摘掉,讓后面的人可以繼續集成。
另外一個是減少依賴,如果集成和發布過程當中,對外部有特別多的依賴,這時也會造成堵塞,因為依賴就會導致等待。
另外一個是質量內建,內建好上游的質量之后才能保證下游更快。如果上游不解決相應的問題,下游肯定會堵塞在那里。我們應該盡早的從上游找問題,盡可能的用一種上游思維思考如何能夠保證早一點讓下游變的更好。
及時反饋也是一樣,有了問題準確及時反饋到具體的人。要避免垃圾式反饋,避免過多無用或不相關的信息打擾開發者,導致開發者對整個反饋機制失去信任。
最后是復用,能復用就盡量復用,避免重復造輪子。
以上是我們認為的持續部署的4個原則及實踐建議。
原文鏈接
本文為阿里云原創內容,未經允許不得轉載。?
總結
以上是生活随笔為你收集整理的2022,你的团队距离持续部署还有多远?的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 开源微服务编排框架:Netflix Co
- 下一篇: NBF事件中心架构设计与实现
