Jenkins+Docker搭建持續整合測試環境
https://sanwen8.cn/p/22e2dDy.html
關於Jenkins
Jenkins是被廣泛應用的持續整合、自動化測試、持續部署的框架,甚至有些專案組順便將其用來做流程管理的工具。根據任務的多寡,Jenkins通常有兩種典型的部署方式。
-
單節點(Master)部署
這種部署適用於大多數專案,其構建任務較輕,數量較少,單個節點就足以滿足日常開發所需。 -
多節點(Master-Slave)部署
通常規模較大,程式碼提交頻繁(意味著構建頻繁),自動化測試壓力較大的專案都會採取這種部署結構。在這種部署結構下,Master通常只充當管理者的角色,負責任務的排程,slave節點的管理,任務狀態的收集等工作,而具體的構建任務則會分配給slave節點。一個Master節點理論上可以管理的slave節點數是沒有上限的,但通常隨著數量的增加,其效能以及穩定性就會有不同程度的下降,具體的影響則因Master硬體效能的高低而不同。
Docker是一款針對程式開發人員和系統管理員來開發、部署、執行應用的一款虛擬化平臺。Docker 可以讓你像使用集裝箱一樣快速的組合成應用,並且可以像運輸標準集裝箱一樣,儘可能的遮蔽程式碼層面的差異。Docker 會盡可能的縮短從程式碼測試到產品部署的時間。簡單來說Docker提供了一種技術,可以讓開發人員方便地將應用程式碼已經執行時的環境一併打包到一個映象中,然後將這個映象上傳至映象倉庫。在測試或者產品環境只需要下載這個映象然後將其啟動就完成了部署(就好比開啟一個集裝箱那麼簡單)。關於Docker更詳細的內容請參考官網文件。
當前Jenkins遇到的困難隨著敏捷開發的普及,自動化測試成為每個專案的必須。一個經過多年開發的專案,其累積的自動化測試數量是驚人的。為了保證每次的部署都是正確的,就需要每次迴歸所有的自動化測試用例。根據專案的不同,有些需要每週跑一輪迴歸測試,而有些專案則需要每天一輪。所以我們會把所有的測試用例進行分組,同時在多臺測試機上執行,以減少一輪測試所需要的時間。而這就要求我們有足夠多的硬體資源來滿足這需求。下圖展示了一個典型的通過Jenkins來管理自動化測試的拓補結構。一臺Master主機管理多臺測試機,Master將測試任務分配給測試機。
當前Jenkins(Master-Slave)結構
這種結構存在一些缺陷:
-
自動化的測試通常都是通過捕捉螢幕控制元件來模擬使用者的行為以達到測試的目的,這就意味著一臺測試機上只能同時執行一組測試用例,否則用例之間就會相互干擾。這就存在資源浪費,因為測試機的配置往往可以支援多組測試用例。
-
維護人員得確保測試機都保持線上,當測試機器數量較多的時候,比如100臺甚至1000臺的時候,這維護的壓力就比較大。
-
通常回歸測試是在晚上執行(如此就能在開發組第二天上班時發現前一天提交的程式碼是否正確),但這上百臺測試機不論白天晚上都在工作狀態,這是另一維度的浪費。
-
很重要的一點,測試機器會因為各種原因導致測試環境被汙染,導致測試不能順利進行,而此時除了維護人員手工處理外,沒有特別好的方案。
-
之前我們提到過,當slave數量達到一定程度的時候,作為Master的節點就會出現效能變差,穩定性下降。
-
每個Slave節點在開始跑測試之前都需要從**庫下載最新的分發包,解壓,設定執行環境。這個過程通常也佔用不少時間,想象一下,突然間上百個slave開始下載最新的庫,這對**庫是一個極大的衝擊。
很自然的一個想法就是將測試機全部替換成Docker容器(Container),而管理這些容器的工作交給更專業的工具,如Google的Kubernetes或者Docker官方提供的Swarm。所有構建的環境都打包進Docker的映象檔案中,自動化測試是一個映象,編譯單元測試是一個映象等等。改進後的拓撲結構如下圖所示:
在這個方案中唯一的技術問題是自動化測試需要桌面系統,而通常Docker容器中執行的都是無圖形介面的應用。解決的方法也非常直接,我們在容器中提供桌面系統(VNC服務)。根據不同的Linux發行版本,我們可以選擇TightVNC或者TigerVNC。不論選擇哪種VNC服務,他們都提供一個虛擬桌面,可以通過VNC的客戶端遠端連線到該桌面進行操作。
對應前文提到的6個不足,在這種結構下悉數得到了解決。
-
每個測試機可以同時執行多組自動化測試用例,也就是說跑原來相同數量的迴歸測試,這種方案下可以至少節省一半的測試機。
-
通過Kubernetes或者Swarm,我們可以實現對容器的自動化管理,從而減輕維護人員的工作。
-
Docker容器可以根據需要動態增減,又因為構建所需的一切環境都被封裝在Docker的映象中,這些測試機器可以被方便的用於其他任務的構建,而不需要進行額外的配置。只需要下載其他構建任務的映象,然後將其啟動。
-
每次測試啟動一個全新的容器,所以環境是完全乾淨的。當某個容器出現問題的時候,這個容器就會被銷燬,同時新起一個容器完成相同的測試工作。
-
在這種結構下Jenkins只需要管理一個slave節點,而Kubernetes和Swarm則可以管理成千上萬個容器。
-
在同一個Docker環境中(同一臺測試機)只需要下載一次最新的自動化測試的映象就能起多個容器,而在這種結構下,測試機數量已經**減少,從而對**庫(私有映象倉庫)的衝擊也明顯減輕了。
一個專案開發了5年,就累積了上萬迴歸測試,需要幾十臺測試機不間斷的執行8、9個小時才能完成;設想下,這個專案還要繼續執行5年甚至10年呢?我們的測試機的數量將會是多少,我們的測試反饋週期還是8、9個小時麼?根據我們的觀察,經過多年的維護,很多功能模組已經是非常完善,基本很少有程式碼的修改。那麼這些功能對應的測試用例是否有必要每次都跑呢?答案我想是否定的,但問題是怎麼來判斷當前程式碼的修改是否會影響到這些功能模組呢?按照現在的設計,我想沒有人敢百分百的肯定。我們是否有必要對現有程式碼做些調整,依照微服務的思想,把我們的分發包拆分下,每次只需要釋出有更新的模組。如此一來我們遞迴的自動化測試用例也只需要包含有改動的那些模組。那時候,很可能我們可以在每次程式碼提交就執行一次迴歸測試。