當前位置:
首頁 > 最新 > 阿里測試環境運維及研發效率提升之道

阿里測試環境運維及研發效率提升之道

本文整理自 GOPS2017·上海站演講《阿里測試環境運維及研發效率提升之道》


講師簡介


劉湘疆(青冥),阿里巴巴運維中台技術專家,2010年加入阿里巴巴,先後從事配置管理、工程效能等相關工作,目前負責阿里巴巴集團測試環境運維及研發效率提升。對於測試環境效率、自動化部署、持續交付有較深刻的認識和實踐經驗。

我是劉湘疆,來自阿里巴巴研發效能事業部,前幾年一直負責集團測試環境的管理和運維。本文跟大家分享一下阿里巴巴在測試環境方面運維和研發效率提升的一些經驗和實踐。

大家平時可能關注生產環境的比較多,各種分享活動絕大多數也是基於生產環境的,本文我要講的是測試環境。生產環境最關注的就是穩定,測試環境來說更關注的是研發效率,如何從一行代碼最快的保證質量發到線上去,這個是我們測試環境最關注的。

測試環境特點如下:

資源配置低:測試環境一般來說資源配置都比較低,跟線上不太一樣,至少在阿里是這樣的。大到網路、機房包括伺服器配置都比線上的配置要差,小到虛擬機、容器,虛擬比都比線上的要高。這是不太一樣的地方,這些對於我們來說也是一些挑戰,後面會講到。

部署頻繁:測試環境下的部署是非常非常頻繁的。比如說你開發一個功能,可能線下部署10到20次,線上才發布1次。部署這塊對於研發來說是非常關注的,就是怎樣能快速看到我部署之後的效果。

業務測試干擾:這塊也是很明顯,因為當你業務需求越來越多的時候,並行的開發就會很多,而且線下環境類型比較多,比如開發環境、性能環境,各式各樣的環境,這些環境之間會有一些干擾。

以下兩種情況比較常見,第一種是我要調用你的服務,結果你的伺服器掛了。第二種是可能多個環境都在提供某個服務,當你要請求這個服務的時候,就可能會調錯了。這些情況都會干擾到我們的測試。

今天的分享主要從資源穩定性部署效率,以及業務穩定性這三個方面來講。


一、資源穩定性


剛才我們提到,測試環境的配置都比較差,絕大多數的機器都是線上淘汰的過保的物理機充當的,雖然過保了實際上還是能用的,為了節省成本基本上都是當測試機來用。這些機器的故障率肯定比線上的要高很多的,那我們要怎麼來保證穩定性呢?就是在容器交付和容器運行兩個階段怎麼盡量保證能夠穩定。

容器交付我們主要是做了資源池的調度策略。右側這邊圖是一個簡化版的容器生產的鏈路,資源池上面是一層調度,分為資源管理和資源生產,當然,這裡還有很多其他的模塊,我這裡就不細化了,重點是突出中間那塊。

最上面有很多的上層系統來調用申請機器,我們線上環境沒有資源池動態分配這層的,就是直接上層系統和一層調度做這些事情,因為下層本身是比較穩定的。

對於測試環境來說,我們在中間插了一層,就是資源池的動態分配,這個系統有五個模塊,分別是宿主機評分,應用環境分級,資源池管理,(就是對資源池怎麼進行合理的調度和分配,這個後面會詳細講到),容量預測,最後一個是分配器。

下面詳細說下資源池動態分配系統的模塊。

第一塊是宿主機評分,我們會對宿主機的機型機房各種維度進行一個綜合的考量,對它進行一個打分。比如說機型,最典型的就是磁碟,磁碟類型到底是機械硬碟還是SSD的硬碟,這個可能對IO性能影響會比較大一點。

還有機房,比如說某些機房的網路或者帶寬相對配置低一些的,這個分數可能會低一點,還有比如這個機房在計劃裁撤,那麼分數也會低一點。另外還有過保時間,歷史故障次數,可調度狀態等。

第二塊是應用環境的分級,我們會對應用進行一個重要等級的劃分。另外就是對於環境的類型進行分配,在測試環境下,環境類型很多。我們有開發環境,穩定環境,持續集成環境,性能環境等。

比如說像穩定環境,因為是要持續提供服務的,給它分配的資源就要盡量足夠穩定。比如說像開發環境、持續集成環境都是屬於即用即申請,用完之後立刻就釋放了,使用周期很短的,針對這種類型可能會有不同的策略。還有像性能環境,對帶寬或者網路的要求,就要盡量的接近線上。

第三塊是容量預測,會根據歷史數據來預測當天所有應用的所有環境類型大概會申請多少機器,這個基本上來說是比較穩定的數據,會進行一個容器的需求量預測。

第四塊是資源池管理,就是動態調整資源池。大家可以看一下右下角這張圖,最下面就是資源池物理機打分後的排序,機器分越高越可靠,分數越低越不可靠。

上面三個框是我們對它進行一個邏輯的劃分,每一個小的劃分段其實就是為某一類環境做準備的,比如說當核心應用來申請穩定環境的時候,會把它分到最可靠的機器上來。

如果是開發環境,或者說是不太重要的應用環境,就會分到不可靠的機器上去,因為它們對於不穩定的容忍度相對來說更高。

再比如持續集成環境或者開發環境,他們是用完就釋放的,使用時間很短,這種環境我們的分配策略是怎麼樣的?其實除了分配策略以外,還有一個打標的作用,當這種環境來的時候,會盡量分到比如剛才說到的某個即將要裁撤的機房去,這樣的話,等到裁撤的時候,上面的機器可以直接釋放掉,而無需在裁撤的時候做大量的遷移操作。

中間的這個劃分就是根據容量預測來的,每天去預測某一種類型應用的某種環境大概佔多少,會動態的對這根線進行動態的調整,每天會不太一樣,保證這個環境的申請盡量落在相應的區間。

這樣就可以做到讓這些長期佔用的環境或者比較重要的應用環境能夠盡量落在比較穩定的宿主機上,讓它的容器穩定性盡量高。

即使我們做到了上面的資源交付,宿主機還是會有問題的,這個是難以避免的。大多數的做法是自愈,當我發現有問題的時候,怎麼樣做到自愈,讓用戶沒有感知。我們沒有辦法避免某個機器不出問題,但是我們可以盡量避免用戶感知到。

我們這裡有一個自愈系統,看右邊這張圖,有四個重要的模型:下面結合場景進行說明。

第一個是條件模型,定義觸發條件。

第二個是原子服務模型,定義一個一個的原子服務。每一個原子服務應該只做一件事情,這裡只是一個規則的定義。以磁碟滿為例,磁碟滿的原子服務要對應調用某一個清理磁碟的介面API。

第三個是條件處理模型,把上面兩個連起來。當滿足某個條件的時候,要去做什麼樣的處理,可能需要把一個或者多個原子服務連起來,比如剛才說的磁碟滿調用清理磁碟的API,這是最簡單的情況。複雜一點的情況可能就要用到自愈事件模型了。

第四個是自愈事件,這個相對更高一層次,是對於條件處理的一個組合,因為在很多情況下,可能上層系統給到的信息並不是那麼的精準,會有些模糊。比如發布失敗,這個事件對於自愈系統來說,可以定義多個條件,依次匹配,就像排查一樣,先檢查磁碟是不是滿了,agent是不是正常的,容器是不是ok的等等。

上層系統可以對接很多了,比如剛剛說到的發布系統,還有監控系統,發現磁碟滿了清理磁碟,發現應用問題自動把服務拉起來,還有調度系統,剛才提到的底層負責資源管理的調度系統,當它發現某台物理機已經出問題的時候,可以把上面現有的容器遷移走,把這個物理機下線或送修,這些都是可以對接多個上層系統的。總的來說,非業務系統問題相對還是比較好處理的。

而對於業務性的問題處理相對麻煩點,因為業務具有多樣性。比如健康檢查,發現有問題就需要對應用進行重啟,甚至做容器遷移。這個我們嘗試在做,從經驗上來看,對應用上來說是有一些要求的:

應用需要有比較準確的健康檢查,這樣監控才能知道應用到底是不是OK的,自愈是不是真的完成了,業務是不是真的恢復了。

優雅上下線比較關鍵,就是先從負載均衡設備上摘下來,然後再下線服務,這樣才能保證客戶端的請求都處理完了,並且不會有新的請求在下線的過程中再進來,導致下游失敗。

第三點就是無狀態,這個也很好理解,我就不多說了。

最後就是快速啟停,之前我們有些應用的啟動時間非常長,導致自愈不太可控,甚至都超時了,讓整個自愈的成功率和時間上不太可控,所以後來就要求應用要能做到快速啟停,至少在三分鐘之內要完成。

以上都是經驗,大家可以參考一下。


二、部署效率


對於研發同學來說,大家最關注的就是研發效率,寫完代碼之後,希望能立刻看到效果,並且迅速得到驗證。這裡面我們認為比較耗時的三個部分就是構建、部署和測試,今天主要是對部署和測試這塊會重點講一下。

其實構建這塊我們也做了很多事情,在阿里每天的構建量非常大,我們有一個專門的構建集群,這裡大概講一下一些提效策略。

Maven的類庫緩存,這個緩存其實要考慮到不同的應用在同時構建時,覆蓋和衝突的問題,這個我們是採用overlayfs這個方式去做的。

第二塊是Docker基礎鏡像預熱。

第三第四個是盡量利用構建的cache和重複利用工作區。這裡提一下cache,因為在Docker構建的時候很明顯,cache利用越多,Docker構建就越快,但是這個cache跟存儲空間需要平衡,怎麼樣能夠保證盡量多緩存的情況下,佔用空間盡量少,有一個辦法就是盡量把它調度到它上一次構建的那台編譯機上。

接下來重點講講部署這塊,我們認為主要就是能做到快速部署、快速回滾,後面會詳細講。

對於測試來說,一個是自動化測試,這樣的話你才能在整個pipeline里跑的起來;還有一個是業務的穩定性,測試環境的業務穩定性相信是困擾很多開發測試同學的大問題。

其實自動化測試跟業務穩定性這兩個東西是相輔相成的,環境越穩定,自動化才能越跑越成熟。反過來說,自動化越成熟,能夠為環境的穩定性提供越大的自動化監測保障。

部署效率我們主要是從部署策略介入的。業界用的比較多的策略一般是分批部署,這也是最常見的一種方式。比如說現在有兩台機器,如右邊這張圖,黃色三角表示流量,這兩個都有流量進入。開始部署的時候先部署第一台,這時只有第二台在提供服務,等第一台部署好了之後,流量全部打到第一台來了,第二台再部署,最終達到兩台都部署完成,流量均衡,這就是分批部署。

在整個部署過程中,總有一台機器提供服務,保證服務不間斷。從部署時間和回滾時間上來看,分幾批部署,部署總時長就是單台的時間乘以批次。

從整個部署時間上來看,單台部署時間越長,那麼部署時間就會拉的很長,所以會盡量減少批次,又要考慮到剩餘的機器能不能撐得住線上的流量。

比如說回滾的時候就是這樣,部署到倒數第二批的時候發現有問題,換個時候不能把所有部署過的批次一下子回滾掉,因為線上剩餘的那一批可能撐不住所有的流量,這個時候你分幾批發,就得分幾批回滾。

所以回滾總時長這裡最好的情況就是在第一批就發現了問題,回滾的時間就等於單台部署的時間。這是線上普遍採用的做法,我們原來在測試環境也是這麼做的。

後來我們在想,測試環境有沒有辦法優化一下,我們考慮用藍綠部署。這裡簡單講一下,還是兩台機器,只有一台在提供服務,我們稱之為主機,另外一台沒有提供服務,我們稱之為備機,上面是什麼版本我也不關心。

部署開始的時候,先部署備機,部署完之後把流量切到備機來,這時備機這時就變成新的主機了,原來的主機變成備機了。需要回滾的時候,直接把流量切過來就好了。

這種做法部署時間是最短的,只需要單台的時間就夠了,因為另外一台不需要部署。回滾時間其實取決於你切流的時間,我們可以做到在幾秒鐘之內就切好。

藍綠部署是用空間來換取時間,我們用新的一批機器來來部署,部署完了之後替換之前的那批機器。

對阿里來說,在線上這樣做的話,是不太可取的,因為線上的量實在是太大了,一個應用就上千台伺服器,要採用藍綠部署的話,需要再拿出一千台伺服器來先部署然後再下掉,而且我們的應用發布是頻率很高的,這對於資源的消耗是非常大,不太可能採取這種方式。

但是對線下來說我們測試環境兩台機器就夠了,當初在分批部署的時候,採用兩台機器,並不是說我們線下流量有多大,必須要兩台才能撐得住。

測試環境流量其實很小,一台伺服器就夠了,之所以用兩台是為了保證穩定性。在部署的時候,原來採用分批發布的時候,至少還有一台總是在提供服務的。

我們採用這種方式主要是為了降低部署時間,我們現在正在嘗試用這種方式來做。

除了在上節說到的構建策略外,還進行了以下優化。

Dockerfile最佳實踐

排除不需要的文件

減少鏡像層數,合併多個指令,體積就會小很多

還有盡量使用cache,我們統計過數據,大部分變的內容都是應用的代碼,對環境的修改很少很少,所以我們會把應用包放在最後。

這些主要是為了構建和拉鏡像比較快

鏡像分發

基礎鏡像預熱,當有資源進入到資源池的時候,我們就開始對公共的基礎鏡像做一些預熱,提前拉到物理機上。這個又與前面講到的資源動態調配有關係,在測試環境有動態調配系統,我已經知道哪些機器上會放哪些應用,所以可以提前把那些應用的基礎鏡像拉到相應的宿主機上,這樣的話在部署的時候會很快。因為只需要去拉取應用包那一層就可以了。

部署中的鏡像預熱,這個在分批部署的時候用處比較大,在第一批部署的時候就開始對第二批第三批進行預熱和拉鏡像了。

大規模文件分發方案,我們發現不管怎麼優化,我們的應用鏡像仍然能夠達到2到3G,即使除去其他公共的東西,光應用包的鏡像也要兩三百兆。對於大規模的文件分發有一個成熟的方案叫蜻蜓,這個是我們開發的系統,已經開源了,有興趣的話大家可以去了解下。現在我們集團里90%以上都是採用蜻蜓來做文件分發的,效果還是比較明顯的。蜻蜓對於遠距離傳輸、大文件傳輸、安全傳輸等都有針對性的解決方案,對比傳統的直接下載方式,尤其是大規模的文件分發,效率能提升至少10倍以上。


三、業務穩定性

第一,業務方希望我們的環境要足夠穩定,所調用的服務要一直正常運行,隨時調用都可以,而且是穩定的,最新的,無干擾的。

第二,調用的時候不希望調到干擾伺服器上去,包括消息也是一樣的,不希望應該發給我的消息,被別人搶掉了。

第三,高效,比如說建立一個隔離環境的時候,不希望做一大堆的配置來實現。

那麼怎麼樣做到這幾點呢:這裡我講兩點,一個是基礎環境,其次是邏輯隔離。

現在比較典型的研發流程是這樣的,從開發測試到集成測試,到預發測試,再到上線。在每個研發階段都有對應的環境做支撐。這裡需要注意下開發環境,開發環境之間互相調用的話,肯定會有干擾,並且不穩定。

所以發布上線完之後我們會去部署一個基礎環境,開發環境去調用穩定環境的服務。基礎環境部署的是主幹代碼,也就是線上的代碼,會自動部署。

這裡面的隔離是怎麼做到的呢?比如,怎麼讓開發環境調到基礎不調到開發呢?甚至還有很多其他的開發環境,為什麼可以做到不調用呢?

重點是邏輯隔離。現在阿里的業務非常多,並行需求特別多,一個應用有可能甚至同時會有幾十個開發環境存在,當調用服務的時候,很有可能會出現調用錯亂。我們是通過隔離組來解決這個問題,原理是根據源頭的IP所在隔離組進行路由。

看上面的圖所示,隔離組裡面有三個應用,基礎環境里有所有的應用,當我發現隔離組裡面沒有這個應用服務的時候,就會調基礎環境,基礎環境調完之後還能調回到你的隔離組環境里去。

不管怎樣每一次都會先檢查隔離組裡有沒有我要調用的服務。在搭建隔離環境做測試的時候,只需要搭建你要修改的那幾個應用就可以了,最大限度的去復用基礎環境下的服務。

上面是沒有邏輯隔離的情況,上面每個圈代表一個環境,ABCDE代表不同的應用,當A1在調用的時候只要發現有B的服務都會調用到,隨機調用的,可能這次是B1下次是B2,亂糟糟的。

這張圖裡創建了兩個隔離組。在隔離組1里,沒有B的環境,所以A1會去調用B的基礎環境;再看隔離組2,這個隔離組裡面有B的環境,所以A2就調B2,沒有C了再往基礎環境調。這個就是跟沒做隔離的區別,上一個圖每個圈上面至少兩三個線,而這個只會調一個。

當然這裡面還有一個問題,比如說在隔離組2里,B1的服務掛掉了,這時A2是不應該調用基礎環境B的,否則會掩蓋B1掛掉的事實,這個時候隔離邏輯還是會嘗試去調用B1,並報錯說調用不到。

這個是最終效果圖。大家都在隔離組裡,沒有散的機器。與上一張圖的另一個區別是這條紅線,這是一個比較特殊的隔離邏輯的高級用法。

比如A是一個前端應用,B是後端的服務,A調用B的服務,如果我是一個B的開發,通過前端頁面方式測試B服務的時候,一般需要再搭一個A的測試環境,這種情況好處理,只要搭一個即可。

如果是多個呢?比如像物流發貨這種情況,你需要先要購買,然後付款,整個走完之後才能發貨,可能需要把整個交易鏈路都搭一遍,這時你會發現這個鏈路很長,要搭建的環境很多,對機器資源也是一種浪費,根本沒有必要。

有沒有更高效的方式呢?這裡面實現了一個邏輯,就是通過用戶的請求來精準路由。

比如你是從某個隔離組發起測試,只有你訪問的時候會走那條路,而其它人還是走這條路,這個與藍綠部署裡面的備機有點像,備機在下線之後,只是被隔離了,機器並不會被釋放掉,一方面這個機器可以用來給開發做debug用,另一方面有問題回滾比較快。

怎樣保證還在提供這個服務,但是這個服務又不被別人調用到呢?我們把這個服務單獨放在一個隔離組裡,就不會被任何人調用到,只是被隔離起來了而已,實際上服務都還在。要切換的時候,只要重新拉回來就行,秒級生效。

講一下實現的原理,阿里有一個中間件叫做鷹眼,可以查看調用鏈路。下每個請求會生成一個ID,這個ID會隨著每一次調用一個一個傳下去,所以當你把這個ID都統計出來,就能知道這條鏈路是什麼樣子的。

我們也是利用了這個東西,把源頭的請求IP放在ID裡面,每次路由的時候都會看ID有沒有跟某個隔離組進行關聯。我們有一個web操作界面,想與哪個隔離組關聯,界面上點一下就好。

當你服務調用的時候,服務路由會把ID取出來,看看你的IP有沒有做關聯,如果有的話就到那個隔離組裡面去調用。

它的好處就是快速的搭建一整套隔離環境,只要在上面點幾下,要哪幾個應用一下子就好了,自然而然就呈現一個封閉的隔離組。

這個東西因為是涉及到阿里的中間件產品,所以大家可能不能直接拿去用,但是這裡提供一個思路,這套東西目前來看已經能夠滿足很多場景了。

如果在沒有使用鷹眼產品的情況下可以採用這種方式,回過頭來看看上一張圖。有一個簡單點的方法就是直接看標,每台機器打了標之後,這個是隔離組標,這個是基礎環境標,比如第一個圈,發現自己的標是隔離組的,調服務的時候,發現這個組裡面沒有需要的服務,就調基礎的了,基礎再往下看的時候,就看他自己的標。

這會存在一個問題,就是一旦調出來就調不回去了,所以要保證所有你要測的東西都在這個裡面。遇到問題排查也比較簡單。

以上就是在業務穩定性這塊做的一個邏輯隔離。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 DevOps時代 的精彩文章:

TAG:DevOps時代 |