摘要: Service Mesher Meetup 上海站演講內容整理。
小螞蟻說:git
本文是基於在 Service Mesher Meetup 上海站的主題分享《螞蟻金服 Service Mesh 漸進式遷移方案》內容整理,完整的分享 PPT 獲取方式見文章底部。github
敖小劍,螞蟻金服高級技術專家,十六年軟件開發經驗,微服務專家,Service Mesh 佈道師,Servicemesher 社區聯合創始人;龍軾,阿里巴巴技術專家、前京東 Hadoop 負責人、Hadoop 代碼貢獻者、現負責UC 基於 Kubernetes 自研的 PaaS 平臺總體的穩定性。編程
你們好,今天給你們帶來的演講主題是《螞蟻金服 Service Mesh 漸進式遷移方案》,給你們介紹一下咱們螞蟻金服主站的 Service Mesh 遷移方案,在稍後的內容中我會給你們解釋什麼是「漸進式」。今天的演講方式有些特殊,將會是兩位講師合做。我是敖小劍,來自螞蟻金服中間件團隊,另一位講師 龍軾 ,來自 UC 基礎研發部。json
今天的內容將會有四塊主要內容:後端
前兩塊內容將由我來爲你們介紹,後兩塊內容將由個人同事 龍軾 爲你們介紹。api
在展開內容以前,先看一下背景,Service Mesh在螞蟻金服主站落地的背景:緩存
今天演講的內容,要給你們介紹的就是,在這樣的背景下,咱們螞蟻金服選擇的Service Mesh主站落地演進方案。這個方案預期會在2019年初全面鋪開。安全
主站落地方案的實施原則,這是咱們在過去半年的實踐中,總結概括出來的行爲指導:服務器
在接下來的演進路線中,你們將會體會到這三個原則在實際落地時的指導做用。網絡
這個圖的信息量有點大,描述的是 Service Mesh 和 k8s 落地可能的多種演進路線。
咱們先從最下面開始看,這是當前螞蟻金服主站大多數應用的現狀:即應用"部署在非k8s上",應用也"不是Service Mesh形態"。 而後看最上面,這是咱們指望的螞蟻金服主站將來的應用終極形態:應用"部署在k8s上",應用也遷移到了"Service Mesh形態"。
這裏有個特別的地方,咱們將Service Mesh形態細分爲兩種模式:
之因此將Service Mesh形態細分,是由於咱們有着這樣一個特殊背景:目前的原生Istio沒法支撐咱們螞蟻金服的規模,所以在改進完善Istio以前,咱們不得不暫時在Sidecar模式下短暫停留。另一個緣由就是考慮到存量應用的遷移,多一個Sidecar模式做爲中間緩衝,會讓整個遷移過程平滑不少。
如今咱們來介紹圖中展現的四條演進路線:
下面咱們來詳細分析各條演進路線的優劣和實施條件。
演進路線2,和路線1的核心差異,在於:是先上k8s,仍是先上Service Mesh。並且路線2是在非k8s條件下一路演進Service Mesh到咱們指望的終極形態Istio模式,這意味着過程當中和最終目標有很是大的偏移。
演進路線2的好處,在於第一步很是的天然:
所以,路線2特別容易落地,能夠快速達成短時間目標,直接拿到Service Mesh的部分成利,如:多語言支持,方便類庫升級等。
可是,這個路線的問題在於再日後走,開始完善Service Mesh的功能以向Istio模式靠攏時,因爲沒有k8s的底層支持,所以不得不作大量的工做來提供類k8s的功能。尤爲是Istio的非k8s支持,官方方案基本上只是一個demo,徹底不具有生產可用性,要完善好,工做量很大。而關鍵點在於,這些投入,在遷移到k8s時,又由於和k8s提供的功能重複而被放棄。
所以,結合咱們前面的原則(符合遠期規劃,不浪費投資),路線2對螞蟻金服主站落地是不合適的。
演進路線4是一個很是特殊的路線,能夠理解爲路線1(先上k8s再上Service Mesh)的短時間妥協版本。由於路線1的前提條件是要先大規模鋪開k8s,將現有應用遷移到k8s以後再繼續往Service Mesh演進,這對於尚未普及k8s的公司來講是一個很是高的門檻,很容易所以受阻而沒法啓動。
所以,若是暫時不具有k8s條件, 又不想就此止步,那麼選擇路線2是惟一的出路。而上面咱們分析過,路線2雖然可以在第一步快速拿到短時間紅利,可是因爲偏離長期目標後續發展會有問題。怎麼辦?
路線4能夠是這種場景下的一個折衷選擇:在k8s沒有鋪開以前,第一步沿路線2走,先吃下非k8s下Sidecar模式快速落地的紅利。而後第二步避開非k8s下繼續演進到Istio模式的大坑,切換到路線1,迴歸長期目標。
好處很是明顯:
缺點就是存在少許的投資浪費,畢竟非k8s下的Sidecar模式仍是有些工做內容在遷移到k8s以後會有改動。不過,這個改動不會太大,和拿到的紅利相比仍是值得的。
路線4在操做時,存在一個變數:現有應用在向Sidecar模式的Service Mesh遷移,是須要必定時間的。有一種可能,就是在遷移過程當中,k8s的普及開始了。這個變數的發生,取決於Sidecar模式的Service Mesh普及快,仍是k8s的普及快。
對路線4的分析結果:這是(k8s沒有普及的)特殊時期的選擇。
在對四條可能的演進路線分析完成以後,咱們來具體介紹螞蟻金服的最終選擇。
坦言說,在過去半年中,咱們的演進路線有幾回搖擺和修訂,今天咱們公佈的路線,和過去幾個月中咱們經過 meetup/技術大會/博客文章 等方式透露出來的方式會有一些變化。主要緣由是在過去的這半年中,一方面咱們對Sercice Mesh的認知更加深刻,另外一方面是螞蟻金服的k8s背景也在變化。
首先,在今年年初,咱們確認Service Mesh大方向時,k8s尚未在螞蟻金服普及,並且也沒有明確的時間表。所以,咱們在一番調研以後,選擇了兩條腿走路的方式:
在今年6月底的杭州第一屆Service Mesh 線下 meetup 中,咱們公佈了 SOFAMesh 項目,我當時作了一個演講 大規模微服務架構下的Service Mesh探索之路 ,有興趣的同窗能夠去回顧一下咱們當時的背景/需求/設計方案。
大概在今年九月,咱們完成了對非k8s下運行istio的深刻調研,得出的結論是要實現這個模式須要很是多的工做。並且,咱們對Service Mesh的認知也更加深入,明確了經過Service Mesh將傳統中間件能力向以k8s爲表明的基礎設施層下沉的戰略方向。期間,內部也明確了k8s普及的大方向,所以,綜合這兩個重要輸入,咱們選擇放棄繼續在路線2上繼續演進(即 istio on 非k8s)的想法。關於這一點,有興趣的同窗能夠去閱讀我在10月份QCon大會上的演講內容 長路漫漫踏歌而行:螞蟻金服Service Mesh實踐探索 。
最近,k8s普及的時間表再一次明確提早,螞蟻金服將會在短期內開啓k8s的大面積普及。所以,咱們的演進路線再一次發生變化。目前最新的演進路線將會是這樣:
須要強調的是:這個演進路線針對的是螞蟻金服主站的特殊場景,並不具體普適性。你們能夠在理解咱們演進路線背後的思路和權衡方式以後,再結合自身的實際狀況進行決策。好比,咱們在UC落地時,因爲UC有完善的k8s支持,並且目前落地的規模沒那麼誇張,所以是直接從"部署在k8s上" + "不是Service Mesh形態",直接遷移到終態的。預計在金融雲落實時,也會是如此,由於客戶也不會有如此規模。
總結:前面咱們介紹了當應用程序向Service Mesh和K8s遷移時的幾種可能的演進路線,分析了各條路線的利弊。並以螞蟻金服主站爲例,介紹了咱們遷移的背景和演進路線的選擇思路,但願可以幫助你們更好的理解Service Mesh的落地實踐,以便在將來設計自家的落地方案時能有所參考。
實現平滑遷移的關鍵
前面給你們介紹了螞蟻金服主站的Service Mesh演進路線,期間談到要實現現有應用的平滑遷移。今天的第二個內容,將給你們介紹平滑遷移實現中的幾個關鍵作法。
首先,第一個關鍵是儘可能保證遷移先後服務間網絡互通。
以向k8s遷移爲例,在非k8s環境,典型的服務間訪問方式是這樣:
在向k8s遷移的過程當中,咱們的作法是保證k8s內外網絡打通,即服務的IP地址(在k8s中是pod ip)是能夠相互直接訪問的。基於這個前提,服務在遷移到k8s的過程當中,原有的服務註冊/服務發現/發起請求等邏輯都無需修改,是否是在k8s內,是否是pod ip,對原有服務化體系徹底是透明的。
所以,向k8s的遷移能夠作到對業務應用很是的平滑,基本感知。
透明攔截在遷移過程當中,能夠起到很是關鍵的做用。
以Service-A要訪問Service-B,在應用向Sidecar模式的Service Mesh遷移先後,會有有四種排列組合場景:
在這四種場景中,全部的網絡請求,請求報文都是徹底一致的,即無論是否被劫持到Sidecar,對請求報文都沒有影響,也就是對發出請求報文的客戶端和接受請求報文的客戶端都是透明的,徹底無感之。
所以,在遷移過程當中,能夠單個服務逐個遷移,甚至服務的單個實例逐個遷移,而無需修改應用自己。
在展開第三個關鍵點以前,咱們來探討一下:在Service Mesh時代,理想的客戶端應該是什麼樣子?
圖中咱們列舉了一個傳統的侵入式框架的客戶端所包含的功能,在侵入式框架中,大部分的功能都是由客戶端實現,所以會包含很是多的功能,如服務發現、負載均衡等基本功能,加密、認證、路由等高級功能。在應用遷移到Service Mesh以後,這些功能都下沉到Service Mesh中。所以,Service Mesh下的客戶端能夠進行大幅度的簡化,成爲一個新的輕量級客戶端。
對於這個輕量級客戶端,咱們但願能夠儘量的作的輕薄通用:實現簡單,無論哪一個編程語言均可以作到輕鬆實現,所以跨語言就方便了。並且越簡單以後升級的可能性就會越少,以免升級客戶端。
那咱們來繼續看,這個輕量級客戶端裏面最後還能剩下什麼內容?
圖中列出了三個,其中最重要的,也是必不可少的是目標服務的標識,即不管如何簡化,最低限度應該告之要訪問誰吧?而後是序列化,對於RPC類確定須要提供編解碼功能,不過對於HTTP/REST類不少語言直接內置了標準實現。而後鏈路追蹤,須要作一點工做來傳遞諸如SpanID之類的參數,一樣這塊也有可能經過自動埋點來實現。所以,最理想最單薄的客戶端,可能只保留最後一個信息:目標服務的標示。
在侵入式框架下,目標服務的標示是和服務註冊/服務發現是直接關聯的,這個標示一般都是服務名,經過服務發現機制實現了一個服務名到服務實例的尋址方式。在Service Mesh機制下,因爲服務發現機制被下沉到Service Mesh中,所以只要底層Service Mesh能支持,這個目標服務的標示能夠沒必要拘泥於服務名。
那麼,問題來了,對客戶端來講:最簡單,最通用,支持最普遍的尋址方式是什麼?是DNS!
在咱們的遷移方案中,咱們考慮引入DNS尋址方式。除了前面說的DNS是支持度最好,使用最廣泛的尋址方式,在全部的編程語言和平臺上均可以支持以外,咱們還但願將DNS尋址方式做爲將來產品的長期方向:
所以,在咱們的演進過程當中,對於客戶端SDK,咱們有這樣一個思路:
圖中描述的是在Service Mesh下,客戶端經過域名來指定要訪問的目標服務,而後經過DNS解析機制來串聯底層的服務註冊/DNS記錄更新/透明劫持傳遞原始信息/Sidecar查找路由目標等詳細實現機制。
這裏僅作簡單示意,我就不詳細展開了。在接下來的內容中,個人同事,來自UC基礎研發部的 龍軾 同窗,將爲你們詳細的展開DNS尋址方案的細節實現。
DNS尋址方案的演進
你們好,我是來自UC基礎研發部的龍軾。 感謝小劍老師給咱們介紹了螞蟻和UC共建的Service Mesh的演進路線和實現平滑遷移的關鍵。
接下來由我來向你們分享下實現平滑遷移的關鍵中的DNS尋址方案的演進。
你們能夠看上面的所示的DNS尋址方案的演進,咱們先了解下各個服務尋址方案的背景。
從 SOA 的尋址,到 Kubernetes 的尋址,而後再到 Istio 的尋址,最後是咱們的 SOFAMesh 的DNS尋址方案。
它們的尋址方案有什麼不一樣,咱們將一一分析它們的細節和整體尋址方案的演進路線。
如今你們能夠先來看下 SOA 架構下基於服務註冊和服務發現的尋址。
咱們能夠看到圖中的 SOA 實際上是單進程多接口的,依賴於 SOA 的服務註冊與服務發現的。
接下來咱們看下 Kubernetes 的 DNS 尋址方式,它的尋址方式實際上是經過DNS 的。
從圖中咱們能夠看到部署到K8S 上面的userservice 服務會生成一條DNS記錄指向K8S 的ClusterIP。
咱們在 Pod 裏面發起請求時經過 DNS 的 SearchDomain 域名補全規則就會從 DNS 裏面查詢獲得ClusterIP,咱們能夠看出 Kubernetes 的尋址方案是單進程單接口的。
看完 Kubernetes 的服務發現以後咱們繼續來看 Istio 的服務發現。
從圖中咱們能夠看出以前的流程都和 K8S 一脈相承,不一樣的地方在於 Istio 裏面有個 SideCar 它把ClusterIP 拿到以後根據 ClusterIP 從 VirtualHost 裏面匹配到 Rule 規則 轉發給目標的 Pod 地址。
最後咱們來看下 SOFAMesh 的 DNS 通用尋址方案。
你們看這張圖:
好的,說完這個方案的細節以後。咱們能夠看出其實其餘的問題都不大,可是要更新DNS的這個咱們須要支持。
一開始咱們 K8S 集羣裏面是用 Kube-DNS 來作 DNS 尋址的,但咱們看這張 Kube-DNS 的架構圖。
能夠看出修改它成本是比較大的,並且全部的DNS 都在同一個域裏面,這個風險係數很高。 若是一旦修改錯誤勢必會影響到以前的 k8s 的 service,致使線上的故障。
OK,既然 CoreDNS 的 Plugins 這麼強大,咱們可不能夠用它來實現咱們剛纔說到的 Renew DNS的機制。 答案很顯然是能夠。
咱們看下上面的圖,實現CoreDNS 的插件很簡單,只須要繼承上面的接口就能夠了。 CoreDNS 官網有具體的教程在教咱們怎麼寫一個插件。這個就不具體的展開了。
咱們能夠看下 CoreDNS 後端存儲的接口,其實和咱們以前對數據操做的接口是沒有什麼差異的。
目前 CoreDNS 的 DynAPI 還在主庫代碼沒合併的狀態。以後 DynAPI 這個項目會獨立成一個插件項目。咱們能夠看下 CoreDNS 社區的 DynAPI 插件進展。
OK,咱們來看下咱們的DynAPI 實現DNS 更新的一個效果。從圖中咱們能夠看出 record.json 裏面的一個域名的更新。經過 DynAPI 咱們成功把 record.json 的DNS 記錄給更新進去而且dns正常工做了。到如今咱們經過CoreDNS 的插件就把DNS 更新的需求給解決了。
其實CoreDNS 官網還有許多有趣的插件,能夠豐富 CoreDNS 的功能和提高 CoreDNS 的性能。 你們能夠看下中間的 autopath 插件,他把咱們屢次的在 searchdomain 拼湊的 DNS 記錄的查詢在在服務器上給實現了。 避免了屢次的 Client 端和 Server 端的數據交互。有興趣的同窗能夠看下 A-Deep-Dive-into-CoreDNS-2018。
咱們把 CoreDNS 的功能開發完了,上線的話不少人關注它的性能。 咱們這邊作了一個簡單的性能測試,能夠看出 CoreDNS 和 Bind DNS 這種如今比較通用的DNS的性能仍是有點差距的。
可是,咱們經過上面的圖能夠看到在必定的QPS 下,CoreDNS 的延時是很低的。 咱們能夠看到全部的延時都落在4ms 以內。
爲了解決QPS的問題,咱們經過 Kubernetes 的 HPA 給 CoreDNS 進行橫向的擴展。
一開始咱們只是經過CPU的維度給 CoreDNS 擴展,但發現波動有點大。 以後咱們切換成經過QPS的維度來進行擴容。
CoreDNS 將會在Kubernetes 1.13 以後成爲 Kubernetes 的默認的DNS服務。咱們將會緊跟社區實施咱們的方案而且反饋給社區。
DNS尋址方案的後續規劃
咱們再來看下咱們後續的一些規劃。
能夠看到咱們的 DynAPI 其實在安全上仍是有欠缺的。咱們後續會把 HTTP 增強成 HTTPS 協議來加強 DynAPI 的安全性。
還有若是咱們 CoreDNS 的後端變化的更新的 Watch 因爲 Watch的範圍過大的話,會返回過多的數據。這樣會影響到 Watch 的性能,CoreOS 在 ETCD3.2 增長了proxy 可讓咱們根據不一樣的 ETCD KeySpace 去Watch,這樣大大的提升了Watch的性能。
最後一個,咱們建議在建立 Kubernetes 集羣的時候把 idc 的信息給帶進Kubernetes的後綴域名中。這樣咱們以後能夠經過 kubernetai 插件把不一樣的 Kubernetes 集羣的域名進行整合經過本 IDC 緩存提升跨 IDC DNS 的訪問速度。
最後咱們總結下,整體方面小劍老師給咱們講了螞蟻金服主站 Service Mesh 的漸進式演進路線和實現平滑遷移的幾個關鍵。 具體細節方面咱們經過CoreDNS 的單點突破解決了 SOFAMesh 的 DNS 尋址的問題。
感謝你們,但願此次演講能讓你們有所收穫。
地址:https://tech.antfin.com/activ...(點擊閱讀原文可跳轉到該網頁)
相關連接:
SOFA 文檔: http://www.sofastack.tech/
SOFA: https://github.com/alipay
SOFAMosn:
https://github.com/alipay/sof...
SOFAMesh:
https://github.com/alipay/sof...
本文爲雲棲社區原創內容,未經容許不得轉載。