喜茶基于 Spring Cloud 和 Kubernetes 構(gòu)建云原始應(yīng)用的落地

????????喜茶互聯(lián)網(wǎng)技術(shù)中心花了一年的時(shí)間,將一整套基于 Spring Cloud 和 Kubernetes 構(gòu)建的云原生(Cloud-Native)微服務(wù)應(yīng)用落地,目前服務(wù)都已經(jīng)部署在云上,一直保持著非常良好的運(yùn)行狀態(tài)。

????????在完成了首次應(yīng)用落地之后,喜茶互聯(lián)網(wǎng)技術(shù)中心將以更快的迭代速度落地更多的云原生應(yīng)用。在過(guò)去這一年的落地實(shí)戰(zhàn)過(guò)程中,我們始終堅(jiān)持做一件正確的事——“技術(shù)和架構(gòu)約定高于配置,推行大規(guī)模自動(dòng)化建設(shè)的同時(shí),在內(nèi)部普及 DevOps 文化”。讓內(nèi)部的所有人都參與到這件事里面進(jìn)來(lái),甚至帶有強(qiáng)制性,因?yàn)樵圃⒎?wù)應(yīng)用的構(gòu)建非常依賴于契約,我們的未來(lái)是大規(guī)模云化和微服務(wù)化,所以只有當(dāng)大家都有了契約意識(shí)之后,才能正常的開(kāi)展各項(xiàng)工作,才能保持我們的整體形散而神不散。如果過(guò)去的這一年我們沒(méi)有堅(jiān)持做這件事情,估計(jì)在這個(gè)時(shí)間點(diǎn)還沒(méi)辦法寫(xiě)出這篇總結(jié)性的文章。

????????關(guān)于云原生應(yīng)用,《Migrating to Cloud-Native Application Architectures》的作者 Matt Stine 在書(shū)中解釋得非常到位,總結(jié)的非常全面也比較抽象,有興趣的可以研究一下,pivotal 官網(wǎng)提供了電子版(點(diǎn)擊這里下載),內(nèi)容 50 幾頁(yè)。其內(nèi)容包含了技術(shù)和管理諸多方面的論證,簡(jiǎn)單的理解就是為了傳統(tǒng)的單體應(yīng)用和面向服務(wù)的應(yīng)用更好地遷移到云上,更好地利用云優(yōu)勢(shì),組織、技術(shù)和文化作出了必要的改變。

DevOps 文化的普及

????????雖然我們把“DevOps 文化的普及”排在“約定高于配置,大規(guī)模自動(dòng)化建設(shè),普及 DevOps 文化”三項(xiàng)任務(wù)(重要程度)的末尾,但實(shí)際上卻是最先進(jìn)行。DevOps 文化的推行直接影響到管理和組織結(jié)構(gòu),還有溝通方式、做事方式、技術(shù)棧、術(shù)語(yǔ)等等內(nèi)容,所以在萬(wàn)事開(kāi)頭,讓大家都知道我們接下來(lái)要做什么,然后才開(kāi)始安排做的時(shí)間和怎么做似乎更符合我們的狀態(tài)。當(dāng)時(shí)我們?cè)u(píng)估過(guò)實(shí)際情況,發(fā)現(xiàn)缺少了一個(gè)云平臺(tái)部門,也就說(shuō)是缺少云端支持,兩名運(yùn)維人員也相對(duì)缺乏深入的容器云運(yùn)維經(jīng)驗(yàn),于是我們開(kāi)始轉(zhuǎn)向“由后端開(kāi)發(fā)主導(dǎo)”的方向,因?yàn)?DevOps 本身模糊了很多開(kāi)發(fā)和運(yùn)維的工作邊界,如果能從開(kāi)發(fā)側(cè)找到 DevOps 的入口,我們依然可以在人力上更勝一籌。果不其然,在選定公有云為基礎(chǔ)平臺(tái)的前提下,我們不需要做太多關(guān)于云方面的運(yùn)維,云廠商保障了我們所需的網(wǎng)絡(luò)和存儲(chǔ)高可用,借助 Kubernetes 和 Docker 容器技術(shù),讓我們的開(kāi)發(fā)側(cè)同學(xué)需要去涉及的運(yùn)維工作僅僅到構(gòu)建出一個(gè)鏡像就可以止步,剩下的工作就是 Kubernetes 自動(dòng)運(yùn)維和應(yīng)用參數(shù)調(diào)優(yōu)。

????????在我們的 DevOps 文化里,運(yùn)維工作的目的并不是維持系統(tǒng)穩(wěn)定,而是促進(jìn)業(yè)務(wù)敏捷上線,系統(tǒng)穩(wěn)定性的運(yùn)維工作已經(jīng)被自動(dòng)化工具和云廠商大范圍取代。而開(kāi)發(fā)同學(xué)的工作除了常規(guī)業(yè)務(wù)開(kāi)發(fā)外,還需要知道怎樣快速無(wú)差別的交付代碼到其他階段環(huán)境運(yùn)行,適當(dāng)?shù)膮⑴c運(yùn)維或者指導(dǎo)運(yùn)維再合適不過(guò)了。如此,開(kāi)發(fā)和運(yùn)維工作邊界才變得有些模糊,但目的是統(tǒng)一的。

????????DevOps 文化的普及第一步是讓運(yùn)維和開(kāi)發(fā)融會(huì)貫通,抹平兩邊的邊界障礙。然后,通過(guò)開(kāi)發(fā)側(cè)的控制和引導(dǎo),讓產(chǎn)品側(cè)接受 DevOps 的操作方式,產(chǎn)品側(cè)都是希望需求能快速推上線,更希望緊急需求可以極速上線,所以說(shuō)如果 DevOps 方式能做到做好,那自然沒(méi)有不接受的理由;通過(guò)運(yùn)維側(cè)的控制和引導(dǎo),讓測(cè)試和線上反饋接入 DevOps;通過(guò)逐漸引導(dǎo) DevOps 文化,疏導(dǎo)規(guī)范流程,推進(jìn)自動(dòng)化,橫向打通管理組織,縱向集成技術(shù)棧和工具鏈,保證質(zhì)量和安全,提升交付能力,穩(wěn)定交付節(jié)奏。

????????更具體的表現(xiàn)為:(1)、開(kāi)發(fā)側(cè)控制了需求入口,總是讓需求有大小、有輕重、有緩急地串行進(jìn)入開(kāi)發(fā)側(cè),不相關(guān)的需求安排成并行開(kāi)發(fā),然后并行測(cè)試,最后測(cè)試控制了需求出口,運(yùn)維將需求串行快速上線,類似于總分總策略。(2)、重新工程化所有項(xiàng)目,項(xiàng)目的工程化是為了支持快速構(gòu)建、發(fā)布和運(yùn)行流程,在項(xiàng)目的生命周期中,需求、開(kāi)發(fā)、測(cè)試、發(fā)布、維護(hù)的每一步都由多個(gè)角色組協(xié)作,從而每一環(huán)節(jié)可以平滑銜接。

????????就這樣開(kāi)發(fā)側(cè)作為 DevOps 入口,我們開(kāi)始了 DevOps 的推行,首先是高仿真生產(chǎn)環(huán)境,在公司內(nèi)部自建了一套 Kubernetes 環(huán)境用于開(kāi)發(fā)調(diào)試、前后端聯(lián)調(diào)以及技術(shù)預(yù)研,然后在云上創(chuàng)建了測(cè)試環(huán)境和預(yù)生產(chǎn)環(huán)境用于無(wú)限逼近生產(chǎn)環(huán)境。很自然地,從開(kāi)發(fā)到測(cè)試再到生產(chǎn)的過(guò)度,環(huán)境相似度正在逐漸逼近生產(chǎn)環(huán)境,流轉(zhuǎn)工作 90% 由自動(dòng)化工具完成,使得階段流轉(zhuǎn)非常的快捷。

????????當(dāng)所有人都知道并熟悉這種文化和方式之后,我們發(fā)現(xiàn),沒(méi)有人工干預(yù)的環(huán)境出故障的機(jī)率微乎其微,人力都可以全力撲在需求設(shè)計(jì)和實(shí)現(xiàn)上,這大概就是我們普及的整個(gè) DevOps 文化的核心部分。

????????當(dāng)然,前期也是障礙不斷,比如喜歡按照傳統(tǒng)方式做開(kāi)發(fā)管理的同學(xué)會(huì)不斷質(zhì)疑,我怎么知道我在操作的對(duì)象是什么,我們對(duì)于那些沒(méi)有經(jīng)手操辦的事情難免有些顧慮,這是嚴(yán)謹(jǐn)?shù)膽B(tài)度,也是正常反應(yīng);又比如當(dāng)并行開(kāi)發(fā)的需求非常多時(shí),如果只讓一個(gè)人去管理所有事務(wù),將會(huì)變的非常困難,只有扁平化的組織結(jié)構(gòu),權(quán)力下放給得力助手才能比較好的應(yīng)付這種“高并發(fā)”模式。誠(chéng)然,這類障礙歸根到底還是 DevOps 普及不到位,只能慢慢磨合和過(guò)渡。

????????一個(gè)最大的疑問(wèn)是 DevOps 是否真的就適合我們!坦白說(shuō),答案只有在試運(yùn)行之后才能知曉。這里說(shuō)的“適合”指的是人和組織是否“適合”。我個(gè)人有過(guò)傳統(tǒng)應(yīng)用轉(zhuǎn)云效率反而下降的經(jīng)歷,究其原因是組織固化,新文化推不動(dòng)。當(dāng)出現(xiàn)這種情況時(shí),可以采取開(kāi)辟新天地的方式,讓新的應(yīng)用系統(tǒng)先行,再逐步重構(gòu)或者替換老的系統(tǒng),前期用更多的資源來(lái)?yè)Q取更高的成功率。我們公司在推行 DevOps 的過(guò)程中,嘗試了兩次 PHP 舊系統(tǒng)的云化后,還是決定放棄,轉(zhuǎn)而直接進(jìn)入新架構(gòu)的云化進(jìn)程,也就是實(shí)現(xiàn)基于 Spring Cloud 和 Kubernetes 的云原生新架構(gòu)。其中的技術(shù)選型出于諸多因素的考慮,比如資源和未來(lái)的發(fā)展方向,我們的 DevOps 針對(duì)的也都是新架構(gòu)下的技術(shù)棧和工具鏈,舊系統(tǒng)大體維持不變。

????????普及 DevOps,工具很關(guān)鍵。開(kāi)發(fā)團(tuán)隊(duì)和運(yùn)維團(tuán)隊(duì)為了促進(jìn)業(yè)務(wù)敏捷快速,需要一系列支持快速發(fā)布軟件的工具和文化。其中工具包括:自動(dòng)化構(gòu)建、持續(xù)集成、持續(xù)部署、持續(xù)監(jiān)控、機(jī)器人和統(tǒng)一平臺(tái)等等。

大規(guī)模自動(dòng)化建設(shè)

????????普及 DevOps 伴隨著大規(guī)模的自動(dòng)化建設(shè),沒(méi)有自動(dòng)化的支持 DevOps 寸步難行。

????????從代碼編輯器、版本管理工具、配置管理、文檔管理、構(gòu)建工具、部署工具、測(cè)試工具、監(jiān)控工具、數(shù)據(jù)采集工具再到機(jī)器人工具等等組成的工具鏈,從編程語(yǔ)言、框架、依賴管理、打包、數(shù)據(jù)持久化技術(shù)、分布式、高可用、安全,容災(zāi)等等組成的技術(shù)棧,都需要能夠支持自動(dòng)化或者被自動(dòng)化。當(dāng)自動(dòng)化在這些方面幫我們完成的工作量低于 80% 時(shí)就會(huì)有明顯的不順暢感,我們的管理工具需要做到貫穿一整個(gè)項(xiàng)目的生命周期,也一并把工具鏈和技術(shù)棧整合在一起,像拉鏈一樣工作。

????????自動(dòng)化建設(shè)本身不直接產(chǎn)生業(yè)績(jī)之類的東西,短期內(nèi)沒(méi)能看出有什么明顯的產(chǎn)出價(jià)值,雖然也可以白紙黑字的存在在那里,卻沒(méi)辦法直接產(chǎn)生收益,終究不像業(yè)務(wù)需求那么直白明了,一個(gè)接著一個(gè),有開(kāi)始有結(jié)束,每個(gè)組織、每個(gè)部門都能清清楚楚地看到,老板也是喜聞樂(lè)見(jiàn)。即便如此,還是有一點(diǎn)需要特別提醒,自動(dòng)化建設(shè)屬于戰(zhàn)略性的東西,講的是鐵打的營(yíng)盤,業(yè)務(wù)需求屬于戰(zhàn)術(shù),一般講怎么快速獲取更高的成功率。戰(zhàn)略是航母,戰(zhàn)術(shù)是航母上的戰(zhàn)斗機(jī),沒(méi)戰(zhàn)略也可以成功,有戰(zhàn)略能走更遠(yuǎn)。

????????做戰(zhàn)略性的事情就需要分清主次,在 80% 常用功能的范圍內(nèi)才需要考慮做自動(dòng)化,20% 的功能屬于臨時(shí)或者不規(guī)范的功能,即使做了自動(dòng)化也是徒增維護(hù)成本。要 100% 實(shí)現(xiàn)自動(dòng)化是不現(xiàn)實(shí)的,因?yàn)榇笠?guī)模自動(dòng)化建設(shè)是要花大成本的,特別是初期,考慮到投入和產(chǎn)出,我們不會(huì)把那些突發(fā)奇想的需求納入到建設(shè)進(jìn)程,一般是做備忘錄日后再說(shuō),我們的目標(biāo)是支持突發(fā)奇想但不全為突發(fā)奇想。如今市面上花花綠綠各種方案,開(kāi)源的,閉源的,一般都是需要精心挑選和自定義整合,最終也是半自研產(chǎn)品,沒(méi)有見(jiàn)過(guò)百分百吻合公司需求的方案,即使是買也是花錢等。

????????說(shuō)到大規(guī)模自動(dòng)化建設(shè)的目標(biāo)就不得不提契約,毫無(wú)契約的自動(dòng)化建設(shè)是盲目的,后果是失控和不堪重負(fù)。擴(kuò)展性和靈活性我們可以量力而為,想用不變應(yīng)萬(wàn)變是不存在的,約定高于配置、限制無(wú)節(jié)制的擴(kuò)展更像是我們想要的東西。我們從目前的樣子,預(yù)測(cè)未來(lái)大概會(huì)是個(gè)什么樣子,然后制定幾種約定好的模式,比如 Java 語(yǔ)言的工程用 Maven/Gradle 來(lái)管理,且構(gòu)建產(chǎn)物為一個(gè)可執(zhí)行的 jar 包,包名和工程名一致等等,只要任何 Java 工程都同時(shí)具備這幾個(gè)要素,就可以接入自動(dòng)化系統(tǒng),那些突發(fā)奇想的需求盡可能去靠近約定,一切都將變得很順利,這就是要求約定高于配置的原因之一。如果有人想突破約定,又能講明白為什么也是可以的,能講出個(gè)所以然,很大概率是我們需要升級(jí)一下自動(dòng)化系統(tǒng)。

技術(shù)和架構(gòu)約定高于配置

????????為了更好更規(guī)范的開(kāi)展工作,約定高于配置(大道至簡(jiǎn))一直是我們秉承的原則,這個(gè)原則也已經(jīng)在業(yè)界備受歡迎,特別是在構(gòu)建云原生應(yīng)用領(lǐng)域,比如“12-因子(Twelve-Factor)”規(guī)范不僅僅方便了開(kāi)發(fā),同時(shí)也方便了運(yùn)維。又比如 Ruby on Rails、Spring Boot、Seneca 等等框架,KISS(keep it simple and stupid),非常適合快速起步,同時(shí)也減輕了協(xié)作和維護(hù)成本,這是開(kāi)發(fā)側(cè)的例子,運(yùn)維側(cè)的比如 CI/CD 約定好流程怎么走,工程只要包含一個(gè)鉤子,從開(kāi)發(fā)到測(cè)試再到生產(chǎn)所有的環(huán)境就都已經(jīng)就緒,DevOps 般的默契,一切盡在不言中。還有監(jiān)控、機(jī)器人也是如此。他們的特點(diǎn)都是在約定的基礎(chǔ)上橫向擴(kuò)展毫無(wú)壓力。

????????約定高于配置原則縱向(深度)的表現(xiàn)有點(diǎn)獨(dú)裁,比如技術(shù)選型,往往是架構(gòu)師獨(dú)裁決定,當(dāng)然不是那種用屁股思考做決定,而是根據(jù)當(dāng)前實(shí)力做超前一點(diǎn)的決定,如果實(shí)力無(wú)法支撐,就實(shí)施備用計(jì)劃,有時(shí)是在最求完美的背后留一手,有時(shí)是在預(yù)防碎片化。

????????喜茶互聯(lián)網(wǎng)技術(shù)中心之所以選擇了 Spring Cloud 和 Kubernetes,一是約定高于配置,二是有實(shí)力支撐。

????????Spring Cloud 的約定高于配置是因?yàn)榛?Spring Boot,Kubernetes 的約定高于配置是因?yàn)閮?nèi)置了自動(dòng)化運(yùn)維。從實(shí)力上來(lái)講,Spring Cloud 開(kāi)發(fā)和普通的 Spring 開(kāi)發(fā)沒(méi)有本質(zhì)的區(qū)別,非常普遍;又我們有開(kāi)發(fā)同學(xué)曾做過(guò) Kubernetes 開(kāi)發(fā),對(duì)其工作原理非常熟悉,有什么功能我們可以直接使用,又有什么功能稍微打磨一下就可以變成金子,其中優(yōu)劣了如指掌,在 Spring Cloud 和 Kubernetes 的結(jié)合上有著豐富的實(shí)戰(zhàn)經(jīng)驗(yàn)。

????????選擇 Kubernetes 作為穩(wěn)定的自動(dòng)化運(yùn)維平臺(tái),依托云廠商,又不被鎖定在特定的云廠商上,自建也壓力不大,這是我們放心選擇 Kubernetes 的主要原因之一,其他比如語(yǔ)言無(wú)關(guān)的微服務(wù)平臺(tái)、潮流等等都不是我們目前重點(diǎn)考慮的因素。我們是做應(yīng)用和應(yīng)用平臺(tái),不是做運(yùn)行平臺(tái),因此,“語(yǔ)言無(wú)關(guān)的微服務(wù)平臺(tái)”其實(shí)并沒(méi)有“語(yǔ)言無(wú)關(guān)的微服務(wù)協(xié)議”來(lái)的誘人,從技術(shù)角度上講,HTTP 差不多算是“語(yǔ)言無(wú)關(guān)的協(xié)議”,其他的像 gPRC、Dubbo 協(xié)議,也都很好,就是感覺(jué)有點(diǎn)兒“語(yǔ)言有關(guān)”。

????????選擇 Spring Cloud 的原因很顯然是因?yàn)?Spring 的前景和社區(qū)支持,另外就是她提供了一整套的解決方案并且非常的開(kāi)放,最后就是她使用的是 HTTP 協(xié)議。前面兩點(diǎn)無(wú)需解釋,最后一點(diǎn)主要還是考慮到未來(lái)我們的系統(tǒng)大體上是 Spring Cloud 應(yīng)用為主,其他語(yǔ)言的應(yīng)用為輔的混合模式,HTTP 相比 gPRC、Dubbo 等協(xié)議性能差個(gè) 2-3 倍也無(wú)妨,目前橫向擴(kuò)展足夠彌補(bǔ) HTTP 協(xié)議性能稍差的缺陷,未來(lái)要不要整改也就是投入和產(chǎn)出的問(wèn)題,架構(gòu)都是需要演化的,前期追求的是易用性、完整性和擴(kuò)展性,后期考慮性能優(yōu)化,再者,都用微服務(wù)架構(gòu)了,局部替換技術(shù)對(duì)整體的影響并不大,又得益于 Spring 一貫以來(lái)良好的設(shè)計(jì)抽象,技術(shù)也已經(jīng)證明可行。

????????有人說(shuō),有了 Kubernetes 就可以不用 Spring Cloud 那一套了!我個(gè)人認(rèn)為不必這么武斷。顯然他們兩者各有所長(zhǎng),如果可以做到揚(yáng)長(zhǎng)避短倒是順勢(shì),如服務(wù)注冊(cè)和發(fā)現(xiàn)、配置、負(fù)載、遠(yuǎn)程調(diào)用的選擇等等,Kubernetes 固然是和語(yǔ)言無(wú)關(guān)的微服務(wù)架構(gòu),當(dāng)我們的系統(tǒng)同時(shí)存在多種異構(gòu)語(yǔ)言的服務(wù)時(shí),這點(diǎn)相對(duì) Spring Cloud 是個(gè)優(yōu)勢(shì)但不明顯。有人說(shuō),Spring Cloud 的微服務(wù)架構(gòu)模式是強(qiáng)耦合,仔細(xì)考察確實(shí)有那么一點(diǎn),不過(guò)除了 Service Mesh 那種 Sidecar 模式,似乎沒(méi)有不耦合的編程模式,使用了 HTTP 協(xié)議后也并非真的那么耦合。另外一點(diǎn)就是,在需要做微調(diào)的時(shí)候我們更加傾向于代碼控制,而不是去做各種 Kubernetes ops 方面的操作,比如細(xì)粒度的灰度發(fā)布、細(xì)微的負(fù)載調(diào)整等等,所以,完全只用兩者中的一個(gè)都會(huì)顯得不那么完美。限于篇幅這里就先不展開(kāi)兩者之間的異同點(diǎn),以后有機(jī)會(huì)再寫(xiě)一篇文章來(lái)詳細(xì)簡(jiǎn)介 Spring Cloud 和 Kubernetes 在生產(chǎn)上的互補(bǔ)和相輔相成。這里只想明確一點(diǎn):選 Kubernetes 是看中了她的自動(dòng)運(yùn)維,選 Spring Cloud 是看中了她提供了一整套微服務(wù)解決方案并且非常開(kāi)放,前者大范圍取代了運(yùn)維的人工操作,后者大規(guī)模的簡(jiǎn)化了架構(gòu)工作,兩者的結(jié)合,在目前看來(lái)是一組最優(yōu)解。

????????坦白講,我們的“技術(shù)和架構(gòu)約定高于配置”始于技術(shù)選型服務(wù)于技術(shù)選型,歸根到底還是看業(yè)務(wù)需求。為了形成可靠的交付節(jié)奏,在遵守每項(xiàng)技術(shù)的最佳實(shí)踐中,制定了自己的最佳實(shí)踐。我們把指導(dǎo)構(gòu)建云原生應(yīng)用的 Twelve-Factor 應(yīng)用于實(shí)踐中,但也杜絕本本主義,比如:早期日志系統(tǒng)沒(méi)有穩(wěn)定,我們的日志并非只輸出到控制臺(tái),同時(shí)也文件存儲(chǔ),當(dāng)某一天日志系統(tǒng)穩(wěn)定了,環(huán)境變量切換一下即可,顯然這種權(quán)衡狀態(tài)下,開(kāi)發(fā)關(guān)心了日志收集,分擔(dān)了運(yùn)維的一點(diǎn)工作,避免了日志丟失,但也只是短暫的。

總結(jié)和展望

????????云原生應(yīng)用的落地涉及的技術(shù)和文化是方方面面的,這篇文章描述的內(nèi)容只是指導(dǎo)原則中的三個(gè)大方面,點(diǎn)到為止,具體技術(shù)細(xì)節(jié)和實(shí)操過(guò)程只能在后續(xù)文章中再大篇幅展開(kāi)。

????????總之,喜茶云原生應(yīng)用的構(gòu)建以及 DevOps 文化的普及是在為業(yè)務(wù)快速發(fā)展布道,云化和自動(dòng)化是為了節(jié)省更多的成本。經(jīng)過(guò)過(guò)去一年的鋪墊,我們?cè)谖磥?lái)的一年里將開(kāi)始展開(kāi)多集群、多中心、跨區(qū)域,還有中間件的開(kāi)發(fā)工作,最終要實(shí)現(xiàn)的目標(biāo)是隨喜茶出國(guó)而全球化。

-- 2019.10.04 完

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容