歡迎光臨
每天分享高質量文章

58集團雲平臺架構實踐與演進

 

在17年底,我們分享了《高可用Docker容器雲在58集團的實踐》這篇文章,對整個容器雲基礎環境搭建與應用選型進行了詳細介紹,本文是在該文章基礎之上的進階篇,是針對具體業務場景的落地解決方案。如果對基礎環境選型比較感興趣,可以查看上篇文章,在本文的最後會附上相關文章的鏈接。對於上篇文章討論過的內容,本文將不再進行詳細討論。後續每個月,雲團隊都會選擇平臺中某一具體領域的相關工作進行詳細討論與分享,歡迎大家關註。大家想瞭解哪方面的實現方案與細節,可進行相應留言。

 

背景

 

通過容器化技術,58雲計算平臺主要解決以下幾個問題:
  1. 資源利用率低:通過雲化技術可以將資源利用率提升至原有的3-4倍,甚至更高。

  2. 服務擴容效率低:將傳統擴容的時間從小時級別降低為分鐘級別。

  3. 上線流程不規範:基於同一的鏡像模板,約束整個上線過程。

為瞭解決上述問題,雲團隊通過技術選型與反覆論證最終決定基於Docker與Kubernetes體系構建整個容器雲環境。
雲計算平臺的發展歷程如下:

 

整體架構

 

58雲計算平臺的整體架構如下:

所有容器雲的架構都是相似的,這裡不做贅述,具體可查看上篇文章。
雲計算平臺承載了集團90%以上的業務流量,作為核心的服務管理與上線系統,它並不是獨立運作的,為了保證整個上線流程的一致性與流暢度,滿足業務日常管理與維護的通用需求,雲平臺與集團內部多個核心系統與組件進行了相應的對接與聯動。

在專案管理方面,雲平臺與代碼管理系統、專案管理等系統進行了內部對接,實現了代碼從編譯到生成鏡像,再到環境部署的完全自動化。
在運維方面,雲平臺與CMDB、服務樹、監控系統等多個運維繫統進行了打通與整合,保證整個運維體系的完整性與用戶體驗的一致性。
在基礎組件方面,集團內部的服務治理體系與常用的中間件系統都針對雲平臺進行了相應的改造,以適配雲平臺的工作樣式,同時雲平臺也集成了現有的資料收集組件,保證資料流與用戶習慣在雲化前後是一致的。
雲平臺的使用方面,平臺定義了四套環境,四套環境基於唯一的鏡像倉庫,這使得同一個代碼版本可以在不同的環境之間進行流轉,在保證代碼唯一性的同時也使得相關環境的變更不會傳遞到下一個環境。

 

架構演進

 

構建一個適配多種業務場景的容器雲有很多細節需要考慮,雲團隊做了很多工作,由於篇幅關係,這裡主要和大家分享58雲計算平臺在“網絡架構”和“服務發現”兩個核心組件上的架構實踐與演進。
網絡架構
在網絡架構方面,通過對比常用的六種容器組網模型,雲計算平臺選擇“bridge+vlan”的方式作為基礎網絡模型。

原生bridge網絡模型存在兩個明顯的缺點:IP利用率低、缺少網絡限速。
為瞭解決IP地址利用率低的問題,雲平臺基於docker的CNM接口開發了網絡插件,支持多個宿主間共享同一個容器網段,也支持IP地址在不同的宿主間復用。

這種網絡樣式下,分配給業務實體的IP地址是隨機的,實體每次重啟IP地址都可能會發生變更。在推進業務雲化的早期,這種樣式被業務所接受,但是隨著雲化行程的不斷深入,業務方面提出了更高的要求:固定IP。
業務需求來源於真實的案例:有些服務要求IP不能發生變化,特別是某些依賴於第三方外部接口的服務。同時集團內部很多系統都是以IP固定為前提,如果IP隨機分配,這些現有系統將不可用或很難用,極大的影響用戶體驗。如果IP固定的需求不能被滿足,業務雲化將很難推進下去。所以在18年4月份,雲平臺對網絡架構進行了升級,支持了固定IP樣式。網絡架構的升級很好的保證了業務雲化的行程。

固定IP的網絡架構基於Kubernetes的CNI接口實現,增加了IP控制器模塊,業務每次擴縮容時,都會與IP控制器交互,進行IP的變更。在業務正常升級流程中,歸屬於業務的IP將不會發生變化。依托於騰訊機房的網絡支撐,平臺將容器網段的路由規則下發到交換機,實現了容器的全網漂移,而不僅僅局限於固定的交換機。(如果你想深入快速學習Kubernetes,可以報名參加我們組織的為期3天的Kubernetes實戰培訓,一線資深講師帶你從0開始上手Kubernetes。)
針對網絡限速的需求,雲平臺結合容器網絡虛擬化的特性,基於自研監控與tc工具實現了容器網絡限速的能力。

標準的tc工具只支持單向限速,即出口流量限速。單方向限速無法滿足業務的實際需求。在深入研究容器網絡虛擬化的原理後,我們發現,容器在做虛擬化時,會創建一個網卡對,他們是對等的網絡設備,在宿主機上體現為veth,在容器內部體現為eth0。基於這個特性,我們實現了雙向限速:即對兩塊網卡同時做出口流量限速。由於是對等網卡,所以對veth做出口流量限速就相當於對eth0做入口流量限速。
在網絡限速的基礎上,雲平臺又進行了多維度的完善,分別支持動態限速、秒級限速與彈性限速等網絡應用場景,極大的實現帶寬復用。
服務發現
服務發現是容器雲平臺中非常核心的服務組件,是流量的入口,也是服務對外暴露的接口。雲平臺中IP動態分配,節點彈性伸縮,需要有一套自動變更負載均衡器的方式。對於後端服務,集團有成熟的服務治理框架與體系,在雲化過程中,中間件團隊對服務治理體系進行了改造使其可以適配不斷變化的雲環境。對於前端服務,集團是基於Nginx做負載均衡,並且沒有一套支持IP自動變更的架構。為了實現前端服務的雲化,雲平臺團隊與運維團隊共同設計了全新的服務發現架構。
在調研階段,雲團隊也調研了Kubernetes自帶的服務發現機制,這一機制無法提供複雜的負載均衡策略,並且無法滿足業務在特殊場景下需要對部分節點摘除流量的需求,所以最終我們否定了這一方案。

這是業界典型的服務發現架構。服務端和負載均衡器通過Consul進行解耦。服務註冊在Consul中,負載均衡器通過Watch Consul中目錄的變化來實時感知節點變更。在雲化的早期,為了滿足快速上線的需求,雲平臺對集團內部的Java Web框架進行了修改,使得其以心跳的方式自動註冊到Consul中。這很好的解決了負載均衡器自動感知業務變更的問題以及雲化過程中的流量灰度問題。
這一架構也引入了新的問題:除錯問題與多語言擴展問題。由於是Java框架代理業務註冊到Consul中,這使得活躍節點無法被下掉流量從而進行除錯,但實際場景中很多故障除錯需要下掉流量後才能進行。對Java語言的支持是通過修改框架來完成的,而集團中還有很多其他型別語言,比如PHP、Node.js和Go等。對每種接入語言或框架都需要以修改代碼的方式才能接入到雲平臺中來,開發成本高並且對業務不友好。Consul被直接暴露給服務方,也增加了Consul的安全風險。
基於此,在18年4月,雲平臺對整個服務發現架構進行了升級。

新的服務發現架構中,業務與Consul中間增加了Proxy代理層,代理層通過Watch Kubernetes事件實時感知業務節點信息的變化,配合健康檢查功能可以保證業務節點在變更時流量無損。基於代理層,任意語言的程式不需要做任何修改,僅通過簡單配置即可接入到雲平臺。服務的註冊與發現托管到雲平臺,Consul組件對業務透明,開發人員使用更友好。

 

復盤與反思

 

回顧這兩年來的容器雲架構演進過程與業務雲化歷程,復盤遇到的棘手問題及其解決方案,與大家共同探討。
在整個雲平臺的設計之初,我們有如下的設計考量:

容器雲都會面臨一個問題:對於業務來說,是容器還是虛擬機?虛擬機是業務習慣的使用樣式,業務更容易接受。容器是以服務為核心,服務存在即存在,服務關閉即銷毀,不再是虛擬機以機器為核心的樣式。思慮再三,最終決定以容器的樣式來定位,全新的平臺提供全新的服務樣式與體驗。
雖然是以容器為核心,但容器中可運行單行程也可運行多行程。我們規範容器中只運行一個業務行程,防止由於運行多行程而導致業務之間相互干擾情況的發生,這類問題很難進行排查與定位。
去Agent化:在傳統物理機樣式下,一臺物理機上可能會有多個Agent:運維管控Agent、監控Agent、業務自定義Agent等。雲化後面臨一個現實的問題:我們需要在每個容器中都安裝這些Agent麽?如果每個容器中都集成這些Agent,對雲平臺來說是簡單的,這沒有任何工作量。但是一臺物理機上可能會運行上百個容器,這些Agent數量也會大量膨脹,帶來系統負載的增加的問題。基於此,雲平臺投入大量的精力來實現容器的無Agent化,即在所有功能正常運行的前提下,Agent只運行在宿主上,不會運行在容器中。
業務雲化過程中雲團隊遇到了很多問題案例,並形成自己獨特的解決方案。這裡選擇了幾個有代表性的案例,與大家進行分享。

服務啟動耗CPU過高是雲化早期時遇到的棘手問題。這個問題產生的原因很多:Java的語言特性導致JVM是在運行中逐步進行優化的;內部的很多開發框架都是在流量過來時才初始化鏈接;某些業務資源也是在流量過來時才進行初始化。當流量分發過來時,多種資源同時初始化導致服務需要大量的CPU資源,超過了平臺為其分配的CPU配額,服務出現大量超時與拋棄。這一問題的簡單解法是多分配CPU資源,但從長遠角度來看這會導致資源利用無法有效把控,也會影響彈性調度的效果。最終,我們從兩個維度解決這一問題:在呼叫方增加預熱策略,流量逐步分發過來,CPU資源使用更平滑;在服務方增加預熱方法,預設初始化鏈接等資源,同時引導用戶進行自定義的初始化。
在容器監控維度方面,由於預設的監控資料是基於隨機採樣的分鐘級資料,導致當服務出現短期秒級的CPU波動時,監控系統無法捕獲,從而影響問題的排查與定位。針對這一問題,雲平臺對監控維度進行了深化,增加了容器級別秒級監控,實時採集每分鐘的最大值上報,便於問題的排查與跟蹤。

由於Cgroups只對CPU和記憶體資源進行了隔離與限速,並沒有對系統負載進行隔離,如果容器中運行行程或執行緒數過多,會導致宿主機整體的負載波動,進而對上面的所有服務都會造成影響。
雲平臺增加了兩個維度的控制策略:容器級別的最大執行緒數控制,防止由於單個容器執行緒數過多會對宿主造成影響。宿主級別的過載保護,當宿主上的負載過高時,過載保護策略會自動觸發宿主上的容器進行漂移,直至負載降至合理的範圍。
雲平臺必須關閉swap交換分割槽,這是一個深刻的經驗教訓。在雲化的早期,雲平臺的交換分割槽沒有關閉,部分服務經常出現由於使用交換分割槽而導致的耗時隨機抖動,這類問題很難排查,耗費了大量的精力。
58雲計算平臺核心軟體版本變遷過程如下:

 

後記

 

容器雲在58集團的實踐與探索過程中,雲團隊做了很多技術選型與優化工作,也進行了很多技術方案的架構演進工作,究其根本原因是58集團是發展了十多年的互聯網公司,它有自己獨特的業務場景和成熟的開發體系與基礎組件,容器雲在集團內部起步較晚,內部系統很難為雲平臺做適配,只能雲平臺通過不斷演進來適配不停發展的業務場景。這也是在較有規模的互聯網公司做基礎架構與創業公司的區別和挑戰所在。所幸在團隊的共同努力下,我們用1年多的時間完成了集團流量服務的雲化工作。目前,集團內部還有很多服務需要雲化,未來的挑戰更大。
作者:姚遠,58集團雲計算平臺技術負責人,架構師;多年互聯網開發和架構經驗,長期從事並關註服務高併發與高性能等方面工作,在58集團先後負責過訊息總線、呼叫鏈跟蹤系統等中間件系統的設計與架構工作;當前主要負責雲計算平臺的架構與設計、推進業務雲化等工作。
赞(0)

分享創造快樂