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