天天看點

分享實錄 | 雲原生下的開發測試

分享實錄 | 雲原生下的開發測試

【以下為分享實錄,有删節】

測試環境管理之困與阿裡巴巴的解決之道

在雲原生時代下,軟體的疊代速度越來越快,對測試的要求也越來越高,很多開發者開始使用Kubernetes來管理測試環境。在這個過程中,開發者會遇到很多困難,其中最主要的兩個問題是:一、本地環境與Kubernetes叢集網絡不通問題;二、共用測試環境時,互相幹擾的問題。

在阿裡巴巴内部,我們主要通過扁平的内網IP和項目環境兩個機制來解決以上痛點。扁平的内網IP主要是基于CNI(Conteinre Network Interface) 機制改造Kubernetes的IP邏輯實作的,可以使叢集中的每個Pod配置設定到的IP與本地機器配置設定到的IP處于一個大的網絡環境下,這樣就可以解決本地環境和叢集之間互通的問題。項目環境是基于RPC、消息中間件的虛拟環境,從表面上看,每個項目環境都是一套獨立完整的測試環境,由一系列服務組成叢集,而實際上,除了個别目前使用者想要測試的服務,其餘服務都是通過路由系統和消息中間件虛拟出來的,指向公共基礎環境的相應服務。這樣操作的好處是,第一不會占用大量的開發資源;第二,不會影響公共基礎環境的穩定性。

分享實錄 | 雲原生下的開發測試

阿裡巴巴的這種測試環境帶來的測試體驗非常爽,本地與叢集雙向互通,每個子項目都可以獨占一個“項目環境”,彼此不會幹擾。但是這種測試環境管理方式實施起來比較複雜,隻适合大型的集團公司,我們希望将這種測試體驗以 “更輕”的方式實作,普惠更多開發者。于是雲效團隊推出了雲原生測試環境工具箱,主要包括kt-connect和kt-virtual-environment這兩個開源工具。

通過kt-connect解決本地與叢集雙向互通問題

首先,我們來聊一聊如何使用Kubernetes測試環境開源工具箱中的kt-connect解決 “本地與叢集雙向互通”的問題。

我們假設有一位主人公叫“程式員小黑”,他所在公司采用了微服務相關的技術實踐。小黑在做本地開發的過程中,會遇到兩種聯調場景,即我需要聯調其它服務和其它服務調用我。

我們先來看第一個場景:聯調其它服務。前面講到本地環境和K8S叢集中的網絡是互相隔離的,那麼在本地完成代碼開發後,如何高效的與其它服務進行聯調呢?最“簡單粗暴”的一種方式,就是在本地完整的部署一套測試環境,這種方式的優點很明顯,效率最高,而且沒有外部依賴。缺點也同樣明顯,一是對開發人員的素質要求非常高,二是要占用大量本地的開發資源,對本地開發機的性能要求很高。第二種方式是利用Kubernetes等工具在本地部署一套K8S叢集,這種方式可以在一定程度上降低開發人員“上手成本”,但是也同樣存在占用大量本地開發資源的問題。還有一種處理方式是利用VPN調用K8S叢集中的服務,這種方式存在兩個問題,一個是本地的服務調用是脫離了Istio的流量控制的,第二個問題VPN這種方式隻解決了本地到叢集的通訊,對于回調這種方式是解決不了的。

分享實錄 | 雲原生下的開發測試

那麼,有沒有更簡單的方式呢?答案是肯定的,通過KT-Connect工具可以讓開發者一鍵建立本地到Kubernetes叢集的網絡連接配接。開發者隻需要運作一個“connect”指令,就可以自動在叢集中建立一個代理容器,并且通過這個代理容器建立本地與叢集的VPN連接配接,同時KT-Connect也會内置DNS服務,本地服務可以直接通過服務的名稱進行服務調用,就好像本地的程式運作在K8S叢集中一樣。 在KT-Connect中,我們給這個代理容器取了一個名字“shadow pod”,即“影子”。它就像是本地服務在叢集中的影子,通過它來完成本地服務與叢集中服務的互相調用。

接下來,我們來看第二個場景:其它服務調用我。在聯調時,小黑不僅需要調用其它人的服務,同時作為服務的生産者又會被其它服務調用。這時隻打通本地到叢集的服務是不能滿足聯調測試需求的,必須同時讓叢集中的服務也可以通路本地的服務。

分享實錄 | 雲原生下的開發測試

這就需要使用KT-Connect 的第二個指令——“Exchange”。Exchange(交換)指令會在叢集内部署一個代理容器,并替換叢集中指定服務的目标容器,進而将發往該服務的所有流量攔截并轉發到本地端口。這是一種“完全替換”,這就意味着在同一時間點,隻有一位開發者可以将他本地的服務加入到叢集中。為了解決這個問題,KT-Connect提供了第三個指令——Mesh(混合)。當我們在本地營運“Mesh”指令後,我們同樣會把本地服務加入到叢集裡面,但是會保持原有的目标服務狀态不變,并且本地服務會繼承目标服務中所有的标簽。依照K8S本身服務發現的原理,請求流量會被随機地轉發到原有服務或本地的服務。同時配合Istio的流量規則,就可以讓所有正常流量依然保持對原應用的通路,而隻對一些有特殊标記的的請求轉發到本地。進而可以實作在一套公用測試環境的基礎上各自獨立的完成本地的內建聯調。

KT-Connect背後的原理

我們通過KT-Connect的“connect”“Exchange” “Mesh”指令實作了本地到叢集的雙向網絡互通,看起來似乎很神奇,其實背後并沒有什麼黑科技。我們隻是綜合利用了Kubernetes原有的特性及SSH這個我們經常會用到的網絡協定,通過Kubectl的端口轉發可以實作将叢集中服務的端口映射到本地,通過SSH協定建立本地與叢集之間的隧道。

分享實錄 | 雲原生下的開發測試

以“Connect”指令為例,了解一下KT-Connect背後的原理。如上圖所示,當開發者在本地運作“Connect”指令後,首先會建立一個代理容器(shadow pod),這個代理容器會運作“SSH Server”和“DNS Server”。當代理容器啟動成功之後,就可以通過“port-forward”将代理容器的22端口轉映射到本地,如2222端口。此時,本地服務就可以通過本地的2222端口建立與叢集内部的連接配接。

分享實錄 | 雲原生下的開發測試

“Exchange”和與“Connect”指令背後的原理類似,我們也會先建立一個代理容器,并通過“port-forward”将代理容器的端口映射到本地。然後根據Exchange的目标服務,判斷将代理容器的哪一個端口的請求全部轉發到本地的特定端口。

“Mesh”與“Exchange”的最大的差異在于“Exchange”會将原應用的副本數直接降到0,會将叢集内所有對原應用的流量全部轉發到本地。而 “Mesh”則是在保持原有應用Pod不變的前提下,建立一個新的代理容器并且繼承原應用的所有标簽,還會增加一個随機的version标簽。這時我們就可以通過Istio規則, 精确控制流量。

分享實錄 | 雲原生下的開發測試

如前文所述,通過KT-Connect我們可以實作從本地到叢集的雙向互通。我們可以看到這樣一個有趣的場景:小黑A可以通過“Mesh”指令把本地服務加入到測試環境裡,并且可以讓叢集中一部分特定的流量轉發到本地,這樣他可以與叢集中的其它服務進行聯調。小黑B通過“Connect”指令連接配接到叢集,直接在本地進行測試。在某些情況下,小黑B需要依賴的服務剛好是小黑A正在開發的版本,小黑B隻要按照Istio的流量規則設定可以調用小黑A服務的值,就可以跟小黑A的服務進行聯調。對于小黑C,他既需要調用叢集中的服務,又需要叢集中的服務回調到本地,是以他在本地既營運了 “Connect”又運作了“Mesh”。

上文描述的其實是一種理想情況,需要建立在我們的測試環境是一種穩定狀态的基礎之上。但在現實情況下,由于頻繁的代碼變更測試環境往往處于一種不太穩定的狀态。接下來我們會介紹如何使用雲原生測試環境工具箱中的kt-virtual-environment打造穩定的測試環境,讓開發者可以更好地進行協同研發工作。

共用測試環境互相幹擾問題及常見解決方案

在一個中大規模研發團隊負責的項目中,往往一個系統裡包含許多(微)服務,而且服務之間存在鍊式依賴,難以獨立啟動運作。這時就很容易出現“共用測試環境互相幹擾”的問題,比如一個開發者重新部署、重新開機測試環境時,可能會打斷所有正在測試的開發者;一個開發者送出了有BUG的代碼,所有開發者都可能受影響;一個開發者為了排查問題,單步調試測試環境服務時,所有開發者測試請求會被攔截。

如何來解決這個問題呢?以往的思路是準備多套測試環境。雖然這種方式可以暫時緩解開發過程中的互相影響,但是這會帶來額外的資源配置設定和管理問題,特别是當沒有那麼多并行開發時會産生非常嚴重的資源浪費。

于是出現了一種“改進”方法,企業通過用helm或自制工具自動化地快速建立一套環境,用完即删。該方法在一定程度上解決閑置資源回收的問題,但是也沒有那麼“完美”。在實際操作過程中,環境的建立其實并沒有那麼“快速”,往往需要等待幾分鐘甚至幾十分鐘的時間。而且如果為每個子項目的成員分别拉一套環境,資源浪費依然嚴重。

在多人協同場景下,如何做到測試環境不互相幹擾又不産生極大的資源浪費呢?在阿裡巴巴内部主要通過“項目環境”的方案解決。

“項目環境”的本質是基于路由隔離實作的一個“虛拟環境”。我們通過一個執行個體來簡單了解一下。

分享實錄 | 雲原生下的開發測試

如上圖中藍色部分所示,由服務A、服務B、服務C、服務D組成一個完整的測試環境,我們稱為“公共基礎環境”(也稱預設環境)。當某位開發者需要進行項目開發的時候,他不需要把應用或服務部署到公共基礎環境中,而是單拉出來一部分資源(服務C和服務D)并複用部分公共基礎環境資源(服務A和服務B)形成 “項目環境”。這樣操作的好處是,第一不會占用大量的開發資源;第二,不會影響公共基礎環境的穩定性。

我們主要通過打“環境标”的形式形成獨立的“隔離域”,比如[dev]代表公共基礎服務執行個體的标簽值,[dev.proj]代表項目環境的服務執行個體。同一個環境标形成一個獨立的“隔離域”,這是基于路由規則實作的。如果服務請求是來自一個有環境标的服務執行個體,它的服務請求會優先尋找跟它具有相同環境标的執行個體,如果沒有,會尋找它上一級的環境标,這叫做“路由兜底”。比如上圖中服務請求來自帶有[dev.proj]環境标的執行個體C,需要調用服務B,但是發現沒有帶環境标[dev.proj]的服務B,于是尋找帶有上一級環境标[dev]的服務B。

分享實錄 | 雲原生下的開發測試

我們還可以将本地開發機加入項目環境。比如開發者“小黑”在本地啟動了一個服務執行個體C,他給這個服務執行個體打的環境标是[dev.proj.local],通過前面介紹路由規則我們了解到帶環境标的服務發出的請求會優先尋找帶相同環境标的服務,如果找不到則會尋找帶有上一級環境标的服務,于是服務C[dev.proj.local]、服務D[dev.proj]和公共基礎環境中服務A[dev]、服務B[dev]就組成了一個新的的“項目環境”(圖中紅色部分)。

分享實錄 | 雲原生下的開發測試

這時“小黑”的同僚也加入了項目,他在本地啟動了一個服務A,如果他沒有對這個服務打“環境标”的話,他會預設使用“公共基礎環境”進行測試。這時小黑在他自己的“項目環境”中的任何調試都不會影響到小黑的同僚,反之亦然。

分享實錄 | 雲原生下的開發測試

後來小黑的同僚和小黑加入了同一個子項目,他們之間需要“聯調”。這時,小黑的同僚隻要給他本地的服務打上一個和小黑的“項目環境”相同的環境标即可,如上圖紅色部分。

總結一下前面介紹的概念:“隔離域”是由路由規則形成的虛拟邊界;每個“環境标”都會形成一個獨立的“隔離域”;“隔離域”之間可以存在部分或完全重合;“隔離域”的成員會随叢集中服務執行個體所帶“環境标”動态變化。

如何使用kt-virtual-environment 打造項目環境

kt-virtual-environment是一種基于Service Mesh的微服務環境複用工具,源于阿裡巴巴内部的項目環境實踐。通過Pod上的虛拟環境标簽,kt-virtual-environment能夠自動将測試環境網絡動态隔離成多個虛拟隔離域,同時以簡單規則在隔離域間局部複用Pod執行個體,進而達到隻需很少資源成本即可建立大量不同微服務版本組合的獨立測試環境的目的。

分享實錄 | 雲原生下的開發測試

下面我們來了解一下如何使用kt-virtual-environment打造項目環境。通過前面的介紹,我們知道相同的“環境标”會形成一個獨立的“隔離域”。是以首先我們需要為服務執行個體打上環境标,在kt-virtual-environment中是通過為為pod(或容器)添加約定的Label的方式實作的。在服務調用過程中,需要為應用程式添加一些邏輯,才能讓“環境标”順利在上下文之間傳遞,這個過程類似SkyWalking、Zipkin等鍊路追蹤工具的SDK端所做的事情,讓“環境标”通過HTTP頭在請求鍊路上一直保持傳遞。第三步,我們需要在叢集中配置Virtual Environment類型的資源執行個體,詳細配置的結構如上圖所示。

分享實錄 | 雲原生下的開發測試

kt-virtual-environment實作的基本原理是:觀察并持續監聽環境中的所有服務和開發資源,動态生成Service Mesh控制面規則,實作核心隔離邏輯 。目前kt-virtual-environment僅支援基于Istio的規則,未來會增加基于其它 控制面的Service Mesh規則的實作。

阿裡巴巴使用項目環境的最佳實踐

分享實錄 | 雲原生下的開發測試

“項目環境”在阿裡巴巴内部已近發展多年,下面我将一些優秀的實踐分享給大家。理論上,“環境标”的層級可以無限多,但是我們的經驗是最好不要超過三級。因為三層的“環境标”基本上可以滿足95%以上的研發場景。

以三層環境标實作的項目環境舉例。第一層一般隻有一個環境标,比如[dev],這是對應預設隔離域(公共環境)使用的環境标,這樣做會讓整個路由規則比較簡單,大家不用猜測“路由兜底”最後會“兜”到哪裡去。這個頂級的[dev]環境标對應的測試環境是不需要開發者自己去部署的,一般是通過“流水線”等自動化工具部署的穩定版本。對于某個子項目,我們可以基于頂級環境标建立一個二級環境标,如[dev.proj1],這樣會形成這個子項目的隔離域(項目環境)。在這個隔離域中,隻需要開發者自己部署需要改動的服務執行個體即可,其它不需要改動的服務執行個體可以複用公共環境中執行個體。有的時候,某位開發者可能要對某服務進行比較大的改動或者他不希望這個服務被其它同僚通路到,他可以基于“項目環境”再建立一個“個人環境”。在這個個人環境中,他既可以調用子項目中的服務,也可以調試本地開發的新的服務版本,并且不會影響到其他開發者。以上,是我們比較推薦的項目環境的用法。

總結:

雲原生測試環境工具箱共包含兩款獨立的工具:kt-connect和kt-virtual-environment。kt-connect是一款本地工具,主要是幫助開發者打通本地和叢集網絡,實作本地加入隔離域。kt-virtual-environment是一種基于Service Mesh的微服務環境複用工具,通過觀察并持續監聽環境中的所有服務和開發資源,動态生成Service Mesh控制面規則,實作核心隔離邏輯 。隻需要一次性部署,開發者不會頻繁使用到。目前兩款工具已經開源,大家可以進入Github社群進行下載下傳使用。

分享實錄 | 雲原生下的開發測試

以上内容整理自金戟和砧木的視訊分享《雲原生下的開發測試》,歡迎大家加入雲效開發者交流群(釘釘群号:34532418)觀看視訊回放,下載下傳演講PPT。

【關于雲效】

雲效,企業級一站式DevOps平台,源于阿裡巴巴先進的研發理念和工程實踐,緻力于成為數字企業的研發效能引擎!雲效提供從“需求 ->開發->測試->釋出->運維->營運”端到端的線上協同服務和研發工具,通過人工智能、雲原生技術的應用助力開發者提升研發效能,持續傳遞有效價值。

【雲效官網】

https://www.aliyun.com/product/yunxiao?channel=zhibo

【DevOps實驗室】挑戰實驗室任務免費領取1280元套餐

https://www.aliyun.com/product/yunxiao/devops

【公測指南】

https://developer.aliyun.com/article/756207

【申請公測】

https://devops.aliyun.com

【學習路徑】

https://help.aliyun.com/document_detail/153739.html

【開發者社群】

https://developer.aliyun.com/group/yunxiao

【精彩活動】雲效公測開啟 「産品體驗官」招募

https://www.aliyun.com/activity/yunxiao/Beta2020
分享實錄 | 雲原生下的開發測試

歡迎掃碼加入雲效開發者俱樂部(釘群:34532418)

繼續閱讀