您好,登錄后才能下訂單哦!
為什么需要ServiceMesh
UCloud App Engine on Kubernetes(后簡稱“UAEK”)是UCloud內(nèi)部打造的一個基于Kubernetes的,具備高可用、跨機房容災、自動伸縮、立體監(jiān)控、日志搜集和簡便運維等特性計算資源交付平臺,旨在利用容器技術提高內(nèi)部研發(fā)運維效率,讓開發(fā)能將更多的精力投入在業(yè)務研發(fā)本身,同時,讓運維能更從容應對資源伸縮、灰度發(fā)布、版本更迭、監(jiān)控告警等日常工作。
考慮到Kubernetes本來就是為自動部署、伸縮和容器化而生,再加上UCloud UAEK團隊完成IPv6組網(wǎng)調(diào)研和設計實現(xiàn)后,一個成熟的容器管理平臺很快正式在北京二地域的多個可用區(qū)上線了。相比于過去申請管理虛擬機部署應用服務,Kubernetes確實帶來了實實在在的便利,例如方便靈活的自動伸縮以及×××的微服務架構,只需簡單配置即可實現(xiàn)跨可用區(qū)容災等。
然而,微服務化又為系統(tǒng)架構帶來許多新的問題,例如服務發(fā)現(xiàn)、監(jiān)控、灰度控制、過載保護、請求調(diào)用追蹤等。大家已經(jīng)習慣自行運維一組Zookeeper集群用以實現(xiàn)服務發(fā)現(xiàn)和客戶端負載均衡,使用UAEK后能否免去運維Zookeeper的工作?為了監(jiān)控業(yè)務運行狀態(tài),大家都需要在代碼里加上旁路上報邏輯,使用UAEK是否能無侵入零耦合地實現(xiàn)監(jiān)控上報?
此外,過去很多系統(tǒng)模塊間調(diào)用缺少熔斷保護策略,波峰流量一打就癱,使用UAEK是否能幫助業(yè)務方免去大規(guī)模改造呢?過去排查問題,尤其是調(diào)用耗時環(huán)節(jié)排查總是費時費力,使用UAEK能否為定位瓶頸提供方便的工具?
顯然,僅憑一個穩(wěn)定的Kubernetes平臺不足以解決這些問題。因此,在UAEK立項之初,團隊就把ServiceMesh作為一個必須實現(xiàn)的目標,任何在UAEK上部署的TCP后臺服務,都能享受到ServiceMesh帶來的這些特性:
SideCar模式部署,零侵入,微服務治理代碼與業(yè)務代碼完全解耦;
與Kubernetes平臺融合的服務發(fā)現(xiàn)機制和負載均衡調(diào)度;
提供靈活,實時,無需重啟、能根據(jù)7層業(yè)務信息進行流量灰度管理功能;
提供統(tǒng)一抽象數(shù)據(jù)上報API層,用于實現(xiàn)監(jiān)控和訪問策略控制;
使用分布式請求鏈路追蹤系統(tǒng),快速追溯Bug,定位系統(tǒng)性能瓶頸;
過載保護機制,能在請求量超過系統(tǒng)設計容量時自動觸發(fā)熔斷;
能在服務上線前提供故障模擬注入演習劇本,提前進行故障處理演練;
這樣,使用UAEK部署應用服務后,即可從小范圍按賬號灰度上線開始,通過陸續(xù)地監(jiān)控觀察,輕松掌握版本異?;赝?、擴大灰度范圍、全量發(fā)布、過載保護、異常請求定位追蹤等信息。
為什么是Istio?
關于ServiceMesh的實現(xiàn),我們重點考察了Istio。通過前期的調(diào)研和測試,我們發(fā)現(xiàn)Istio的幾個特性能很好滿足UAEK的需求:
完美支持Kubernetes平臺;
控制面和數(shù)據(jù)轉(zhuǎn)發(fā)面分離;
Sidecar部署,掌控所有服務間調(diào)用流量,無上限的控制力;
使用Envoy作為Sidecar實現(xiàn),Envoy使用C++11開發(fā),基于事件驅(qū)動和多線程機制運行,性能好并發(fā)能力強,媲美NGINX;
對業(yè)務的代碼和配置文件零侵入;
配置簡單,操作方便,API完善。
cdn.xitu.io/2018/8/23/16565d6f6dfeaed9?w=646&h=507&f=png&s=55105">
整個服務網(wǎng)格分成控制面板和數(shù)據(jù)面兩大部分。數(shù)據(jù)面指的就是注入到應用Pod中的Envoy容器,它負責代理調(diào)度模塊間的所有流量。控制面分為Pilot,Mixer和Citadel三大模塊,具體功能如下:
Pilot負責向Kubernetes API獲取并Watch整個集群的服務發(fā)現(xiàn)信息,并向Envoy下發(fā)集群服務發(fā)現(xiàn)信息和用戶定制的路由規(guī)則策略。
Mixer分為Policy和Telemetry兩個子模塊。Policy用于向Envoy提供準入策略控制,黑白名單控制,QPS流速控制服務;Telemetry為Envoy提供了數(shù)據(jù)上報和日志搜集服務,以用于監(jiān)控告警和日志查詢。
Citadel為服務和用戶提供認證和鑒權、管理憑據(jù)和 RBAC。
此外Istio為運維人員提供了一個叫istioctl的命令行工具,類似kubernetes的kubectl。運維編寫好路由規(guī)則yaml文件后,使用istioctl即可向集群提交路由規(guī)則。
Istio整體工作的原理和流程細節(jié)非常復雜,所涉及到的技術棧有一定的深度和廣度。這里只概括一下大體過程:
運維人員使用istioctl或者調(diào)用API向控制層創(chuàng)建修改路由規(guī)則策略。
Pilot向Kube APIServer獲取并watch集群服務發(fā)現(xiàn)信息。
部署應用程序時,Istio會在pod的部署配置中注入Envoy容器,Envoy會通過iptables nat redirect劫持代理pod中的全部TCP流量。
Envoy會實時從Pilot更新集群的服務發(fā)現(xiàn)信息和路由規(guī)則策略,并根據(jù)這些信息智能調(diào)度集群內(nèi)的流量。
Envoy會在每次請求發(fā)送前向Mixer Policy發(fā)送Check請求檢查該請求是否收策略限制或者配額限制,每次請求接收后會向Mixer Telemetry上報本次請求的基本信息,如調(diào)用是否成功、返回狀態(tài)碼、耗時數(shù)據(jù)。
Citadel實現(xiàn)了雙向TLS客戶端證書生成與注入,服務端密鑰和證書的下發(fā)注入,以及K8S RBAC訪問控制。
Istio在UAEK環(huán)境下的改造之路
經(jīng)過上述的調(diào)研和與一系列測試,UAEK團隊充分認可Istio的設計理念和潛在價值,希望通過利用Istio豐富強大的微服務治理功能吸引更多的內(nèi)部團隊將服務遷移到UAEK環(huán)境中。
然而,事實上,在UAEK上接入Istio的過程并非一帆風順。最早開始調(diào)研Istio的時候,Istio還在0.6版本,功能并不完善,在UAEK環(huán)境中無法開箱即用。
IPv6問題的解決
我們首先碰到的問題是,UAEK是一個純IPv6網(wǎng)絡環(huán)境,而Istio對IPv6流量的支持并不完備,部分組件甚至無法在IPv6環(huán)境下部署。
在介紹具體改造案例之前,先了解下Istio Sidecar是如何接管業(yè)務程序的流量。
如上圖所描述,Istio會向應用Pod注入兩個容器:proxy-init容器和envoy容器。proxy-init容器通過初始化iptables設置,將所有的TCP層流量通過nat redirect重定向到Envoy監(jiān)聽的15001端口。以入流量為例,Envoy的服務端口接收到被重定向到來的TCP連接后,通過getsocketopt(2)系統(tǒng)調(diào)用,使用SO_ORIGINAL_DST參數(shù)找到該TCP連接的真實目的地IP地址,并將該請求轉(zhuǎn)發(fā)到真實目的IP。
然而,我們發(fā)現(xiàn)在IPv6環(huán)境下,Envoy無法劫持Pod的流量。通過抓包觀察和追溯源碼發(fā)現(xiàn),Pod啟動的時候,首先會運行一個iptables初始化腳本,完成pod內(nèi)的nat redirect配置,將容器內(nèi)的TCP出入流量都劫持到Envoy的監(jiān)聽端口中,但這個初始化腳本沒有ip6tables的對應操作并且discard了所有IPv6流量,因此我們修改了初始化腳本,實現(xiàn)了IPv6的流量劫持。
一波剛平,一波又起。完成IPv6流量劫持后, 我們發(fā)現(xiàn)所有訪問業(yè)務服務端口的TCP流量都被Envoy重置,進入Envoy容器中發(fā)現(xiàn)15001端口并沒有開啟。追溯Envoy和Pilot源碼發(fā)現(xiàn),Pilot給Envoy下發(fā)的listen地址為0:0:0:0:15001, 這是個IPv4地址,我們需要Envoy監(jiān)聽地址的為[::0]:15000,于是繼續(xù)修改Pilot源碼。
經(jīng)過上述努力,應用服務端程序Pod終于能成功Accept我們發(fā)起的TCP連接。但很快,我們的請求連接就被服務端關閉,客戶端剛連接上就立刻收到TCP FIN分節(jié),請求依然失敗。通過觀察Envoy的運行日志,發(fā)現(xiàn)Envoy接收了TCP請求后,無法找到對應的4層流量過濾器(Filter)。
深入跟進源碼發(fā)現(xiàn),Envoy需要通過getsocketopt(2)系統(tǒng)調(diào)用獲取被劫持的訪問請求的真實目的地址, 但在IPv6環(huán)境下Envoy相關的實現(xiàn)存在bug,如下代碼所示。由于缺少判定socket fd的類型, getsocketopt(2)傳入的參數(shù)是IPv4環(huán)境下的參數(shù),因此Envoy無法找到請求的真實目的地址,遂報錯并立刻關閉了客戶端連接。
發(fā)現(xiàn)問題后,UAEK團隊立刻修改Envoy源碼,完善了getsocketopt(2) 的SO_ORIGINAL_DST選項的IPv6兼容性,然后將這一修改提交到Envoy開源社區(qū),隨后被社區(qū)合并到當前的Master分支中,并在Istio1.0的Envoy鏡像中得到更新使用。
到此為止,Istio SideCar終于能在UAEK IPv6環(huán)境下正常調(diào)度服務間的訪問流量了。
此外,我們還發(fā)現(xiàn)Pilot、Mixer等模塊在處理IPv6格式地址時出現(xiàn)數(shù)組越界、程序崩潰的情況,并逐一修復之。
性能評估
Istio1.0發(fā)布之前,性能問題一直是業(yè)界詬病的焦點。我們首先考察了增加了Envoy后,流量多了一層復制,并且請求發(fā)起前需要向Mixer Policy進行一次Check請求,這些因素是否會對業(yè)務產(chǎn)生不可接收的延遲。經(jīng)過大量測試,我們發(fā)現(xiàn)在UAEK環(huán)境下會比不使用Istio時增加5ms左右的延遲,對內(nèi)部大部分服務來說,這完全可以接受。
隨后,我們重點考察了整個Istio Mesh的架構,分析下來結論是,Mixer Policy和Mixer Telemetry很容易成為整個集群的性能短板。由于Envoy發(fā)起每個請求前都需要對Policy服務進行Check請求,一方面增加了業(yè)務請求本身的延遲,一方面也給作為單點的Policy增大了負載壓力。我們以Http1.1請求作為樣本測試,發(fā)現(xiàn)當整個網(wǎng)格QPS達到2000-3000的時候,Policy就會出現(xiàn)嚴重的負載瓶頸,導致所有的Check請求耗時顯著增大,由正常情況下的2-3ms增大到100-150ms,嚴重加劇了所有業(yè)務請求的耗時延遲,這個結果顯然是不可接受的。
更嚴重的是,在Istio 0.8以及之前的版本,Policy是一個有狀態(tài)的服務。一些功能,如全局的QPS Ratelimit配額控制,需要Policy單個進程記錄整個Mesh的實時數(shù)據(jù),這意味著Policy服務無法通過橫向擴容實例來解決性能瓶頸。經(jīng)過取舍權衡,我們目前關閉了Policy服務并裁剪了一些功能,比如QPS全局配額限制。
前面提到過,Mixer Telemetry主要負責向Envoy收集每次請求的調(diào)用情況。0.8版本的Mixer Telemetry也存在嚴重的性能問題。壓測中發(fā)現(xiàn),當集群QPS達到2000以上時,Telemetry實例的內(nèi)存使用率會一路狂漲。
經(jīng)過分析定位,發(fā)現(xiàn)Telemetry內(nèi)存上漲的原因是數(shù)據(jù)通過各種后端Adapter消費的速率無法跟上Envoy上報的速率, 導致未被Adapter處理的數(shù)據(jù)快速積壓在內(nèi)存中。我們隨即去除了Istio自帶的并不實用的stdio日志搜集功能,這一問題隨即得到極大緩解。幸運的是,隨著Istio1.0的發(fā)布,Telemetry的內(nèi)存數(shù)據(jù)積壓問題得到解決,在相同的測試條件下,單個Telemetry實例至少能勝任3.5W QPS情況下的數(shù)據(jù)搜集上報。
問題、希望與未來
歷經(jīng)重重問題,一路走來,一個生產(chǎn)環(huán)境可用的ServiceMesh終于在UAEK環(huán)境上線了。在這一過程中,也有部門內(nèi)其他團隊受UAEK團隊影響,開始學習Istio的理念并嘗試在項目中使用Istio。然而,目前的現(xiàn)狀離我們的初心依然存在差距。
Istio依然在高速迭代中,無論是Istio本身還是Envoy Proxy,每天都在演進更新。每一次版本更新,帶來的都是更為強大的功能,更為簡練的API定義,同時也帶來了更復雜的部署架構。從0.7.1到0.8,全新的路由規(guī)則v1alpha3與之前的API完全不兼容,新的virtualservice與原先的routerule截然不同,給每位使用者構成了不少麻煩。
如何完全避免升級Istio給現(xiàn)網(wǎng)帶來負影響,官方依然沒有給出完美平滑的升級方案。此外,從0.8到1.0雖然各個組件的性能表現(xiàn)有顯著提升,但從業(yè)內(nèi)反饋來看,并沒令所有人滿意,Mixer的Check緩存機制究竟能多大程度緩解Policy的性能壓力依然需要觀察。
值得一提的是,我們發(fā)現(xiàn)的不少bug同時也在被社區(qū)其他開發(fā)者發(fā)現(xiàn)并逐一解決。令我們開心的是,UAEK團隊不是信息孤島,我們能感受到Istio官方社區(qū)正在努力高速迭代,始終在致力于解決廣大開發(fā)者關心的種種問題,我們提交的issue能在數(shù)小時內(nèi)被響應,這些,都讓我們堅信,Istio是一個有潛力的項目,會向Kubernetes一樣走向成功。
從UAEK接入用戶的經(jīng)驗來看,用戶需要正確地使用好Istio離不開前期深入的Istio文檔學習。UAEK后續(xù)需致力于要簡化這一過程,讓用戶能傻瓜化、界面化、隨心所欲地定制自己的路由規(guī)則成為我們下一個愿景。
UAEK團隊始終致力于改革UCloud內(nèi)部研發(fā)流程,讓研發(fā)提升效率,讓運維不再苦惱,讓所有人開心工作。除了繼續(xù)完善ServiceMesh功能,下半年UAEK還會開放更多的地域和可用區(qū),提供功能更豐富的控制臺,發(fā)布自動化的代碼管理打包持續(xù)集成(CI/CD)特性等等,敬請期待!
作者介紹
陳綏,UCloud資深研發(fā)工程師,先后負責監(jiān)控系統(tǒng)、Serverless產(chǎn)品、PaaS平臺ServiceMesh等開發(fā),有豐富的分布式系統(tǒng)開發(fā)經(jīng)驗。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。