今天的話題是,持續(xù)集成和“云”,主要部分是我之前兩年的工作和我的一些個人思考。
這個話題我之前在中國的ruby大會上講過,slides在這里 ,供參考,不過但是現(xiàn)在講的內(nèi)容根據(jù)最近多半年的工作進展又有所變化。
先自我介紹一下,我是軟件工程師,從業(yè)13年,主要從事的領(lǐng)域都是應(yīng)用系統(tǒng)開發(fā),涉及
OA、電信網(wǎng)管/增值業(yè)務(wù)、互聯(lián)網(wǎng)等領(lǐng)域。
2009年底加入阿里,2015年4月離職,主要做的事情:廣告應(yīng)用系統(tǒng) -> 運維自動化平臺 -> 持續(xù)集成服務(wù)平臺。
最后的持續(xù)集成服務(wù)平臺是來自于實踐需要,我最先在做廣告業(yè)務(wù)系統(tǒng)的研發(fā)工作,廣告系統(tǒng)雖然復(fù)雜,但是其中的應(yīng)用系統(tǒng)從軟件架構(gòu)上看并沒有什么特別的地方,所以希望將精力投在可以改進團隊工作水平的地方。
一開始是一個運維自動化平臺,由于團隊人手有限,我基本是一個人做的,發(fā)現(xiàn)開發(fā)效率很好,軟件質(zhì)量也不錯,所以在工作中總結(jié)了一些質(zhì)量改進的實踐,在團隊中推廣,這是我從研發(fā)進入QA的起點。
經(jīng)過一段時間摸索,我們發(fā)現(xiàn)測試自動化搞不起來的原因之一是成本太高。
我之前習(xí)慣用ruby或者rails,所有的測試都可以單機完成,用cucumber這樣的工具可以做BDD,用vagrant可以避免環(huán)境污染,所以自動化沒問題。而java就沒有這些條件了,數(shù)據(jù)庫掌握在DBA手里,測試的linux是大家公用的,很容易引起沖突。
于是我和主管商量,決定搞一個平臺,通過它降低研發(fā)成本,在本團隊開展一段時間以后,又帶著系統(tǒng)轉(zhuǎn)到技術(shù)質(zhì)量部,把CISE做大,測試部門成立了專門的團隊,離職前已經(jīng)開始在各bu和研發(fā)團隊廣泛運用。
對CI的理解
持續(xù)集成平臺究竟解決什么問題呢?
簡單說,就是兩個自動化:
· 構(gòu)建自動化
· 測試自動化
測試自動化好理解,構(gòu)建自動化比想象中要復(fù)雜一些,我一般用下面這張圖來解釋。
我們手里的軟件,總是可以進行不斷地分解,從系統(tǒng)到模塊,最后到類和方法。由于整體和部分的功能不能完全劃等號,所以測試需要在各個層面上進行,但是這些測試的成本和收益有所不同。
如圖,我之前感到j(luò)ava開發(fā)的痛苦,就源于工程師手中沒有更上層的“武器”,所以只能在單測上用力。
所以,如果我們能做好更大尺度系統(tǒng)的自動化的構(gòu)建,那么研發(fā)人員也就有機會使用“高層”的自動化測試,而避免在細節(jié)上寫太多的用例。
但這個并不容易,我們的努力也只是起到了一部分作用。
平臺介紹
下面說一下這個平臺本身,由于涉及到阿里巴巴內(nèi)部系統(tǒng),有些是不能說的,不過還好,核心部分并沒啥技術(shù)含量 :-)
很多人對CI的了解是基于jenkins,當(dāng)然也有些人接觸過travis CI或者circle CI,我們的系統(tǒng)更像后者,當(dāng)然功能上要更強些。
平臺的起點是公司的gitlab和svn服務(wù),通過自動監(jiān)控或者hook觸發(fā),每一次代碼提交都會觸發(fā)一個自動化過程,在這個過程中,平臺負責(zé)分配虛擬機、數(shù)據(jù)庫等必要資源,然后將代碼編譯打包構(gòu)建運行。
編譯打包構(gòu)建運行看起來是一個自動化過程,但每個環(huán)節(jié)實際上都可以有驗證——這其實就是各種測試。
· 編譯前可以做代碼掃描(有的語言是編譯后做代碼掃描)
· 編譯之后可以做單測
· 打包運行后可以做集成測試
和travis不同的是,如果目標涉及多個應(yīng)用,之間存在服務(wù)調(diào)用,那么我們還會自動的將相關(guān)應(yīng)用也部署好,然后在一個機器群里面做更接近真實場景的功能測試。
做過類似工作的同學(xué)一定知道這一點的代價有多大,但這樣會有很大好處——我們可以在一次commit后自動進行所有層面的測試——從單測到系統(tǒng)交付測試。
當(dāng)然這是理論上的,實際中可以根據(jù)研發(fā)團隊需要進行選擇。
總結(jié)一下,我們認為,CI平臺應(yīng)該能進行所有粒度的測試,最小針對函數(shù),最大可以針對分布式系統(tǒng)。作為前提,CI平臺需要支持整個系統(tǒng)的自動化構(gòu)建。
這個大概是和travis CI之間最大的不同,下面再列幾個不是很重要的區(qū)別。
使用云平臺解決虛機問題,身在阿里巴巴,所以我們使用阿里云的ECS,需要資源是隨時申請,用過以后立即釋放重置。
這樣可以解決環(huán)境污染的問題(即使是java應(yīng)用,有些團隊也會留下本地文件操作,這些東西會導(dǎo)致測試不可重復(fù))。
數(shù)據(jù)庫自動分配,我們構(gòu)建了mysql集群,不過不是一般意義上的那種協(xié)作集群,而是一個數(shù)據(jù)庫池,讓數(shù)據(jù)庫和虛機一樣隨用隨取,用后重置。
這樣做是為了讓java程序員也可以像rails的db migration一樣可以用到干凈的數(shù)據(jù)庫。
對這個平臺的介紹就這些,下面討論一些經(jīng)驗教訓(xùn)。
經(jīng)驗教訓(xùn)
UI應(yīng)該盡量輕
這個話題要和jenkins/hudson做對比,這兩個系統(tǒng)我其實不是很熟,不過也知道它們都是很強大的自動化系統(tǒng)。但是,jenkins/hudson的最大問題是,它們的UI做的太多了,用戶可以在UI上做很多事——很多和CI沒關(guān)系的事情。
舉個例子:
jenkins的任務(wù)是可以排隊調(diào)度的,而對于CI來說,排隊是什么意思呢?研發(fā)工程師養(yǎng)成持續(xù)小步提交代碼這個好習(xí)慣以后,又硬生生由于資源不足而被迫等待,最終可能會放棄這個好習(xí)慣,實在是不劃算。
我們的辦法是——敞開供應(yīng),只要有代碼提交就分配機器,當(dāng)然有人會質(zhì)疑,因為這會導(dǎo)致需要一個很大的資源后備池,不過這可能正是“云”時代的不同思考方式——在“云”的時代,資源的使用毛刺應(yīng)該通過大規(guī)模后備池來抹平。
當(dāng)然,濫用資源還是要避免的,只是我們認為需要“后置懲罰”,比如通過審計,找出資源消耗大戶,打他的板子。
當(dāng)我們把所有的額外功能都剝掉以后,發(fā)現(xiàn)UI其實就一個作用——展現(xiàn),因為CI需要的是完全的自動化,人工本來就不需要介入,只要最后被notify一下,或者偶爾過來在web上看看報表趨勢什么的就夠了。
CI是服務(wù)加最佳實踐
我們理解的第二個經(jīng)驗就是,搞CI,是服務(wù)加最佳實踐,所以一定要指導(dǎo)研發(fā)團隊,而不能完全任由研發(fā)團隊提要求,很多團隊的工程師良莠不齊,對各種編程api比較熟悉,但是可能缺乏做事的好習(xí)慣,這時需要指導(dǎo)他們,當(dāng)然前提是你也要對開發(fā)很了解才行,否則會被鄙視的。
對CI來說,最大的常見麻煩是不寫測試,這個一般是通過管理教育,比較簡單。
另外一個隱藏的比較深——開發(fā)人員對系統(tǒng)的運行并不了解,比如開發(fā)的系統(tǒng)運行在linux上,但是基本的命令都不會。
這個問題我們遇到了挑戰(zhàn),有人認為這涉及到分工,研發(fā)工程師不應(yīng)該了解線上,但是這個觀點是有問題的。
因為很多bug和環(huán)境相關(guān),如果開發(fā)人員不能在”真“的環(huán)境中嘗試,一旦系統(tǒng)報錯,很難不發(fā)生扯皮——這個扯皮可能發(fā)生在開發(fā)和測試之間,更可怕的是發(fā)生在線上,光定位就需要N多人參與,成本極大。
插件
最后是插件的問題,這個說來簡單——插件能解決一些問題,不過插件設(shè)計之初實際上就限制了其使用,所以我總結(jié)的教訓(xùn)就是:先別急著做插件,想好了設(shè)計再動手。
更進一步
先進一步談?wù)剬I平臺職責(zé)的理解,然后結(jié)合這些理解最后說說“云”和docker的作用
CI平臺的職責(zé)
關(guān)于CI平臺的職責(zé),我上次已經(jīng)提過,基本上就是這些:
構(gòu)建自動化:提供環(huán)境
測試自動化:提供平臺
先說構(gòu)建
構(gòu)建工作主要產(chǎn)出兩個東西:最終輸出的軟件包和待測的應(yīng)用系統(tǒng)(有時后者會包含前者),這兩個產(chǎn)出的核心要點有所不同。
最終輸出的軟件包大多數(shù)公司都會做的,重點是構(gòu)建過程環(huán)境無關(guān)而且可重復(fù),因此需要提供配管服務(wù),比如最好有yum、npm、gem等軟件包服務(wù)。
但是這里有個問題——間接依賴的軟件包如何鎖定的問題,ruby的bundle機制很不錯,通過Gemfile.lock讓依賴包都有明確的版本(而不是“最新版本”這種含糊的說法),但是maven就沒有這樣的支持,目前沒有很好地辦法,只能讓構(gòu)建號和軟件包號建立關(guān)聯(lián),便于回溯。
而待測的應(yīng)用系統(tǒng)是比較難的地方,它也需要配管系統(tǒng)支持,同時還需要資源的就緒能力,一個關(guān)鍵要點是——資源必須是隔離的,否則很難避免測試時互相干擾。
這個隔離應(yīng)該做到什么程度呢?舉個例子,我們?yōu)榱诉M行系統(tǒng)聯(lián)調(diào),自動構(gòu)建了一套涉及N個系統(tǒng)的集群,這個集群是為了進行自動的聯(lián)調(diào)測試。而理論上我們?nèi)绻枰珻I平臺應(yīng)該可以再構(gòu)建另一個集群,各種架構(gòu)細節(jié)和前一個集群完全相同,但這兩個集群進行工作時應(yīng)該互不影響。
這要求應(yīng)用需要符合一些最佳實踐的要求,比如12 factor里面說的不要硬編碼ip地址等等
為什么要這樣?因為持續(xù)集成是不斷前進的工作節(jié)奏,一個人的工作有了階段性結(jié)果后,需要進行驗證,這種驗證應(yīng)該是獨立的,如果和其他人共享測試環(huán)境,要么測試結(jié)果不穩(wěn)定,要么變成我上次說到的排隊,那就降低了效率。
這兩張圖說的就是這個意思,同一團隊的兩個程序員公用數(shù)據(jù)庫進行測試,測試結(jié)果就會不穩(wěn)定,同樣,如果他們的應(yīng)用依賴了另一個公共服務(wù),那么測試依然不能穩(wěn)定。
不知道第二種情況會不會難以理解,簡單說就是那個公共服務(wù)也是有存儲的,所以那個數(shù)據(jù)庫里面的數(shù)據(jù)會造成干擾。
構(gòu)建自動化比較復(fù)雜,而測試自動化相對來說簡單一些,不過這里的重點是對各種測試的抽象和區(qū)分。
根據(jù)上次分享的反饋,發(fā)現(xiàn)有相當(dāng)多的人不太理解這張圖。
我們把測試分為UT/FT/IT/ST等等,但其實它們可以抽象成一個東西——都是對某個軟件單元的驗證,區(qū)別在于單元的粒度
補充說明一下上面說的一些名詞:
· UT:單元測試
· FT:功能測試
· IT:集成測試
· ST:系統(tǒng)測試
所謂的“上層用例變化慢“,是相對的,因為應(yīng)用系統(tǒng)常常是需求一變,整個推翻,所以上層需求用例的變化常常帶來下層大量用例的變化,而反之則未必.
考慮到需求和測試用例直接聯(lián)系很緊密,我們可以認為需求用例的變動頻率和測試用例的變動正相關(guān)。
當(dāng)然,測試自動化還有一個要做的工作是對結(jié)果的分析匯總,主要是各種測試手段的輸出千差萬別,需要進行數(shù)據(jù)匯總,這個和普通的數(shù)據(jù)處理沒啥區(qū)別,我也不是這方面的專家,就不獻丑了。
但是,作為CI平臺,對結(jié)果數(shù)據(jù)的分析匯總要建立在測試階段的界定上,簡單說就是要明確區(qū)分UT、IT等環(huán)節(jié)階段,這是后續(xù)報表很重要的信息,不能小看。
CI職責(zé)講完了,我下面想說一下自己對“云”在CI方面價值的理解——簡單說就是標準化。
CI的自動化測試和普通測試一樣,有天生就要面對的問題:
· bug確認(可重現(xiàn))
· 代碼覆蓋
· 測試的真實性
先說bug確認的困難,在測試團隊待過的人一般都能理解問題確認有多麻煩,很多的bug是辛辛苦苦發(fā)現(xiàn)的,結(jié)果被開發(fā)同學(xué)一句“環(huán)境不一樣”就打發(fā)了。
所以測試非常需要標準的環(huán)境,而這正是“云”可以提供的,要是進一步考慮自動化測試,那是比普通測試更需要標準環(huán)境的場合,因為它是無人值守的,對意外的適應(yīng)能力更弱。
代碼覆蓋也是測試的一個重要指標,幾乎所有的開發(fā)語言和框架都有不止一個代碼測試覆蓋率統(tǒng)計工具,而代碼覆蓋其實是涉及到測試層次的,在上層測試一個系統(tǒng),往往能夠覆蓋不少下層用例,如果能從多個層次測試系統(tǒng),可以讓工作事半功倍。
最后再說一下測試的真實性,這里是指對mock技術(shù)的使用。我們很多時候使用mock技術(shù)只有一個原因——對方系統(tǒng)太難打交道了,所以做個mock先繞開(有時需要模擬對端錯誤,這種情況還是需要mock的)。
但是真實情況下我們訪問的不是白板方法,這么做的有風(fēng)險,最后還是要聯(lián)調(diào),所以這種情況是把測試推后了,是轉(zhuǎn)移矛盾而不是解決矛盾。
我之前做的CI平臺,正是想通過云技術(shù),可以相對低成本的構(gòu)建“全部系統(tǒng)”,因為(借助我們的平臺)有時候這個做法比mock要簡單,更重要的是,這種做法肯定比mock要真實。
以上都是云的價值,也是docker的價值,不過docker有個獨特的價值,就是有可能將測試甚至運維工作變成服務(wù)。
這里說的服務(wù)不是那種在公司里某個部門為其它團隊提供的服務(wù)平臺,那很容易模糊邊界(比如開發(fā)要求測試幫忙等等)。
這里的服務(wù)是指成立公司,把這些工作變成business的東西。
當(dāng)然,這塊其實不稀奇,我之前說過的Traivs CI、shippable、coding應(yīng)該都在做,docker創(chuàng)業(yè)團隊大多都在做這個,不過我想說的是——為什么這事變得可行了?
這是由于標準化,一個應(yīng)用應(yīng)該是個什么樣子?在docker的語境中是比較一致的,這為用戶和服務(wù)平臺提供了相對簡單的協(xié)作邊界。
舉個例子,這是我們平臺自己的一個模塊在進行自動化構(gòu)建時寫到描述文件(相當(dāng)于 .tavis.yml)中的內(nèi)容:
這么一大坨,我不相信會有人能受得了,但是如果在docker中呢?
這樣還符合我之前說的原則——開發(fā)人員自己管理環(huán)境
在這種變化下,我覺得我們做的東西可以大幅度簡化,以至于變?yōu)橐粋對外服務(wù)的business,根據(jù)這個想法,我自己做了一點簡單的嘗試,不過是用青云做的,錄了兩段很短的視頻,在這里:
http://v.youku.com/v_show/id_XODAzNzgyMjUy.html
http://v.youku.com/v_show/id_XODAzNzgxOTky.html
我要講的基本上就這些,今天應(yīng)該沒超時,最后關(guān)于docker上的CI再多說兩句,提個想法——docker應(yīng)該依靠但不依賴IAAS。
借助SDN,避免通過Docker來劃分安全域:我看了一點最近docker大會的介紹,老實說,有一種觀點是把vm廢掉,我是不以為然的,所謂vm所帶來的成本其實正是我們獲得安全隔離的原因,這兩者是一體的,我們直接拿來用vm做安全隔離最好,讓docker解決安全問題應(yīng)該是一條歧路。
深度依賴compose機制,建立聯(lián)調(diào)/系統(tǒng)測試的構(gòu)建標準:應(yīng)該會有很多人和我想的一樣——將compose.yml作為重要信息來源,外部的系統(tǒng)通過它理解應(yīng)用間的聯(lián)系,即使不使用 docker compose 這個軟件,也應(yīng)該遵循 compose.yml 的規(guī)范,這樣我們不但能讓單兵(容器)的外部邊界清晰,還能讓戰(zhàn)陣(分布式系統(tǒng))也能被管控系統(tǒng)理解和支撐。
深度依賴compose需要讓compose.yml目的變得純粹些,我知道compose描述的內(nèi)容很容易變成“不同環(huán)境”,其實這個想法也許不正確,我認為一個git分支就對應(yīng)一種場景——比如某些分支是用來開發(fā)局部功能的,它不需要系統(tǒng)測試和聯(lián)調(diào),而master必然要聯(lián)調(diào)——所以不用在代碼中留下多份 compose_xxx.yml,而應(yīng)該在不同分支上編寫不同的 compose.yml,其內(nèi)容由分支維護者負責(zé)。
分享人:李建業(yè),前阿里巴巴員工(花名:李福),2002年本科畢業(yè),之后一直從事軟件開發(fā),涉及辦公自動化、電信網(wǎng)管/增值業(yè)務(wù)系統(tǒng)以及互聯(lián)網(wǎng);2009年12月加入淘寶的廣告應(yīng)用開發(fā)團隊;從2011年底開始,關(guān)注軟件研發(fā)本身,主要工作包括運維自動化系統(tǒng)和持續(xù)集成服務(wù)平臺。
核心關(guān)注:拓步ERP系統(tǒng)平臺是覆蓋了眾多的業(yè)務(wù)領(lǐng)域、行業(yè)應(yīng)用,蘊涵了豐富的ERP管理思想,集成了ERP軟件業(yè)務(wù)管理理念,功能涉及供應(yīng)鏈、成本、制造、CRM、HR等眾多業(yè)務(wù)領(lǐng)域的管理,全面涵蓋了企業(yè)關(guān)注ERP管理系統(tǒng)的核心領(lǐng)域,是眾多中小企業(yè)信息化建設(shè)首選的ERP管理軟件信賴品牌。
轉(zhuǎn)載請注明出處:拓步ERP資訊網(wǎng)http://m.vmgcyvh.cn/
本文標題:前阿里員工技術(shù)分享:持續(xù)集成和“云”
本文網(wǎng)址:http://m.vmgcyvh.cn/html/news/10515318339.html