大家好,今天課程的主要內(nèi)容為如何從頭搭建 DevOps 流水線以及其在研發(fā)工作中的意義,最后是 DevOps 流水線實(shí)踐與敏捷開發(fā)的關(guān)系的總結(jié)。 最開始是在極限編程里提出了持續(xù)集成,然后 ThoughtWorks 又提出了持續(xù)交付,之后又提出了DevOps 這個(gè)概念,為什么要做這些呢?我認(rèn)為原因是隨著時(shí)間的增長,生產(chǎn)力會(huì)不斷的下降。團(tuán)隊(duì)剛開始時(shí)效率很高,從 0 到 1,功能上線很快,但是到了后期速度就會(huì)越來越低,直到最后開發(fā)停滯。系統(tǒng)開發(fā)的后期往往會(huì)出現(xiàn)三個(gè)難點(diǎn):第一,增加新特性難。隨著系統(tǒng)功能的累積,會(huì)出現(xiàn)很多重復(fù)的代碼以及不合理的設(shè)計(jì),導(dǎo)致增加一個(gè)新特性時(shí)要改的地方非常多,改動(dòng)成本非常高;第二,修復(fù)缺陷難。用戶可能會(huì)報(bào)一些缺陷或 Bug,但是因?yàn)榇a太亂、太復(fù)雜導(dǎo)致很難定位到缺陷;第三,引出新的缺陷。做新 Feature 時(shí),很容易出現(xiàn)打地鼠的現(xiàn)象,按下一個(gè) Bug 結(jié)果又冒出來三個(gè) Bug,給團(tuán)隊(duì)帶來困境。 出現(xiàn)這些現(xiàn)象的原因首先是在需求演變的過程中,有的代碼會(huì)不斷地腐壞,方法會(huì)越來越長,類會(huì)變得越來越大,代碼出現(xiàn)大量的重復(fù)。雖然有些團(tuán)隊(duì)會(huì)制定代碼規(guī)范,但在實(shí)際應(yīng)用中,可能基本上都在 Word 或 PDF 里“躺著”,檢查執(zhí)行難以長期堅(jiān)持。 其次是架構(gòu)也會(huì)腐壞。項(xiàng)目開始時(shí)架構(gòu)師通常會(huì)根據(jù)業(yè)務(wù)設(shè)計(jì)好架構(gòu),有多少個(gè)模塊、對象,分到幾層,哪層可以調(diào),哪層不能調(diào),怎么依賴關(guān)系,這些都會(huì)很清楚,但在不斷的演變過程中,架構(gòu)往往會(huì)變得亂七八糟。 戴明(William Edwards Deming)提出了質(zhì)量內(nèi)建的概念,即產(chǎn)品的質(zhì)量在建設(shè)過程中就已經(jīng)嵌入,并不是靠后期的檢測來發(fā)現(xiàn)的。后期的檢測并不能增進(jìn)代碼質(zhì)量,也不能提升產(chǎn)品質(zhì)量,問題發(fā)現(xiàn)的越早修復(fù)的成本越低。所以我們希望每一次往代碼庫提交代碼時(shí),都能夠馬上獲得反饋:這次修改是好的還是不好的,是不是增加了重復(fù)的代碼,是不是降低了測試覆蓋率,是不是破壞了某一些功能等等。有了這樣的評(píng)判標(biāo)準(zhǔn),就能夠始終保證每個(gè)人每次提交代碼都是在產(chǎn)品上增加價(jià)值,而不是破壞它。在這個(gè)背景下就引入了流水線這個(gè)概念。 流水線是一個(gè)隱喻,意思是將軟件研發(fā)的各個(gè)環(huán)節(jié)銜接起來。我認(rèn)為流水線在研發(fā)管理過程中扮演了三個(gè)角色:不辭辛勞的臨時(shí)工、鐵面無私的守護(hù)者以及快速精準(zhǔn)的操作員。 流水線是不辭辛勞的臨時(shí)工。現(xiàn)在的構(gòu)建流水線都可以按需創(chuàng)建。比如說 CODING,這么多的企業(yè)在用它的持續(xù)集成功能,不可能給每一個(gè)用戶分配固定的計(jì)算、存儲(chǔ)等資源。如果要能線性的增長,策略應(yīng)該是當(dāng)用戶需要構(gòu)建時(shí)會(huì)按需進(jìn)行創(chuàng)建,并且用完之后進(jìn)行銷毀。從這一點(diǎn)上看,流水線就很像一個(gè)臨時(shí)工。除此之外,流水線還可以不厭其煩地做重復(fù)的事情,尤其是持續(xù)集成的團(tuán)隊(duì)每天都要提交很多次代碼,每一次提交都人工做一次檢查就很痛苦,但機(jī)器就能重復(fù)機(jī)械運(yùn)動(dòng)。 流水線是鐵面無私的守護(hù)者。首先是代碼規(guī)范。很多開發(fā)團(tuán)隊(duì)的代碼規(guī)范都“活”在 Word 或 PDF 里,即使有資深教練或者技術(shù) Leader 偶爾會(huì)做一些代碼評(píng)審,這種執(zhí)行力度也是遠(yuǎn)遠(yuǎn)不夠的。但是通過集成到流水線中的方式,比如指定一個(gè)方法不能超過多少行,一個(gè)類不能超過多少行,代碼重復(fù)率不能超過多少,代碼的寬度及命名等,進(jìn)行自動(dòng)化、標(biāo)準(zhǔn)化的檢測,就可以有效的保證代碼規(guī)范的落地;第二是測試覆蓋率。在日常的開發(fā)工作中會(huì)有單元測試、組件測試、接口測試、集成測試、端到端測試等多種測試,每一次提交代碼都需要檢查測試覆蓋率有沒有下降。但很多團(tuán)隊(duì)這一塊是缺失的,他們在流水線上只是做了構(gòu)建、打包、部署等動(dòng)作,并沒有跑測試覆蓋率,而是靠大規(guī)模的手工測試來保證質(zhì)量,導(dǎo)致無法快速迭代;第三是架構(gòu)約束。代碼一般有分層,每一層里應(yīng)該放什么文件,哪個(gè)文件能夠調(diào)哪個(gè)文件,這些都是有約束的,需要一套自動(dòng)化的機(jī)制來保證落地;其次還有安全性檢查。比如做 Web 開發(fā)會(huì)引入一些第三方的開源代碼,這些開源代碼往往會(huì)有安全缺陷,需要在每次引入新內(nèi)容時(shí)進(jìn)行安全性檢查。 流水線是快速精準(zhǔn)的操作員。越復(fù)雜的系統(tǒng),環(huán)境就越多,包括開發(fā)聯(lián)調(diào)環(huán)境、測試環(huán)境、預(yù)發(fā)布環(huán)境等,到正式的環(huán)境還會(huì)有多個(gè)實(shí)例。每個(gè)環(huán)境上訪問數(shù)據(jù)庫的 URL 不一樣,訪問其他服務(wù)的環(huán)境也會(huì)不一樣,如何保證在操作過程中都不出錯(cuò)?可以依靠流水線來標(biāo)準(zhǔn)化、流程化、自動(dòng)化地完成這些動(dòng)作,每次代碼提交時(shí)都檢查規(guī)范,針對不同的環(huán)境打出不同的包,持續(xù)的部署到不同的環(huán)境上面。 那么如何搭建一條流水線?有一種方式叫做流水線即代碼(Pipeline as Code),即把流水線放到代碼里。我認(rèn)為這樣做的好處是版本化,傳統(tǒng)的搭建方式問題在于操作沒有記錄,也無法強(qiáng)制 Review,當(dāng)一臺(tái)服務(wù)器掛掉,換一臺(tái)服務(wù)器時(shí)需要把原來流水線的配置重新操作一遍。如果將流水線變成代碼,就可以跟蹤及重復(fù)創(chuàng)建,提高生產(chǎn)效率。另外補(bǔ)充一點(diǎn),流水線在構(gòu)建時(shí)主要有兩種方式,一個(gè)叫聲明式,一個(gè)叫指令式。聲明式就是規(guī)定好環(huán)節(jié)與步驟,需要怎樣的東西。而指定式需要寫很多的條件判斷,是邏輯式的,維護(hù)成本也會(huì)高一些,所以聲明式是目前普遍采用的一種方式。 一條典型流水線應(yīng)該包含四個(gè)關(guān)鍵環(huán)節(jié)。第一是構(gòu)建。前端、后端的代碼都需要編譯,前端比如 HTML、JS、CSS 等,可能還會(huì)用到一些模板,需要做編譯工作將其轉(zhuǎn)成瀏覽器能夠支持的格式;第二是檢查。編譯完成之后需要檢查代碼是不是符合規(guī)范,是不是有很多的重復(fù)代碼,重復(fù)率超過了多少等等;第三是測試。測試環(huán)節(jié)很重要,會(huì)影響團(tuán)隊(duì)對于產(chǎn)品發(fā)布的信心。這里講一個(gè)測試金字塔理論:底層是大量的單元測試,中間是組件測試或者接口測試,頂部是端到端測試。因?yàn)榇罅康倪壿嫸际窃诟鞣N If else 分支里,單元測試可以覆蓋到這些分支,那么上層的測試就不需要再覆蓋下層已經(jīng)覆蓋過的邏輯了。而上層測試的價(jià)值在于把這些代碼集成起來,站在用戶的角度去使用它,看看能否正常工作。上層和下層的測試關(guān)注點(diǎn)不一樣,解決的問題也不一樣;第四是部署。最后需要構(gòu)建鏡像,并推到制品庫里面去,更新服務(wù)器,做完這一系列的事情之后,流水線實(shí)例就會(huì)銷毀。 最后總結(jié)一下,為什么會(huì)衍生出 DevOps 實(shí)踐及其跟敏捷開發(fā)的關(guān)系: 第一,我們最重要的目標(biāo)是通過持續(xù)不斷地及早交付有價(jià)值的軟件使客戶滿意。我認(rèn)為這跟敏捷是一脈相承的。敏捷的原則里說可工作的軟件高于詳盡的文檔,客戶更希望看到的是可用的軟件,而不僅僅是文檔說明,但是由于開發(fā)過程的不透明,造成了客戶喜歡做微觀管理的現(xiàn)象,同時(shí)也會(huì)讓開發(fā)團(tuán)隊(duì)變得很被動(dòng)。敏捷里有個(gè)價(jià)值觀叫尊重,這種尊重是需要團(tuán)隊(duì)自己去贏得的。通過建立一套流程,提高開發(fā)過程的透明度,從而建立客戶與團(tuán)隊(duì)之間的信任。另外跟敏捷原則相契合的一點(diǎn)是響應(yīng)變化高于遵循計(jì)劃。這不是一句口號(hào),而是一種能力,它包含:項(xiàng)目管理能力、需求管理能力、配置管理能力以及質(zhì)量保障能力。這四種能力建設(shè)起來之后,團(tuán)隊(duì)才能擁有響應(yīng)變化的能力。持續(xù)集成、自動(dòng)化測試、自動(dòng)部署等這些核心能力,搭配上代碼規(guī)范、CodeReview、TDD等這些實(shí)踐,才能真正提升開發(fā)團(tuán)隊(duì)的實(shí)力,而不是僅僅把 Scrum 導(dǎo)入進(jìn)來,開開計(jì)劃會(huì)、站立會(huì)就行了。 第二,可工作的軟件是進(jìn)度的首要度量標(biāo)準(zhǔn)。不是每天站會(huì)或者每周寫個(gè)郵件告訴客戶這周完成了多少工作,而一定是部署完成后,變成了可以看到的、可以體驗(yàn)的功能才算是真正的進(jìn)度。 第三,堅(jiān)持不懈的追求技術(shù)卓越和良好的設(shè)計(jì),敏捷能力由此增強(qiáng)。開發(fā)團(tuán)隊(duì)擁有了代碼規(guī)范檢查、自動(dòng)化測試等這些質(zhì)量門禁以后,才有底氣去不斷的做優(yōu)化,得到可持續(xù)的、快速迭代的速率。實(shí)踐都會(huì)隨著技術(shù)的變化而變化,團(tuán)隊(duì)能力也在持續(xù)的變化,但能不能持續(xù)地保持敏捷,那就要看價(jià)值觀、原則是不是能夠持續(xù)地符合。 |
|