本文來(lái)自Rancher Labs
持續(xù)集成和持續(xù)交付(CI/CD)是DevOps背后的助推力之一懒震。如果你的企業(yè)正在考慮使用DevOps罩息,那么CI/CD絕對(duì)是需要考慮的其中一部分。但是CI/CD到底意味著什么挎狸?為什么它如此重要呢扣汪?為了對(duì)你的DevOps工具包和IT部署進(jìn)行戰(zhàn)略規(guī)劃,深入理解CI/CD至關(guān)重要锨匆。本文中崭别,我們將探討CI/CD所需解決的難點(diǎn)冬筒、需要的工具以及預(yù)期的收益。
首先茅主,我們從大局著手舞痰。DevOps旨在創(chuàng)建一個(gè)流暢的工作流程,并盡可能減少越區(qū)切換和建立快速反饋回路诀姚。這意味著什么呢响牛?工作會(huì)從第一步開始一直向前推進(jìn),并且在理想狀態(tài)中赫段,無(wú)需倒退再進(jìn)行修復(fù)呀打,因?yàn)樗鼈儜?yīng)該能夠驗(yàn)證和修復(fù)問題。為此糯笙,開發(fā)人員需要快速的反饋回路贬丛。該反饋通過(guò)快速自動(dòng)化測(cè)試提供,并且該測(cè)試將驗(yàn)證代碼在進(jìn)入下一階段之前能否按照預(yù)期工作给涕。
為了減少越區(qū)切換豺憔,成員較少的小組將使用較小的功能并且掌控整個(gè)流程:創(chuàng)建請(qǐng)求、提交够庙、QA以及部署恭应。其重點(diǎn)是快速推出小段代碼,因?yàn)樽兏叫≡耪#\斷昼榛、修復(fù)和補(bǔ)救就越容易。
持續(xù)集成(CI)實(shí)現(xiàn)了從第一步到最后一步的快速流程剔难,并通過(guò)持續(xù)交付(CD)將其擴(kuò)展到實(shí)際生產(chǎn)部署褒纲。我們將其稱為CI/CD。現(xiàn)在钥飞,我們開始深入了解它們。
深入探索持續(xù)集成
首先衫嵌,我們關(guān)注CI/CD的CI(持續(xù)集成)部分读宙。實(shí)際上,大部分公司僅執(zhí)行了CI楔绞。而完成整個(gè)CI/CD结闸,需要該企業(yè)已經(jīng)是一個(gè)成熟的DevOps企業(yè)。
說(shuō)到集成酒朵,我們指的是程序員在其本地計(jì)算機(jī)上開發(fā)的代碼(包括更新或添加新特性)集成到代碼庫(kù)中桦锄。這一過(guò)程會(huì)面臨以下3個(gè)挑戰(zhàn):
跟蹤所有變更,以便在發(fā)生錯(cuò)誤時(shí)仍然可以恢復(fù)到之前的狀態(tài)蔫耽,以最大程度地避免服務(wù)中斷结耀。
當(dāng)多個(gè)開發(fā)人員同時(shí)在同一個(gè)項(xiàng)目中工作時(shí)需要管理沖突
將新代碼添加到代碼庫(kù)之前需要捕捉到錯(cuò)誤
接下來(lái)留夜,我們將討論可以解決以上幾個(gè)痛點(diǎn)的3個(gè)工具。
1图甜、 版本控制
隨著代碼從開發(fā)人員轉(zhuǎn)移到運(yùn)維人員碍粥,它會(huì)根據(jù)測(cè)試結(jié)果不斷進(jìn)行調(diào)整。所有的更改都會(huì)被版本控制系統(tǒng)捕捉黑毅。版本控制是一個(gè)軟件工具可以幫助開發(fā)者管理源代碼更改嚼摩。在特殊類型的數(shù)據(jù)庫(kù)中它會(huì)一直跟蹤所有更改。
理想狀態(tài)下矿瘦,軟件系統(tǒng)的所有部分都會(huì)被捕獲到枕面,包括:
源代碼
資產(chǎn)
環(huán)境
軟件開發(fā)文檔
對(duì)系統(tǒng)中存儲(chǔ)的文件的任何更改
2、master和開發(fā)分支
通常情況下缚去,在同一個(gè)項(xiàng)目中會(huì)有多個(gè)開發(fā)人員一起工作潮秘,可能是幾個(gè)人也可能是上百個(gè)程序員,因此這可能會(huì)導(dǎo)致混亂病游。為了不讓穩(wěn)定性遭受破壞或減輕在版本控制主分支中引入錯(cuò)誤的風(fēng)險(xiǎn)唇跨,每個(gè)開發(fā)人員應(yīng)該并行處理系統(tǒng)的不同部分。他們通過(guò)本地計(jì)算機(jī)上的“分支機(jī)構(gòu)(branch)”執(zhí)行這一操作衬衬。
但是在分支機(jī)構(gòu)上工作本身并不是解決方案买猖,每個(gè)開發(fā)人員正在處理的代碼必須集成到不斷擴(kuò)充的代碼庫(kù)中。
開發(fā)人員在分支機(jī)構(gòu)中工作而無(wú)需提交主分支的時(shí)間越長(zhǎng)滋尉,與每個(gè)人在master中所做的更改進(jìn)行集成和合并的難度就越大玉控。所以,由于開發(fā)人員在不提交代碼的情況下處理代碼的時(shí)間越長(zhǎng)狮惜,獲得代碼的難度就越大高诺,因此從邏輯上來(lái)說(shuō)就應(yīng)該增加提交代碼的頻率。但是更好的方法是碾篡,使其持續(xù)集成虱而。
下圖描繪了如何可視化不同分支。藍(lán)色是master分支开泽,其他顏色都是在自己的分支上工作的單個(gè)開發(fā)人員牡拇,這些分支最終合并到master分支中。
不過(guò)穆律,就算有分支機(jī)制也并非一帆風(fēng)順惠呼。即使開發(fā)人員每天提交代碼,沖突仍然會(huì)發(fā)生峦耘。因?yàn)槠渌麍F(tuán)隊(duì)成員會(huì)繼續(xù)做出更改剔蹋,而沒有考慮各方的訴求。實(shí)際上辅髓,集成問題經(jīng)常需要返工泣崩,包括手動(dòng)合并沖突的更改少梁。但是比起開發(fā)團(tuán)隊(duì)整周或一個(gè)月都在埋頭工作而不處理沖突,找出并解決一天工作中的沖突要簡(jiǎn)單很多律想。因此猎莲,盡管無(wú)法避免集成問題,但CI可以大大減少集成問題技即。
3著洼、部署流水線和自動(dòng)化測(cè)試
QA的部分工作是找出錯(cuò)誤并確保代碼是可部署的。傳統(tǒng)流程中而叼,在部署完成后會(huì)由一個(gè)單獨(dú)的團(tuán)隊(duì)來(lái)負(fù)責(zé)QA身笤。因?yàn)殚_發(fā)人員通常每年僅執(zhí)行幾次測(cè)試,因此在引入更改幾個(gè)月后他們才了解到錯(cuò)誤葵陵。到那時(shí)液荸,因果之間的聯(lián)系可能已經(jīng)很難查證,導(dǎo)致診斷越來(lái)越困難脱篙。但是自動(dòng)化測(cè)試解決了這個(gè)問題娇钱。
使用部署流水線之后,每次將代碼添加到版本控制中都會(huì)觸發(fā)一系列測(cè)試绊困。流水線會(huì)自動(dòng)構(gòu)建和測(cè)試代碼以確保它可以按預(yù)期工作文搂,并且一旦集成到代碼庫(kù)中就可以繼續(xù)工作。雖然在測(cè)試環(huán)境中代碼可以完美執(zhí)行秤朗,但它仍有可能在生產(chǎn)環(huán)境中不幸失敗煤蹭,因?yàn)樯a(chǎn)中的環(huán)境和所有依賴項(xiàng)都會(huì)影響代碼性能。依賴項(xiàng)并不屬于app中的一部分取视,但仍需要運(yùn)行它硝皂。例如數(shù)據(jù)庫(kù)、數(shù)據(jù)/對(duì)象存儲(chǔ)以及服務(wù)和應(yīng)用程序可能需要調(diào)用的API作谭。因此稽物,開發(fā)和測(cè)試環(huán)境必須模仿生產(chǎn)環(huán)境。另外折欠,必須對(duì)所有依賴項(xiàng)進(jìn)行代碼測(cè)試姨裸。
簡(jiǎn)而言之,部署代碼時(shí)有3個(gè)測(cè)試階段怨酝,每個(gè)階段都會(huì)額外增加復(fù)雜性:
(1)驗(yàn)證代碼本身是否按照預(yù)期工作;
(2)在代碼庫(kù)中繼續(xù)進(jìn)行驗(yàn)證那先;
(3)驗(yàn)證性能在具有所有依賴項(xiàng)的類生產(chǎn)環(huán)境中保持不變农猬。
如果代碼每天都被提交到版本控制中,則可以對(duì)其進(jìn)行自動(dòng)化測(cè)試售淡,并且在引入代碼之日會(huì)標(biāo)記出任何構(gòu)建斤葱、測(cè)試或集成錯(cuò)誤慷垮,從而可以立即進(jìn)行修復(fù)。這確保代碼總是處于可部署和可運(yùn)送的狀態(tài)揍堕,稱為綠色構(gòu)建料身。
自動(dòng)測(cè)試允許開發(fā)人員提高測(cè)試和集成的頻率——從周期性執(zhí)行到持續(xù)測(cè)試集成,并在約束最少的情況下發(fā)現(xiàn)問題衩茸。最糟糕的情況也不過(guò)是一天的工作都浪費(fèi)了芹血。
關(guān)于版本控制的爭(zhēng)議
關(guān)于是否改在版本控制中存儲(chǔ)敏感信息(如 access token、密鑰和密碼)進(jìn)行了一些討論楞慈。一方面幔烛,有人認(rèn)為應(yīng)該將一切(包括secret)都存儲(chǔ)在這里,從而將這一方法推向極限囊蓝。但是有人認(rèn)為這是不良做法饿悬,并認(rèn)為敏感信息應(yīng)該單獨(dú)存儲(chǔ)。
版本控制允許開發(fā)人員比較聚霜、合并和還原以前的修訂狡恬。通過(guò)允許他們?cè)诔霈F(xiàn)問題時(shí)將生產(chǎn)中的系統(tǒng)快速還原到以前的版本,從而將風(fēng)險(xiǎn)降到最低蝎宇。為此弟劲,無(wú)論版本多小,所有更新和更改都必須在版本控制中進(jìn)行跟蹤夫啊。如果不是這樣函卒,生產(chǎn)中的代碼將開發(fā)和測(cè)試環(huán)境中的代碼不匹配,從而導(dǎo)致不一致撇眯。
簡(jiǎn)而言之报嵌,版本控制是事實(shí)的單一來(lái)源,包含了系統(tǒng)的預(yù)期狀態(tài)以及所有以前的狀態(tài)熊榛。通過(guò)將所有生產(chǎn)環(huán)境中的組件放置到版本控制中锚国,開發(fā)人員可以重復(fù)可靠地重現(xiàn)工作軟件系統(tǒng)中的所有組件。這是啟用所謂的不可變基礎(chǔ)架構(gòu)的關(guān)鍵玄坦,我們將在稍后討論血筑。
持續(xù)交付:擴(kuò)展CI以實(shí)現(xiàn)流暢的代碼部署
即使使用了持續(xù)集成,將代碼部署到生產(chǎn)中的過(guò)程依舊是手動(dòng)煎楣、乏味且容易出錯(cuò)的豺总。如果真是這樣,那么顯然不會(huì)頻繁地將代碼部署到生產(chǎn)中择懂。IT部門會(huì)盡可能避免執(zhí)行艱巨而危險(xiǎn)的任務(wù)喻喳,這會(huì)導(dǎo)致要部署的代碼與生產(chǎn)中運(yùn)行的代碼之間差異越來(lái)越大,進(jìn)一步加具危險(xiǎn)困曙,然后形成一種惡性循環(huán)表伦。那么解決這一惡性循環(huán)的答案是啟用CI/CD中的CD部分谦去。
CD擴(kuò)展了CI,確保在將代碼推廣到整個(gè)用戶群之前讓代碼在生產(chǎn)環(huán)境中能夠平滑運(yùn)行蹦哼。最常見的CD方法是金絲雀和藍(lán)綠部署鳄哭。
進(jìn)行藍(lán)綠部署期間,IT會(huì)與當(dāng)前版本一起部署一個(gè)新的組件或應(yīng)用程序版本纲熏。新版本(綠)被部署到生產(chǎn)中并對(duì)其進(jìn)行測(cè)試妆丘,與此同時(shí)當(dāng)前版本(藍(lán))依舊可以使用。如果新版本的代碼運(yùn)行良好赤套,那么所有用戶將會(huì)切換到新版本中飘痛。
金絲雀部署也有兩個(gè)版本:當(dāng)前版本和更新版本。IT開始將一小部分用戶請(qǐng)求路由到新版本容握。代碼和用戶的行為會(huì)被持續(xù)監(jiān)控宣脉。如果錯(cuò)誤率或用戶投訴并沒有增加,則路由到新版本的請(qǐng)求份額將逐漸增加(例如剔氏,1%塑猖、10%、50%最后到100%)谈跛。一旦所有請(qǐng)求都發(fā)送到新版本中羊苟,那么舊版本就會(huì)自動(dòng)退休或刪除。
通過(guò)按需環(huán)境創(chuàng)建自助服務(wù)
現(xiàn)在感憾,我們已經(jīng)研究了CI蜡励、CD及其各自的工具和方法,下面我們來(lái)討論環(huán)境和基礎(chǔ)架構(gòu)阻桅。CI / CD需要一種創(chuàng)新的方法凉倚。
如我們所見,自動(dòng)化測(cè)試使開發(fā)人員可以自己執(zhí)行QA嫂沉。為了確保一切都能在生產(chǎn)中正常運(yùn)行稽寒,他們必須在整個(gè)開發(fā)和測(cè)試過(guò)程中使用類似于生產(chǎn)的環(huán)境。
傳統(tǒng)上趟章,開發(fā)人員必須向Ops團(tuán)隊(duì)請(qǐng)求(手動(dòng))設(shè)置的測(cè)試環(huán)境杏糙。此過(guò)程可能需要數(shù)周,有時(shí)甚至數(shù)月蚓土。此外宏侍,手動(dòng)部署的測(cè)試環(huán)境通常會(huì)出現(xiàn)配置錯(cuò)誤,或者與生產(chǎn)環(huán)境有很大差異蜀漆,因此即使代碼通過(guò)了所有預(yù)部署測(cè)試负芋,仍然會(huì)導(dǎo)致生產(chǎn)問題。
CI / CD的關(guān)鍵部分是為開發(fā)人員提供按需類似于生產(chǎn)的環(huán)境,使其可以在自己的工作站上運(yùn)行旧蛾。為什么這很重要?開發(fā)人員只有在相同的條件下進(jìn)行部署和測(cè)試時(shí)蠕嫁,才能知道代碼在生產(chǎn)中的行為锨天。如果他們?cè)诓煌沫h(huán)境中測(cè)試代碼,則當(dāng)最終將代碼部署到生產(chǎn)環(huán)境中時(shí)剃毒,他們可能會(huì)發(fā)現(xiàn)代碼不兼容病袄,那么此時(shí)對(duì)客戶造成了重大影響,再解決問題已經(jīng)為時(shí)已晚赘阀。
不可變基礎(chǔ)設(shè)施:牛與寵物
在討論版本控制系統(tǒng)時(shí)益缠,我們談到了將環(huán)境與所有其他應(yīng)用程序組件進(jìn)行編碼的需求,接下來(lái)讓我們進(jìn)一步討論這些環(huán)境基公。
如果在版本控制中定義了環(huán)境規(guī)范并進(jìn)行了編碼幅慌,那么在容量增加(水平擴(kuò)展)時(shí)復(fù)制環(huán)境就像按一個(gè)按鈕一樣簡(jiǎn)單(盡管之后它很有可能通過(guò)Kubernetes自動(dòng)化了)。
擴(kuò)展意味著在高峰時(shí)段增加計(jì)算能力轰豆。例如胰伍,Netflix的使用率在每個(gè)星期五晚上達(dá)到峰值,然后在午夜之后的某個(gè)時(shí)間再次恢復(fù)正常酸休。為了確保享受無(wú)緩沖的視頻骂租,Netflix復(fù)制了其流控制組件(已在版本控制中進(jìn)行了編碼),以滿足需求斑司。然后渗饮,流量恢復(fù)后所有所謂的副本都被破壞,使流容量恢復(fù)正常宿刮。
為了實(shí)現(xiàn)這一點(diǎn)互站,至關(guān)重要的是,每當(dāng)實(shí)施基礎(chǔ)架構(gòu)或應(yīng)用程序更新時(shí)糙置,這些基礎(chǔ)架構(gòu)或應(yīng)用程序都會(huì)自動(dòng)復(fù)制到其他地方并置于版本控制中云茸。這將確保無(wú)論何時(shí)創(chuàng)建新環(huán)境,它都將與整個(gè)流水線(從dev到QA到生產(chǎn))的環(huán)境匹配谤饭。例如标捺,如果Netflix要更新其流服務(wù)而忘了捕獲版本控制的更改,它將在高峰時(shí)段復(fù)制有故障或過(guò)時(shí)的組件揉抵,從而導(dǎo)致問題甚至服務(wù)中斷亡容。
由于掌握了版本控制中的環(huán)境編碼,因此手動(dòng)更改環(huán)境不是最佳實(shí)踐冤今,因?yàn)槿魏问謩?dòng)操作都容易出錯(cuò)闺兢。而應(yīng)該將更改放入版本控制中,并從頭開始重新創(chuàng)建環(huán)境(和代碼)。這稱為不可變基礎(chǔ)架構(gòu)屋谭。這些與CI / CD部分中討論的應(yīng)用于基礎(chǔ)架構(gòu)的原則相同脚囊。
你也許聽過(guò)牛與寵物的比喻。這個(gè)比喻放在這里十分合適桐磁。以前悔耘,基礎(chǔ)設(shè)施被視為寵物。如果有問題我擂,你會(huì)盡力解決它衬以,以便它可以生存。今天校摩,基礎(chǔ)設(shè)施被視為牛看峻。如果它無(wú)法正常工作或需要更新,請(qǐng)殺死它并啟動(dòng)新環(huán)境衙吩。這非常強(qiáng)大互妓,并且大大降低了問題潛入系統(tǒng)的風(fēng)險(xiǎn)。
發(fā)布與部署解耦
傳統(tǒng)上分井,軟件發(fā)布是由市場(chǎng)啟動(dòng)日期驅(qū)動(dòng)的车猬。因此,要發(fā)布的新功能會(huì)在宣布日期的前一天部署到生產(chǎn)中尺锚。但是珠闰,我們知道將特性或更新發(fā)布到生產(chǎn)中總是有風(fēng)險(xiǎn)的,尤其是如果你一次發(fā)布整個(gè)特性時(shí)瘫辩。因此伏嗜,將部署與發(fā)布捆綁在一起將使IT部門總是需要為失敗膽戰(zhàn)心驚。試想一下伐厌,如果在廣泛推廣的前一天發(fā)生了重大問題承绸,IT團(tuán)隊(duì)就會(huì)感到恐慌,并且會(huì)在客戶和媒體中引起巨大不良反響挣轨。
更好的方法是使部署與發(fā)布解耦军熏。盡管這兩個(gè)詞經(jīng)常互換使用卷扮,但它們是兩個(gè)獨(dú)立的過(guò)程荡澎。部署意味著將軟件版本安裝到任何環(huán)境(包括生產(chǎn)環(huán)境)中。它不一定必須與發(fā)布相關(guān)聯(lián)晤锹。另一方面摩幔,發(fā)布意味著向客戶群提供新功能。在整個(gè)功能開發(fā)過(guò)程中頻繁進(jìn)行生產(chǎn)部署的目的是降低服務(wù)中斷的風(fēng)險(xiǎn)鞭铆,該風(fēng)險(xiǎn)由IT部門承擔(dān)或衡。另一方面,何時(shí)向客戶展示新功能應(yīng)該是業(yè)務(wù)決策,而不是技術(shù)決策封断。
部署周期長(zhǎng)會(huì)決定新功能發(fā)布的頻率斯辰。如果IT可以按需部署,那么公開新功能的速度應(yīng)該成為業(yè)務(wù)和市場(chǎng)營(yíng)銷的決定坡疼。
結(jié) 論
總而言之椒涯,CI要求將代碼連續(xù)集成到代碼庫(kù)中,以在發(fā)生錯(cuò)誤時(shí)捕獲錯(cuò)誤回梧,從而最大程度地減少返工。要實(shí)現(xiàn)這種方法祖搓,需要三個(gè)工具:版本控制狱意,以跟蹤所有更改并使整個(gè)團(tuán)隊(duì)都可以使用最新的源代碼版本;master拯欧,負(fù)責(zé)自己分支的開發(fā)人員每天合并更新详囤;部署流水線將觸發(fā)一系列測(cè)試,基本上是自動(dòng)進(jìn)行QA镐作。
CD擴(kuò)展了CI藏姐,以驗(yàn)證代碼是否處于可部署狀態(tài),并自動(dòng)將其釋放到生產(chǎn)環(huán)境中该贾。為此羔杨,需要一個(gè)成熟的DevOps組織,該組織必須先掌握CI杨蛋,然后才能嘗試使用CD兜材。
如果實(shí)施得當(dāng),CI(/ CD)將大大提高你的IT團(tuán)隊(duì)的生產(chǎn)力逞力。你的系統(tǒng)或應(yīng)用程序在不斷改進(jìn)曙寡,同時(shí)將部署風(fēng)險(xiǎn)降至最低,從而增強(qiáng)了生產(chǎn)力和員工滿意度的積極循環(huán)寇荧。此外举庶,快速推出新功能和更新可推動(dòng)創(chuàng)新,進(jìn)而更快揩抡,更頻繁地為用戶帶來(lái)價(jià)值户侥。顯然,隨著越來(lái)越多的組織采用這些DevOps方法捅膘,由于傳統(tǒng)方法無(wú)法與CI / CD競(jìng)爭(zhēng)添祸,因此對(duì)那些沒有采用DevOps方法的企業(yè),壓力會(huì)越來(lái)越大寻仗。
附錄:部署流水線測(cè)試套件
集成測(cè)試檢查應(yīng)用程序如何與其他應(yīng)用程序和服務(wù)交互刃泌,以確保代碼與這些依賴項(xiàng)正確交互。遠(yuǎn)程服務(wù)的虛擬或模擬版本可用于準(zhǔn)確地重新創(chuàng)建生產(chǎn)環(huán)境。
驗(yàn)收測(cè)試會(huì)驗(yàn)證是否滿足業(yè)務(wù)需求耙替,以確保功能或應(yīng)用程序?yàn)樽罱K用戶提供所需的價(jià)值亚侠。
性能測(cè)試可驗(yàn)證該應(yīng)用程序在類似生產(chǎn)的負(fù)載下如何在整個(gè)堆棧(代碼、數(shù)據(jù)庫(kù)俗扇、存儲(chǔ)硝烂、網(wǎng)絡(luò)、虛擬化)中工作铜幽。由架構(gòu)決策或網(wǎng)絡(luò)滞谢、數(shù)據(jù)庫(kù)、存儲(chǔ)或其他系統(tǒng)的意外限制引起的問題應(yīng)在此處解決除抛。
非功能測(cè)試包括可用性狮杨、可伸縮性、性能到忽、容量橄教、安全性等。這些要求取決于環(huán)境的正確配置喘漏。測(cè)試將驗(yàn)證環(huán)境是否已正確構(gòu)建和配置护蝶。
冒煙測(cè)試驗(yàn)證該應(yīng)用程序可以連接到所有支持系統(tǒng),例如數(shù)據(jù)庫(kù)翩迈、服務(wù)或信息傳遞系統(tǒng)持灰;冒煙測(cè)試通常是手動(dòng)的。
也有自動(dòng)安全性測(cè)試以及探索性和其他手動(dòng)或資源密集型測(cè)試帽馋。我們的目標(biāo)是盡早捕獲更多錯(cuò)誤搅方,并使用這些更耗時(shí)的測(cè)試來(lái)驗(yàn)證高層次的需求,并將產(chǎn)品完全集成到盡可能接近生產(chǎn)的環(huán)境中绽族。