一站式動(dòng)態(tài)多環(huán)境建設(shè)案例
01 問(wèn)題背景
致景科技成立于 2013 年 12 月,是領(lǐng)先的紡織產(chǎn)業(yè)互聯(lián)網(wǎng)企業(yè),國(guó)家高新技術(shù)企業(yè)。旗下?lián)碛小鞍俨肌薄ⅰ叭肌薄ⅰ疤旃ぁ薄ⅰ爸戮敖饤l”、“致景紡織智造園”、“致景智慧倉(cāng)物流園”等業(yè)務(wù)板塊,致力于通過(guò)大數(shù)據(jù)、云計(jì)算、物聯(lián)網(wǎng)等新一代信息技術(shù),全面打通紡織服裝行業(yè)的信息流、物流和資金流,幫助行業(yè)實(shí)現(xiàn)協(xié)同化、柔性化、智能化的升級(jí),構(gòu)建紡織服裝縱向一體化的數(shù)智化綜合服務(wù)平臺(tái)。
我們作為集團(tuán)公司已經(jīng)成立 2 年多的一個(gè)業(yè)務(wù)團(tuán)隊(duì),項(xiàng)目并行開(kāi)發(fā)上線的情況越來(lái)越多。值得一提的是,我們目前處于微服務(wù)化拆分剛開(kāi)始的階段,目前 35 個(gè)微服務(wù),拆完之后大概會(huì)去到 60 個(gè)左右。在這樣的背景下,原先大家都使用一套開(kāi)發(fā)/測(cè)試/生產(chǎn)環(huán)境串行跑研發(fā)流程,隨著項(xiàng)目數(shù)量、開(kāi)發(fā)測(cè)試需求的變多,微服務(wù)拆分的進(jìn)行,原先的方式已經(jīng)不太適合我們。下面簡(jiǎn)單羅列一下,我們?cè)谶@過(guò)程中所遇到的三個(gè)問(wèn)題。
1.項(xiàng)目測(cè)試環(huán)境被搶占
最典型的問(wèn)題就是一個(gè)項(xiàng)目測(cè)試環(huán)境經(jīng)常性被缺陷修復(fù)的測(cè)試流程搶占,導(dǎo)致項(xiàng)目測(cè)試時(shí)斷時(shí)續(xù),對(duì)測(cè)試而言缺乏沉浸式體驗(yàn),同時(shí)測(cè)試環(huán)節(jié)成為項(xiàng)目并行度的主要瓶頸,驗(yàn)證影響項(xiàng)目迭代的進(jìn)度。
2.開(kāi)發(fā)聯(lián)調(diào)環(huán)境不穩(wěn)定
為了保證開(kāi)發(fā)的體驗(yàn),開(kāi)發(fā)環(huán)境是允許開(kāi)發(fā)同學(xué)自由發(fā)布。由于使用一套環(huán)境,不同的同學(xué)進(jìn)行開(kāi)發(fā)環(huán)境發(fā)布,經(jīng)常性地導(dǎo)致聯(lián)調(diào)中斷。不少開(kāi)發(fā)同學(xué)轉(zhuǎn)而尋求端到端的線下聯(lián)調(diào),在個(gè)人機(jī)器上部署上下游應(yīng)用,這種模式在微服務(wù)化推廣之后,特別是面對(duì)眾多的微服務(wù)應(yīng)用基本上寸步難行。如何解決開(kāi)發(fā)階段代碼調(diào)試的便攜性,成為了我們遇到的第二個(gè)問(wèn)題。
3.線上灰度環(huán)境的缺乏
第三個(gè)問(wèn)題也是最重要的,之前我們?nèi)鄙賹iT(mén)提供給產(chǎn)品經(jīng)理進(jìn)行功能驗(yàn)證的預(yù)發(fā)環(huán)境。新功能完成測(cè)試之后直接上線到線上環(huán)境,研發(fā)團(tuán)隊(duì)為了避免避免對(duì)客戶產(chǎn)生不良影響,經(jīng)常性地將發(fā)布計(jì)劃安排在晚上。拋開(kāi)研發(fā)團(tuán)隊(duì)的發(fā)布幸福度不談,線上環(huán)境缺乏灰度發(fā)布能力意味著新功能上線以后就會(huì)對(duì)全量用戶放開(kāi),一旦發(fā)生了產(chǎn)品設(shè)計(jì)缺陷或者代碼漏洞的情況,那么影響面將會(huì)是全網(wǎng)的,風(fēng)險(xiǎn)巨大且不可控。
綜上所述,我們需要解決線下缺乏隔離的多套環(huán)境來(lái)支持多項(xiàng)目的開(kāi)發(fā)和測(cè)試,同時(shí)在線上需要具備靈活的流量路由策略支持灰度發(fā)布需求。
02 方案調(diào)研與探索
結(jié)合我們公司實(shí)際情況,我們的目標(biāo)是開(kāi)發(fā)團(tuán)隊(duì)不依賴運(yùn)維團(tuán)隊(duì),即 DEV = OPS 。我們可以一鍵拉起邏輯隔離的開(kāi)發(fā)/項(xiàng)目環(huán)境,同時(shí)可以支持預(yù)發(fā)環(huán)境隔離,對(duì)于生產(chǎn)環(huán)境可以通過(guò)配置灰度規(guī)則流量、自然流量來(lái)進(jìn)行全鏈路灰度的驗(yàn)證。
根據(jù)我們對(duì)當(dāng)前問(wèn)題的分析,參考目前互聯(lián)網(wǎng)上的解決方案,都指向了項(xiàng)目環(huán)境治理和服務(wù)流量治理的方案,我們稍微羅列下常用的幾種方案,我們最終選擇的是阿里云微服務(wù)引擎 MSE 全鏈路灰度 + 云效應(yīng)用交付平臺(tái) APPSTACK 的集成方案。
1.自研 Ribbon 實(shí)現(xiàn)
我們使用的是 Spring Cloud 框架,在平時(shí)的業(yè)務(wù)開(kāi)發(fā)過(guò)程中,后端服務(wù)與服務(wù)之間的調(diào)用往往通過(guò) Fegin 或者 RestTemplate 兩種調(diào)用方式。這其中是通過(guò) Ribbon 這個(gè)組件幫我們做了負(fù)載均衡的功能。灰度的核心就是路由,我們可以通過(guò)重寫(xiě) Ribbon 默認(rèn)的負(fù)載均衡算法,在負(fù)載均衡調(diào)用之前,增加流量路由的邏輯,那么就意味著我們能夠控制服務(wù)流量的轉(zhuǎn)發(fā)。
這個(gè)方案要實(shí)施下去,對(duì)于大廠來(lái)說(shuō)確實(shí)可以從 0 到 1 再到 100 進(jìn)化出來(lái),對(duì)我們來(lái)說(shuō),如果僅僅是實(shí)現(xiàn)一個(gè)路由的功能,做一個(gè)只支持核心場(chǎng)景的簡(jiǎn)陋版確實(shí)不是非常困難的事情。但如果要達(dá)到成熟可應(yīng)用的階段,需要投入專門(mén)的技術(shù)資源對(duì)其進(jìn)行管理與維護(hù),同時(shí)由于 Spring Cloud 微服務(wù)框架本身的復(fù)雜性,隨著微服務(wù)數(shù)量逐步增多,鏈路越來(lái)越長(zhǎng),相關(guān)的微服務(wù)治理問(wèn)題的定位與解決,也會(huì)耗費(fèi)不菲的時(shí)間成本。
2.物理隔離(藍(lán)綠發(fā)布)
這種方案需要為要灰度的服務(wù)搭建一套網(wǎng)絡(luò)隔離、資源獨(dú)立的環(huán)境,在其中部署服務(wù)的灰度版本。由于與基礎(chǔ)環(huán)境隔離,基礎(chǔ)環(huán)境中的其他服務(wù)無(wú)法訪問(wèn)到需要灰度的服務(wù),所以需要在灰度環(huán)境中冗余部署這些服務(wù),以便整個(gè)調(diào)用鏈路正常進(jìn)行流量轉(zhuǎn)發(fā)。此外,注冊(cè)中心等一些其他依賴的中間件組件也需要冗余部署在灰度環(huán)境中,保證微服務(wù)之間的可?性問(wèn)題,確保獲取的節(jié)點(diǎn) IP 地址只屬于當(dāng)前的網(wǎng)絡(luò)環(huán)境。這個(gè)方案需要為這些業(yè)務(wù)場(chǎng)景采用堆機(jī)器的方式來(lái)維護(hù)多套灰度環(huán)境,會(huì)造成運(yùn)維、機(jī)器成本過(guò)大,成本和代價(jià)遠(yuǎn)超收益;當(dāng)然如果應(yīng)用數(shù)目很小,就兩三個(gè)應(yīng)用,這個(gè)方式還是很方便的,可以接受的。
3.MSE 標(biāo)簽路由+APPSTACK 應(yīng)用編排(我們的選擇)
這兩款產(chǎn)品的說(shuō)明文檔見(jiàn)鏈接
云效應(yīng)用交付平臺(tái) AppStack :
https://help.aliyun.com/document_detail/321856.html
阿里云微服務(wù)引擎 MSE 全鏈路灰度 :
https://help.aliyun.com/document_detail/170454.html
我們假定通過(guò)上面的兩篇文章,讀者已經(jīng)對(duì)這兩個(gè)產(chǎn)品已經(jīng)有了簡(jiǎn)單的了解,一句話介紹就是:APPSTACK 負(fù)責(zé)應(yīng)用的環(huán)境管理和流水線發(fā)布,MSE 負(fù)責(zé)流量的全鏈路灰度。
- MSE 全鏈路灰度的重要概念
對(duì)照下面的 MSE 標(biāo)簽路由的圖,我們重點(diǎn)介紹下 MSE 標(biāo)簽路由的幾個(gè)重要概念如應(yīng)用的打標(biāo)、流量染色/自動(dòng)染色、標(biāo)識(shí)鏈路傳遞等,同時(shí)下圖也是我們采用方案的核心原理,使用域名來(lái)標(biāo)識(shí)不同的邏輯隔離環(huán)境。
核心示意圖
(1)應(yīng)用(服務(wù))打標(biāo)
對(duì)照核心示意圖,我們發(fā)現(xiàn)每個(gè)應(yīng)用都有個(gè)(base/gray)的 tag,有了這個(gè) tag,我們才可以根據(jù) tag 定義流量規(guī)則。
我們創(chuàng)建 MSE 應(yīng)用的時(shí)候是通過(guò)特定 annotation 和環(huán)境變量給 MSE 應(yīng)用打標(biāo)的。
特定 annotation:
alicloud.service.tag=dev1
環(huán)境變量:
spring.cloud.nacos.discovery.metadata.version
增加特定的 annotation 跟環(huán)境變量
比如通過(guò) annotation 打標(biāo)之后我們就可以在 MSE 的標(biāo)簽路由中進(jìn)行流量規(guī)則定義,同時(shí)我們也可以看到 Nacos 里面的服務(wù)有了一個(gè)標(biāo)簽相關(guān)的元數(shù)據(jù)(_micro.service.env_);
MSE 流量規(guī)則配置
Nacos 里面元數(shù)據(jù)信息
也有額外增加一個(gè)容器環(huán)境變量的做法:
spring.cloud.nacos.discovery.metadata.version
這種做法會(huì)在 Nacos 的服務(wù)元數(shù)據(jù)中增加一個(gè) version 屬性,像 MSE 云原生網(wǎng)關(guān)就會(huì)借助這個(gè) version 屬性進(jìn)行流量管理,而 MSE 全鏈路灰度是借助 alicloud.service.tag 定義的標(biāo)簽進(jìn)行流量管理。
容器中增加 gray 相關(guān)的環(huán)境變量
MSE 流量規(guī)則配置出現(xiàn) gray 節(jié)點(diǎn)
Nacos 里面有g(shù)ray環(huán)境的元數(shù)據(jù)信息
MSE 云原生網(wǎng)關(guān)可以選擇 gray 版本
(2) 流量染色/自動(dòng)染色
簡(jiǎn)單講,流量染色就是流量帶上了特別的標(biāo)識(shí),對(duì)于 HTTP 請(qǐng)求來(lái)說(shuō),是請(qǐng)求頭里帶了一些標(biāo)識(shí)信息,對(duì)于 Message 來(lái)說(shuō),是消息頭里帶了標(biāo)識(shí)信息;我們這里主要講下 HTTP 流量染色問(wèn)題;一種是人工的往 HTTP 請(qǐng)求里面增加標(biāo)識(shí)信息,比如前端請(qǐng)求后端 API 的時(shí)候,增加一個(gè) xx:111 的標(biāo)識(shí)信息,那我們就說(shuō)這個(gè)流量被染色了。而自動(dòng)染色,則說(shuō)的是一個(gè)沒(méi)有標(biāo)識(shí)的 HTTP 請(qǐng)求,經(jīng)由某個(gè)打了標(biāo)的 nacos 服務(wù)之后,往后調(diào)用下一個(gè)服務(wù)的時(shí)候,自動(dòng)會(huì)帶上這個(gè) nacos 服務(wù)的標(biāo)簽信息在請(qǐng)求頭里;最簡(jiǎn)單的舉例就是 a 應(yīng)用調(diào)用 b(gray)應(yīng)用,那b應(yīng)用調(diào)用后面的 c 應(yīng)用的時(shí)候,會(huì)自動(dòng)帶上 x-mse-tag:gray 的請(qǐng)求頭,這就是自動(dòng)染色。
這里特別提到 x-mse-tag:xxx 這個(gè)標(biāo)識(shí),他是 MSE 系統(tǒng)保留的標(biāo)識(shí),不僅僅代表了染色,同時(shí)也代表了鏈路傳遞(這個(gè)請(qǐng)求鏈路上的各個(gè)節(jié)點(diǎn)都會(huì)依次傳遞這個(gè)標(biāo)簽下去)和默認(rèn)的路由規(guī)則(優(yōu)先選擇 xxx 標(biāo)識(shí)的服務(wù),沒(méi)有找到的情況下,再選擇 base 服務(wù)-沒(méi)有打標(biāo)的),這個(gè)默認(rèn)路由規(guī)則是不需要顯式定義的。
我們的解決方案也是特別地利用了這一點(diǎn),對(duì)照核心示意圖,我們?cè)谟蛎种刑砑恿肆髁繕?biāo)識(shí),然后在 Ingress-Nginx 中將流量標(biāo)識(shí)解析出來(lái)然后通過(guò) x-mse-tag:xxx 的方式一路傳遞下去,這樣就實(shí)現(xiàn)了在整個(gè)鏈路上優(yōu)先選擇 xxx 標(biāo)識(shí)的服務(wù),使用沒(méi)有標(biāo)識(shí)的 base 服務(wù)進(jìn)行兜底。
(3)標(biāo)識(shí)鏈路傳遞
流量被染色,也就是請(qǐng)求頭中有特定標(biāo)識(shí)之后,這個(gè)標(biāo)識(shí)在調(diào)用鏈路中如何可以傳遞下去,比如一個(gè) HTTP 請(qǐng)求,帶了 user-id:100 的頭,陸續(xù)需要經(jīng)過(guò) A->B->C。即調(diào)用 A 的時(shí)候帶了 user-id:100,A 調(diào)用 B 的時(shí)候也希望可以帶上 user-id:100 的請(qǐng)求頭,同樣 B 調(diào)用 C 的時(shí)候也要帶上 user-id:100。這個(gè)就是標(biāo)識(shí)的鏈路傳遞,有了這個(gè)標(biāo)識(shí)鏈路傳遞,我們才可以在為 A/B/C 應(yīng)用定義按 user-id 的值進(jìn)行路由的策略。MSE 的標(biāo)識(shí)鏈路傳遞的方法是定義環(huán)境變量 alicloud.service.header=x-user-id,在入口應(yīng)用 A(所有版本,gray+base)增加該環(huán)境變量以后,往后的調(diào)用 B 和 C 的過(guò)程中,都會(huì)自動(dòng)添加請(qǐng)求頭 x-user-id 進(jìn)行傳遞,這樣就方便我們?cè)?A,B,C 節(jié)點(diǎn)按照特有規(guī)則進(jìn)行路由定義。當(dāng)然 x-mse-tag 這個(gè)特殊的請(qǐng)求頭默認(rèn)就是鏈路傳遞的,MSE 會(huì)把這個(gè)標(biāo)識(shí)層層傳遞下去并進(jìn)行默認(rèn)的路由規(guī)則(tag 優(yōu)先,base 兜底);MSE 標(biāo)識(shí)鏈路傳遞的原理如下,借助分布式鏈路追蹤的框架的實(shí)現(xiàn)方式,每個(gè)應(yīng)用的探針攔截請(qǐng)求并解析標(biāo)識(shí),然后暫存到線程空間,在往后調(diào)用的時(shí)候再通過(guò)探針把標(biāo)識(shí)塞到下個(gè)請(qǐng)求。通過(guò)分布式鏈路追蹤的框架完成標(biāo)識(shí)傳遞。
- 阿里云效應(yīng)用交付 APPSTACK 簡(jiǎn)述
我們把云效 APPSTACK 引入進(jìn)來(lái),主要目的是方便開(kāi)發(fā)同學(xué)通過(guò)白屏的管理方式自助完成 MSE 所需要的配置工作,同時(shí)在微服務(wù)架構(gòu)下,我們希望應(yīng)用進(jìn)行拆分之后,每個(gè)應(yīng)用都有自己的 owner。
通過(guò) APPSTACK 我們可以屏蔽 K8s 的 deployment,service,ingress 等細(xì)節(jié),研發(fā)同學(xué)面向的就是應(yīng)用+環(huán)境+流水線。這樣最終開(kāi)發(fā)人員在 APPSTACK 通過(guò)流水線完成應(yīng)用的環(huán)境部署,每個(gè)環(huán)境都會(huì)按照 MSE 標(biāo)簽路由的要求打上不同的標(biāo)識(shí)。
應(yīng)用的多套環(huán)境部署
圖片每個(gè)環(huán)境都會(huì)按照 MSE 標(biāo)簽路由的要求打上不同的標(biāo)識(shí)
在這里我們不展開(kāi)講述 APPSTACK 的核心功能,我們這里主要的就是借助應(yīng)用編排,讓每個(gè)應(yīng)用的每個(gè)環(huán)境部署的時(shí)候,可以設(shè)置好 MSE 標(biāo)簽路由所需要的各種環(huán)境變量和 annotation。
03 我們的解決方案
我們?cè)谡{(diào)研了以上能力之后,根據(jù)自己公司的實(shí)際場(chǎng)景與業(yè)務(wù)需求,根據(jù)不同環(huán)境的特性,定義了多種環(huán)境的抽象,基于此構(gòu)建了一站式動(dòng)態(tài)多環(huán)境的能力,并針對(duì)主要場(chǎng)景設(shè)計(jì)了不同的實(shí)施方案。
1 環(huán)境定義
通過(guò)對(duì)阿里云微服務(wù)引擎 MSE 標(biāo)簽路由和云效應(yīng)用編排 APPSTACK 的調(diào)研,結(jié)合我們前面提到所面臨的問(wèn)題,我們最終定義了我們整個(gè)研發(fā)體系所需要的環(huán)境體系即:多套的開(kāi)發(fā)環(huán)境(含基礎(chǔ)環(huán)境)+多套項(xiàng)目環(huán)境(含基礎(chǔ)環(huán)境)+(集成)測(cè)試環(huán)境+預(yù)發(fā)環(huán)境+(支持灰度)生產(chǎn)環(huán)境,如下圖
多套開(kāi)發(fā)環(huán)境:目標(biāo)是支持多個(gè)項(xiàng)目的在開(kāi)發(fā)階段的開(kāi)發(fā)聯(lián)調(diào),核心要求是各項(xiàng)目動(dòng)態(tài)隔離并且支持端云互聯(lián),項(xiàng)目動(dòng)態(tài)隔離是每個(gè)項(xiàng)目都有自己的開(kāi)發(fā)聯(lián)調(diào)環(huán)境且只需部署有變動(dòng)應(yīng)用,端云互聯(lián)是開(kāi)發(fā)可以將自己本地跑的應(yīng)用注冊(cè)到這個(gè) MSE 這個(gè)體系里面來(lái),實(shí)現(xiàn)可以本地調(diào)試的目的,兩個(gè)研發(fā)可以點(diǎn)對(duì)點(diǎn)地進(jìn)行本地 debug 來(lái)跟蹤問(wèn)題。開(kāi)發(fā)基礎(chǔ)環(huán)境是負(fù)責(zé)兜底服務(wù)調(diào)用的,每個(gè)應(yīng)用生產(chǎn)部署之后都需要同步更新開(kāi)發(fā)基礎(chǔ)環(huán)境,保障基礎(chǔ)環(huán)境是最新的生產(chǎn)版本。
多套項(xiàng)目環(huán)境:目標(biāo)是支持耗時(shí)較長(zhǎng)的大型項(xiàng)目,比如重大技改,重大業(yè)務(wù)項(xiàng)目,需要長(zhǎng)時(shí)間占用測(cè)試環(huán)境跟內(nèi)外部關(guān)聯(lián)方進(jìn)行穩(wěn)定測(cè)試的。核心要求是各個(gè)項(xiàng)目動(dòng)態(tài)隔離。關(guān)于項(xiàng)目動(dòng)態(tài)隔離的定義同上。
測(cè)試環(huán)境:目標(biāo)是支持短平快的項(xiàng)目測(cè)試和集成測(cè)試,比如日常的缺陷修復(fù),或者多個(gè)小項(xiàng)目需要集成到一起發(fā)布,同時(shí)也是我們?nèi)粘W詣?dòng)化測(cè)試的環(huán)境。項(xiàng)目環(huán)境中的特性分支也需要經(jīng)過(guò)測(cè)試環(huán)境的自動(dòng)化測(cè)試才可以上線。
預(yù)發(fā)環(huán)境:目標(biāo)是支持產(chǎn)品經(jīng)理在真實(shí)環(huán)境中驗(yàn)證產(chǎn)品功能,進(jìn)行驗(yàn)收,預(yù)發(fā)環(huán)境使用的基礎(chǔ)建設(shè)如數(shù)據(jù)庫(kù)等同生產(chǎn)環(huán)境是一致的,當(dāng)然這里對(duì)系統(tǒng)設(shè)計(jì)也會(huì)提出更高的要求,比如需要保持向前兼容,就像數(shù)據(jù)庫(kù),只能增列不能減列,不能在 sql 中使用 select * 等等,這些我們通過(guò) DMS 進(jìn)行數(shù)據(jù)庫(kù)結(jié)構(gòu)變更的約束和通過(guò)代碼檢查保障,此處不贅述。
生產(chǎn)環(huán)境:目標(biāo)是支持規(guī)則流量+自然流量的全鏈路灰度,這里的規(guī)則流量指的是帶有明顯特征的流量,通過(guò) MSE 的流量規(guī)則能夠清晰定義的請(qǐng)求,比如請(qǐng)求頭,參數(shù),cookie,body 中數(shù)據(jù)符合規(guī)則的。自然流量則相反,我們不指定任何特征,比如全部流量的 1%導(dǎo)入到灰度環(huán)境,這個(gè)我們就理解成自然流量。
綜合來(lái)看,目前的環(huán)境體系里,開(kāi)發(fā)環(huán)境和項(xiàng)目環(huán)境涉及到動(dòng)態(tài)隔離,所以需要部署基礎(chǔ)環(huán)境來(lái)完成服務(wù)兜底的能力,這個(gè)基礎(chǔ)環(huán)境也就是 MSE 標(biāo)簽路由中無(wú)標(biāo)簽(base)應(yīng)用的提供者。
這一套環(huán)境體系的流轉(zhuǎn)流程主要有:
1. 拉取特性分支進(jìn)入開(kāi)發(fā)環(huán)境進(jìn)行本地開(kāi)發(fā)和前后端聯(lián)調(diào),然后提測(cè)到項(xiàng)目環(huán)境
2. 項(xiàng)目環(huán)境由測(cè)試團(tuán)隊(duì)完成功能測(cè)試之后,將應(yīng)用部署到(集成)測(cè)試環(huán)境
3. 在(集成)測(cè)試環(huán)境同其他特性分支一起完成集成,并通過(guò)自動(dòng)化測(cè)試和簡(jiǎn)單驗(yàn)證,就可以部署至預(yù)發(fā)環(huán)境
4. 產(chǎn)品經(jīng)理在預(yù)發(fā)環(huán)境進(jìn)行功能驗(yàn)收測(cè)試,通過(guò)之后可以發(fā)布到生產(chǎn)環(huán)境進(jìn)行灰度驗(yàn)證
5. 在生產(chǎn)環(huán)境可以按照規(guī)則流量+自然流量進(jìn)行灰度驗(yàn)證,通過(guò)之后就可以導(dǎo)入全部流量
6. 最后將特性分支合并至主干后用最新的生產(chǎn)版本更新開(kāi)發(fā)/項(xiàng)目基礎(chǔ)環(huán)境。
2.主要場(chǎng)景實(shí)施
- 場(chǎng)景一:項(xiàng)目隔離的動(dòng)態(tài)多環(huán)境
按照我們的解決方案,項(xiàng)目環(huán)境要實(shí)現(xiàn)的是邏輯隔離的動(dòng)態(tài)多環(huán)境,相當(dāng)于每個(gè)應(yīng)用我們要通過(guò) APPSTACK 部署基礎(chǔ)環(huán)境(負(fù)責(zé)兜底的無(wú)標(biāo)簽 base 應(yīng)用)和動(dòng)態(tài)項(xiàng)目環(huán)境(有變更的)同時(shí)我們需要保障前端調(diào)用后端的域名可以轉(zhuǎn)換成 x-mse-tag 的請(qǐng)求頭。
1. 通過(guò) APPSTACK 部署好有標(biāo)簽的應(yīng)用(項(xiàng)目環(huán)境)和沒(méi)標(biāo)簽的應(yīng)用(基礎(chǔ)環(huán)境),下列截圖僅做示范
2. 在 ingress-nginx 中解析域名中的 tag 屬性轉(zhuǎn)換成 x-mse-tag 請(qǐng)求頭鏈路傳遞,通過(guò) ingress 配置攜帶 header 方式到 api 網(wǎng)關(guān)。
通過(guò)注解
nginx.ingress.kubernetes.io/configuration-snippet 實(shí)現(xiàn),具體如下:
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: proxy_set_header x-mse-tag dev1
通過(guò)這樣簡(jiǎn)單配置之后,前端調(diào)用后端服務(wù)的時(shí)候,只要通過(guò)特定的域名請(qǐng)求,那 ingres-nginx 就可以把這個(gè)域名對(duì)應(yīng)的請(qǐng)求自動(dòng)添加一個(gè) x-mse-tag 的請(qǐng)求傳遞到 api 網(wǎng)關(guān)應(yīng)用,然后借助這個(gè) x-mse-tag 的特殊請(qǐng)求頭,在調(diào)用下游服務(wù)的時(shí)候,就會(huì)一路優(yōu)先選擇 dev1 標(biāo)簽的服務(wù),沒(méi)有 dev1 標(biāo)簽的服務(wù)就會(huì)去找兜底的 base 服務(wù)。
- 場(chǎng)景二:規(guī)則流量全鏈路灰度的生產(chǎn)環(huán)境
1. 通過(guò) APPSTACK 在生產(chǎn)環(huán)境部署好有灰度標(biāo)識(shí)的應(yīng)用。
2. 定義流量路由規(guī)則,在 MSE 控制臺(tái)為本次灰度鏈路中的入口應(yīng)用設(shè)置流量路由規(guī)則,比如本次發(fā)布更新了 A-B-C 三個(gè)應(yīng)用,A 就是入口應(yīng)用。
通過(guò)這種方式定義之后,我們可以設(shè)置符合某些特征的流量進(jìn)入到 A 應(yīng)用的 gray 版本,并且向后層層傳遞過(guò)去,不用每個(gè)應(yīng)用重復(fù)設(shè)置路由規(guī)則。這就會(huì)滿足了規(guī)則流量的全鏈路灰度的要求。
- 場(chǎng)景三:自然流量全鏈路灰度的生產(chǎn)環(huán)境
1. 通過(guò)APPSTACK在生產(chǎn)環(huán)境部署好有灰度標(biāo)識(shí)的應(yīng)用,略圖。這里至少需要為本次項(xiàng)目的入口應(yīng)用 A(也可以是全部應(yīng)用)增加一個(gè)自動(dòng)染色的變量 profiler.micro.service.tag.trace.enable=true,這個(gè)變量會(huì)把經(jīng)過(guò)這個(gè)入口應(yīng)用 A 的流量自動(dòng)染色,往后傳遞的時(shí)候自動(dòng)增加 x-mse-tag 的請(qǐng)求頭,從而實(shí)現(xiàn)全鏈路灰度
2. 定義流量規(guī)則,即自然流量的多少比例進(jìn)入 gray 環(huán)境
這樣通過(guò)入口應(yīng)用的自動(dòng)染色,以及入口應(yīng)用的自然流量分批,我們就可以讓進(jìn)入到入口應(yīng)用 gray 節(jié)點(diǎn)的自然流量進(jìn)入到全鏈路的灰度環(huán)境(灰度優(yōu)先,基礎(chǔ)應(yīng)用兜底)。
目前為止,我們實(shí)現(xiàn)了默認(rèn)按照域名進(jìn)行項(xiàng)目/開(kāi)發(fā)多環(huán)境邏輯動(dòng)態(tài)隔離的效果;同時(shí)提供給研發(fā)團(tuán)隊(duì)便捷的白屏管理的工具,可以由項(xiàng)目組獨(dú)立拉起整個(gè)環(huán)境,通過(guò)三個(gè)場(chǎng)景化的實(shí)施方案,完美解決了開(kāi)篇提到的三個(gè)問(wèn)題。
3.相關(guān)技術(shù)原理概要介紹
MSE + APPSTACK 的解決方案,核心的地方在于流量規(guī)則的定義以及流量標(biāo)識(shí)的傳遞,其核心的解決方案在于流量中標(biāo)識(shí)的解析和傳遞,我們?cè)倏匆淮芜@個(gè)標(biāo)識(shí)傳遞的圖:
怎么樣才能實(shí)現(xiàn)這里面最核心的解析 Extract 和注入 Inject 的功能呢?
答案是探針,為每個(gè) MSE 管理的應(yīng)用運(yùn)行時(shí)候增加一個(gè) java agent 的探針,完成一個(gè)類似 JVM AOP 的能力,在 ACK(K8s)的容器中,MSE 通過(guò)如下的方式自動(dòng)為應(yīng)用安裝 java agent;
1. 配置 Webhook,然后根據(jù) Pod 或者 Namespac中的 Labels,來(lái)判斷是否要掛載 Java Agent。如果需要掛載,則就對(duì) Pod 的聲明?件做出后續(xù)修改
2. 獲取并添加環(huán)境變量 JAVA_TOOL_OPTIONS,?于加載 Java Agent。
3. 給業(yè)務(wù)容器添加 Volume,?于存儲(chǔ) Java Agent 的?件內(nèi)容。
4. 給 Pod 添加 Init container,?于在業(yè)務(wù)容器啟動(dòng)前下載 Java Agent
最終我們每個(gè)被 MSE 管理的應(yīng)用在 POD 層面可以看到如下信息:
有了這個(gè)探針,我們可以攔截所有 HTTP REQUEST 的處理類,將我們關(guān)心的標(biāo)識(shí)信息暫存起來(lái),然后在應(yīng)用內(nèi)部消費(fèi) Nacos 服務(wù)的時(shí)候增加 MSE 支持的路由邏輯,選擇合適的服務(wù) provider(比如是打了 gray 標(biāo)的),同時(shí)在調(diào)用這個(gè) provider 的服務(wù)的時(shí)候,可以將暫存的流量標(biāo)識(shí)帶在請(qǐng)求頭里繼續(xù)傳遞下去,大體上跟我們最開(kāi)始提到的自研 Ribbon 的方式相似。不過(guò) MSE 在這塊做得比較成熟,同時(shí)不單單支持了 HTTP REST 這種服務(wù)調(diào)用方式,還包括了 Dubbo、RocketMQ 的消息灰度、數(shù)據(jù)庫(kù)灰度等。當(dāng)然全鏈路灰度僅僅是微服務(wù)引擎 MSE 一個(gè)很小的功能,微服務(wù)引擎 MSE(Microservices Engine)是一個(gè)面向業(yè)界主流開(kāi)源微服務(wù)生態(tài)的一站式微服務(wù)平臺(tái),提供注冊(cè)配置中心(原生支持 Nacos/ZooKeeper/Eureka)、云原生網(wǎng)關(guān)(原生支持 Ingress/Envoy)、微服務(wù)治理(原生 支持Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服務(wù)治理規(guī)范)的能力,有興趣的同學(xué)可以看看官方文檔。
04 借事修人
作為創(chuàng)業(yè)團(tuán)隊(duì)來(lái)講,能夠快速具備一站式解決服務(wù)治理問(wèn)題,是一件非常酷的事。這整個(gè)方案的討論實(shí)施過(guò)程中,研發(fā)團(tuán)隊(duì)對(duì)于 K8s、Nginx Ingress、MSE 都有較深入的理解。“像我們部門(mén)研發(fā)團(tuán)隊(duì),沒(méi)有專門(mén)的運(yùn)維團(tuán)隊(duì),每個(gè)開(kāi)發(fā)人員都可以深入了解每個(gè)產(chǎn)品的來(lái)龍去脈,想想就很有意義。”