螞蟻金服 Service Mesh 漸進式遷移方案|Service Mesh Meetup 實錄

小螞蟻說: git

本文是基於在 Service Mesher Meetup 上海站的主題分享《 螞蟻金服 Service Mesh 漸進式遷移方案》 內容整理,完整的分享 PPT 獲取方式見文章底部。 github


敖小劍,螞蟻金服高級技術專家,十六年軟件開發經驗,微服務專家,Service Mesh 佈道師,Servicemesher 社區聯合創始人; 龍軾,阿里巴巴技術專家、前京東 Hadoop 負責人、Hadoop 代碼貢獻者、現負責UC 基於 Kubernetes 自研的 PaaS 平臺總體的穩定性。 編程

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1


你們好,今天給你們帶來的演講主題是《螞蟻金服 Service Mesh 漸進式遷移方案》,給你們介紹一下咱們螞蟻金服主站的 Service Mesh 遷移方案,在稍後的內容中我會給你們解釋什麼是「漸進式」。今天的演講方式有些特殊,將會是兩位講師合做。我是敖小劍,來自螞蟻金服中間件團隊,另一位講師 龍軾 ,來自 UC 基礎研發部。 json


Service Mesh 演進路線 後端

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


今天的內容將會有四塊主要內容: api

  1. Service Mesh演進路線:介紹螞蟻金服計劃在主站落地Service Mesh的方案,因爲涉及到大量的存量應用和超大規模,又要保證遷移過程的平滑,所以咱們的落地方案相比社區方案要複雜的多。 緩存

  2. 實現平滑遷移的關鍵:介紹在整個遷移方案中,爲了實現平滑遷移的幾個關鍵作法,而後今天咱們將詳細展開其餘的一個關鍵點:DNS尋址方案。 安全

  3. DNS尋址方案的演進:詳細介紹Kubernetes/Istio/SOFAMesh一路演進過來的DNS尋址方式 服務器

  4. DNS尋址方案的後續規劃:介紹咱們在DNS尋址方案上的後續規劃 網絡


前兩塊內容將由我來爲你們介紹,後兩塊內容將由個人同事 龍軾 爲你們介紹。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


在展開內容以前,先看一下背景,Service Mesh在螞蟻金服主站落地的背景:

  • 目標:須要知足咱們對長期目標的承認,具體指服務間通信走Service Mesh,並且是Istio這種帶完整的控制平面的Service Mesh形態,基礎設施要構建在k8s之上,而應用的形態要向微服務靠攏。

  • 現狀:而現實是存在不少挑戰,首先還有不少應用沒有實現微服務化,並且咱們的k8s普及程度也不夠,還有很是多的應用沒有運行在kubernets之上。Istio的成熟程度也稍顯不足,不夠穩定,更大的挑戰的是Istio目前沒法原生支持咱們螞蟻金服的規模,咱們還在試圖對Istio進行改進和擴展。最後,在落地時必須考慮的很是現實的一點:現有系統中爲數衆多的應用不可能一晚上之間所有遷移。

  • 關鍵需求:所以在落地實施時,很是重要的需求是:要實現平滑遷移。簡單說,微服務 + Service Mesh + kubernetes 是咱們的目標,可是如何從現有體系出發,向目標平穩和堅實的邁進,必須給出可行的實踐指導。


今天演講的內容,要給你們介紹的就是,在這樣的背景下,咱們螞蟻金服選擇的Service Mesh主站落地演進方案。這個方案預期會在2019年初全面鋪開。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


主站落地方案的實施原則,這是咱們在過去半年的實踐中,總結概括出來的行爲指導:

  • 符合遠期規劃:必定要有清晰的長期目標,明確的知道將來的大方向。避免走彎路,避免浪費投資,理想狀態是計劃中的每一步均可覺得下一步奠基堅實的基礎。即便由於某些緣由不得已妥協或繞行,也應該清晰的知道後面應該如何迴歸,謝絕中途推倒重來——代價過高,沒法承受。

  • 按部就班:認清現實,如此之大的變革,必定是須要分步進行,不要心存一步登天的幻想,現實可行的方式是小步快跑。將整個過程拆解爲若干個大步驟,每一步的工做量和複雜度都控制在一個能夠接受的範圍內,以保證每一步都簡單方便,切實可行。

  • 有可操做性:在操做層面上,要有足夠的彈性,即每一個步驟中的工做內容,都應該是能夠分批進行。以步步爲營的方式,逐步擴大戰果,杜絕一刀切。


在接下來的演進路線中,你們將會體會到這三個原則在實際落地時的指導做用。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


這個圖的信息量有點大,描述的是 Service Mesh 和 k8s 落地可能的多種演進路線。


咱們先從最下面開始看,這是當前螞蟻金服主站大多數應用的現狀:即應用"部署在非k8s上",應用也"不是Service Mesh形態"。 而後看最上面,這是咱們指望的螞蟻金服主站將來的應用終極形態:應用"部署在k8s上",應用也遷移到了"Service Mesh形態"。


這裏有個特別的地方,咱們將Service Mesh形態細分爲兩種模式:

  1. Sidecar模式:只有Sidecar,沒有控制平面,和外部系統的各類集成都是在Sidecar中直接進行。這是第一代的Service Mesh,Linkerd/Envoy都是如此,華爲基於ServiceComb演進而來的mesher,新浪微博的Mesh,包括咱們螞蟻金服基於MOSN開發的用於取代多語言客戶端的Mesh方案。

  2. Istio模式:有完善的控制平面,能夠提供強大的控制能力,並且從數據平面分離,這是第二代的Service Mesh,典型如Istio和Conkduit/Linkerd 2.0。


之因此將Service Mesh形態細分,是由於咱們有着這樣一個特殊背景:目前的原生Istio沒法支撐咱們螞蟻金服的規模,所以在改進完善Istio以前,咱們不得不暫時在Sidecar模式下短暫停留。另一個緣由就是考慮到存量應用的遷移,多一個Sidecar模式做爲中間緩衝,會讓整個遷移過程平滑不少。


如今咱們來介紹圖中展現的四條演進路線:

  1. 左邊的路線1,思路是先將應用遷移k8s部署,再遷移到Service Mesh形態。這條路線的最大好處,是過程當中每一個階段的絕大多數投資都將最終得以保留,由於符合k8s+service mesh的遠期目標

  2. 右邊的路線2,思路是跳過k8s,先遷移到Service Mesh形態,一路演進到Istio模式,而後最後遷移到k8s。

  3. 中間的路線3,直接一步到位,這個路線是Istio默認的方式,或者說Istio根本沒有考慮過遷移的問題,默認客戶已經有完善的k8s,而後將改造好的應用直接部署在Istio上。這個路線對於螞蟻金服主站的複雜場景,固然是不現實的。(補充:只是對螞蟻金服主站不合適,對於大多數公司,規模不是那麼巨大,也沒有歷史負擔,也有k8s基礎,徹底可行。)

  4. 還有一條特別的路線4,走位飄忽,先和路線2同樣遷移到Sidecar模式,而後走迴路線1,上k8s,再在有k8s支持的狀況下繼續演進到Istio模式。


下面咱們來詳細分析各條演進路線的優劣和實施條件。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


演進路線2,和路線1的核心差異,在於:是先上k8s,仍是先上Service Mesh。並且路線2是在非k8s條件下一路演進Service Mesh到咱們指望的終極形態Istio模式,這意味着過程當中和最終目標有很是大的偏移。


演進路線2的好處,在於第一步很是的天然:

  • 沒有k8s的限制,所以不依賴基礎設施,實施方便。畢竟,k8s普及度是個大問題

  • 在原有的侵入式框架的客戶端SDK基礎上,經過包裹一個proxy,重用原有SDK的能力,能夠很是快速的獲得一個基本可用的Sidecar

  • 除了多一個proxy外,沒有引入太多的新概念和新思想,符合現有開發人員/運維人員的心智,容易接受


所以,路線2特別容易落地,能夠快速達成短時間目標,直接拿到Service Mesh的部分成利,如:多語言支持,方便類庫升級等。


可是,這個路線的問題在於再日後走,開始完善Service Mesh的功能以向Istio模式靠攏時,因爲沒有k8s的底層支持,所以不得不作大量的工做來提供類k8s的功能。尤爲是Istio的非k8s支持,官方方案基本上只是一個demo,徹底不具有生產可用性,要完善好,工做量很大。而關鍵點在於,這些投入,在遷移到k8s時,又由於和k8s提供的功能重複而被放棄。


所以,結合咱們前面的原則(符合遠期規劃,不浪費投資),路線2對螞蟻金服主站落地是不合適的。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


演進路線4是一個很是特殊的路線,能夠理解爲路線1(先上k8s再上Service Mesh)的短時間妥協版本。由於路線1的前提條件是要先大規模鋪開k8s,將現有應用遷移到k8s以後再繼續往Service Mesh演進,這對於尚未普及k8s的公司來講是一個很是高的門檻,很容易所以受阻而沒法啓動。


所以,若是暫時不具有k8s條件, 又不想就此止步,那麼選擇路線2是惟一的出路。而上面咱們分析過,路線2雖然可以在第一步快速拿到短時間紅利,可是因爲偏離長期目標後續發展會有問題。怎麼辦?


路線4能夠是這種場景下的一個折衷選擇:在k8s沒有鋪開以前,第一步沿路線2走,先吃下非k8s下Sidecar模式快速落地的紅利。而後第二步避開非k8s下繼續演進到Istio模式的大坑,切換到路線1,迴歸長期目標。


好處很是明顯:

  • 在k8s未鋪開前,先往前邁進一步,避免就此卡殼

  • 和路線2同樣,第一步能夠快速的拿到短時間紅利

  • 後續轉爲路線1後,由於符合遠期規劃,所以後續演進不存在投資浪費的問題


缺點就是存在少許的投資浪費,畢竟非k8s下的Sidecar模式仍是有些工做內容在遷移到k8s以後會有改動。不過,這個改動不會太大,和拿到的紅利相比仍是值得的。


路線4在操做時,存在一個變數:現有應用在向Sidecar模式的Service Mesh遷移,是須要必定時間的。有一種可能,就是在遷移過程當中,k8s的普及開始了。這個變數的發生,取決於Sidecar模式的Service Mesh普及快,仍是k8s的普及快。


對路線4的分析結果:這是(k8s沒有普及的)特殊時期的選擇。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


在對四條可能的演進路線分析完成以後,咱們來具體介紹螞蟻金服的最終選擇。


坦言說,在過去半年中,咱們的演進路線有幾回搖擺和修訂,今天咱們公佈的路線,和過去幾個月中咱們經過 meetup/技術大會/博客文章 等方式透露出來的方式會有一些變化。主要緣由是在過去的這半年中,一方面咱們對Sercice Mesh的認知更加深刻,另外一方面是螞蟻金服的k8s背景也在變化。


首先,在今年年初,咱們確認Service Mesh大方向時,k8s尚未在螞蟻金服普及,並且也沒有明確的時間表。所以,咱們在一番調研以後,選擇了兩條腿走路的方式:

  1. 在非k8s環境下,以Sidecar模式先進行少許落地,主要是替換掉原有的多語言客戶端 (拿短時間紅利)

  2. 開發SOFAMesh,集成MOSN到Istio,增長對多種RPC協議的支持,增長對RPC服務模式的兼容(爲最終目標作準備 )


在今年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的大面積普及。所以,咱們的演進路線再一次發生變化。目前最新的演進路線將會是這樣:

  1. 當前尚未開始遷移的應用(處於演進路線圖最下方),將按照路線1的方式進行遷移:先遷移到k8s,再遷移到Sidecar模式的Service Mesh

  2. 目前部分已經遷移的應用(路線2/4的第一步,非k8s部署的 Sidecar 模式),將沿路線4遷移,和路線1會師

  3. 因爲應用衆多,所以預計到 k8s + Sidecar模式 的遷移工做會持續比較長時間,在此期間,咱們會同步完善Istio,和Istio官方一塊兒合做來實現Istio對超大規模部署的支持

  4. 最後一步,遷移到最終目標(固然這一步的方案依然有不少待定內容,繼續努力)


須要強調的是:這個演進路線針對的是螞蟻金服主站的特殊場景,並不具體普適性。你們能夠在理解咱們演進路線背後的思路和權衡方式以後,再結合自身的實際狀況進行決策。好比,咱們在UC落地時,因爲UC有完善的k8s支持,並且目前落地的規模沒那麼誇張,所以是直接從"部署在k8s上" + "不是Service Mesh形態",直接遷移到終態的。預計在金融雲落實時,也會是如此,由於客戶也不會有如此規模。


總結:前面咱們介紹了當應用程序向Service Mesh和K8s遷移時的幾種可能的演進路線,分析了各條路線的利弊。並以螞蟻金服主站爲例,介紹了咱們遷移的背景和演進路線的選擇思路,但願可以幫助你們更好的理解Service Mesh的落地實踐,以便在將來設計自家的落地方案時能有所參考。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


實現平滑遷移的關鍵

前面給你們介紹了螞蟻金服主站的Service Mesh演進路線,期間談到要實現現有應用的平滑遷移。今天的第二個內容,將給你們介紹平滑遷移實現中的幾個關鍵作法。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


首先,第一個關鍵是儘可能保證遷移先後服務間網絡互通。


以向k8s遷移爲例,在非k8s環境,典型的服務間訪問方式是這樣:

  • 每一個服務向註冊中心註冊

  • 客戶端發起訪問前,經過註冊中心獲得目標服務的實例列表信息,如IP地址/端口等


在向k8s遷移的過程當中,咱們的作法是保證k8s內外網絡打通,即服務的IP地址(在k8s中是pod ip)是能夠相互直接訪問的。基於這個前提,服務在遷移到k8s的過程當中,原有的服務註冊/服務發現/發起請求等邏輯都無需修改,是否是在k8s內,是否是pod ip,對原有服務化體系徹底是透明的。


所以,向k8s的遷移能夠作到對業務應用很是的平滑,基本感知。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


透明攔截在遷移過程當中,能夠起到很是關鍵的做用。


以Service-A要訪問Service-B,在應用向Sidecar模式的Service Mesh遷移先後,會有有四種排列組合場景:

  1. Service-A和Service-B都沒有遷移到Serive Mesh:此時請求會直接從Service-A發送到Service-B,稱爲直連,這是應用在開始遷移到Service Mesh以前的標準工做方式

  2. Service-A已經遷移到Service Mesh,Service-B尚未:此時Service-A發出來的請求,會被劫持,而後發送到和Service-A一塊兒部署的Sidecar(稱爲Outbound Sidecar),此時鏈路中只有一個Sidecar,稱爲(客戶端)單跳

  3. Service-B已經遷移到Service Mesh,Service-A尚未:此時Service-A發出來的請求,在到達Service-B時,會被劫持到和Service-B一塊兒部署的Sidecar(稱爲Inbound Sidecar),此時鏈路中也只有一個Sidecar,稱爲(服務器端)單跳

  4. Service-A和Service-B都遷移到Serive Mesh:此時Service-A發出來的請求,會被兩次劫持,分別進入Outbound Sidecar和Inbound Sidecar,此時鏈路中有兩個Sidecar,稱爲雙跳。這是Istio的標準工做模式,也是咱們遷移完成以後的最終工做模式。


在這四種場景中,全部的網絡請求,請求報文都是徹底一致的,即無論是否被劫持到Sidecar,對請求報文都沒有影響,也就是對發出請求報文的客戶端和接受請求報文的客戶端都是透明的,徹底無感之。


所以,在遷移過程當中,能夠單個服務逐個遷移,甚至服務的單個實例逐個遷移,而無需修改應用自己。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


在展開第三個關鍵點以前,咱們來探討一下:在Service Mesh時代,理想的客戶端應該是什麼樣子?


圖中咱們列舉了一個傳統的侵入式框架的客戶端所包含的功能,在侵入式框架中,大部分的功能都是由客戶端實現,所以會包含很是多的功能,如服務發現、負載均衡等基本功能,加密、認證、路由等高級功能。在應用遷移到Service Mesh以後,這些功能都下沉到Service Mesh中。所以,Service Mesh下的客戶端能夠進行大幅度的簡化,成爲一個新的輕量級客戶端。


對於這個輕量級客戶端,咱們但願能夠儘量的作的輕薄通用:實現簡單,無論哪一個編程語言均可以作到輕鬆實現,所以跨語言就方便了。並且越簡單以後升級的可能性就會越少,以免升級客戶端。


那咱們來繼續看,這個輕量級客戶端裏面最後還能剩下什麼內容?


圖中列出了三個,其中最重要的,也是必不可少的是目標服務的標識,即不管如何簡化,最低限度應該告之要訪問誰吧?而後是序列化,對於RPC類確定須要提供編解碼功能,不過對於HTTP/REST類不少語言直接內置了標準實現。而後鏈路追蹤,須要作一點工做來傳遞諸如SpanID之類的參數,一樣這塊也有可能經過自動埋點來實現。所以,最理想最單薄的客戶端,可能只保留最後一個信息:目標服務的標示。


在侵入式框架下,目標服務的標示是和服務註冊/服務發現是直接關聯的,這個標示一般都是服務名,經過服務發現機制實現了一個服務名到服務實例的尋址方式。在Service Mesh機制下,因爲服務發現機制被下沉到Service Mesh中,所以只要底層Service Mesh能支持,這個目標服務的標示能夠沒必要拘泥於服務名。


那麼,問題來了,對客戶端來講:最簡單,最通用,支持最普遍的尋址方式是什麼?是DNS!


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


在咱們的遷移方案中,咱們考慮引入DNS尋址方式。除了前面說的DNS是支持度最好,使用最廣泛的尋址方式,在全部的編程語言和平臺上均可以支持以外,咱們還但願將DNS尋址方式做爲將來產品的長期方向:

  • 在SOFAMesh和SOFAMosn中,咱們已經基於名爲x-protocol的方式實現了DNS通用尋址方式,用來解決Dubbo/HSF/SOFA等傳統SOA服務模型在Service Mesh下的訪問問題 (備註: 具體內容請見個人博客文章 SOFAMesh中的多協議通用解決方案x-protocol介紹系列(1)-DNS通用尋址方案 )

  • 將來在咱們的serverless產品中,咱們但願能夠爲運行其上的Function提供DNS尋址支持

  • 可能還會有其餘更加普遍的使用場景。

所以,在咱們的演進過程當中,對於客戶端SDK,咱們有這樣一個思路:

  • 一方面簡化原有的SDK,去除和Sidecar重複的內容(知足短時間需求)

  • 另外一方面,考慮到必然有一次客戶端SDK的更換過程,那麼咱們但願在簡化的同時引入基於DNS的通用尋址方式,以便在將來的後續遷移和功能擴展中能夠依託這個機制來實現 (符合長期目標)


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


圖中描述的是在Service Mesh下,客戶端經過域名來指定要訪問的目標服務,而後經過DNS解析機制來串聯底層的服務註冊/DNS記錄更新/透明劫持傳遞原始信息/Sidecar查找路由目標等詳細實現機制。


這裏僅作簡單示意,我就不詳細展開了。在接下來的內容中,個人同事,來自UC基礎研發部的 龍軾 同窗,將爲你們詳細的展開DNS尋址方案的細節實現。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


DNS尋址方案的演進

你們好,我是來自UC基礎研發部的龍軾。 感謝小劍老師給咱們介紹了螞蟻和UC共建的Service Mesh的演進路線和實現平滑遷移的關鍵。


接下來由我來向你們分享下實現平滑遷移的關鍵中的DNS尋址方案的演進。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


你們能夠看上面的所示的DNS尋址方案的演進,咱們先了解下各個服務尋址方案的背景。


從 SOA 的尋址,到 Kubernetes 的尋址,而後再到 Istio 的尋址,最後是咱們的 SOFAMesh 的DNS尋址方案。


它們的尋址方案有什麼不一樣,咱們將一一分析它們的細節和整體尋址方案的演進路線。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


如今你們能夠先來看下 SOA 架構下基於服務註冊和服務發現的尋址。


咱們能夠看到圖中的 SOA 實際上是單進程多接口的,依賴於 SOA 的服務註冊與服務發現的。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


接下來咱們看下 Kubernetes 的 DNS 尋址方式,它的尋址方式實際上是經過DNS 的。


從圖中咱們能夠看到部署到K8S 上面的userservice 服務會生成一條DNS記錄指向K8S 的ClusterIP。


咱們在 Pod 裏面發起請求時經過 DNS 的 SearchDomain 域名補全規則就會從 DNS 裏面查詢獲得ClusterIP,咱們能夠看出 Kubernetes 的尋址方案是單進程單接口的。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


看完 Kubernetes 的服務發現以後咱們繼續來看 Istio 的服務發現。


從圖中咱們能夠看出以前的流程都和 K8S 一脈相承,不一樣的地方在於 Istio 裏面有個 SideCar 它把ClusterIP 拿到以後根據 ClusterIP 從 VirtualHost 裏面匹配到 Rule 規則 轉發給目標的 Pod 地址。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


最後咱們來看下 SOFAMesh 的 DNS 通用尋址方案。

  1. 根據咱們以前分析的 SOA 尋址方案和 Kubernetes 尋址方案,咱們能夠看出若是咱們的微服務不通過拆分和改造想上 Service Mesh 的話咱們須要支持SOA以前的那種單個Pod 多個接口的。

  2. 從圖中看就是咱們須要支持 com.alipay.userservice.interface1, com.alipay.userservice.interface2 這些接口解析到 ClusterIP, 咱們知道k8s 中的service 是不支持的。

  3. 那該如何是好,咱們只能在DNS 上作文章修改DNS的記錄來實現這一功能。肯定了這一方案以後咱們來看下咱們設計的DNS尋址方案實現細節。



640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


你們看這張圖:

  1. 咱們用 CRD 定義了一個 RPCService 和以前的 Service 有一樣的 selector 的標籤。

  2. 而後用 RPC Service Controller 對 RPCService 作 Watch,當 RPCService 有更新的時候咱們就把接口就是上述的 com.alipay.userservice.interface1 的記錄寫入 CoreDNS 裏面

  3. 而 interface 是經過 Pod 裏面的 Register Agent 來獲取 Dubbo 裏面暴露的。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


好的,說完這個方案的細節以後。咱們能夠看出其實其餘的問題都不大,可是要更新DNS的這個咱們須要支持。


一開始咱們 K8S 集羣裏面是用 Kube-DNS 來作 DNS 尋址的,但咱們看這張 Kube-DNS 的架構圖。


能夠看出修改它成本是比較大的,並且全部的DNS 都在同一個域裏面,這個風險係數很高。 若是一旦修改錯誤勢必會影響到以前的 k8s 的 service,致使線上的故障。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


  1. 這個時候咱們跟蹤到社區的 CoreDNS 項目,咱們來看下 CoreDNS 的具體的架構。  它採用做爲 Web 服務器 Caddy 的服務器框架,延用了Caddy 中的插件機制,大大的增長了 CoreDNS 的靈活性。

  2. 它的插件機制也特別簡單,把全部的插件註冊進一個Map裏面來,在調用的時候從Map拿出他們有共同接口的函數。有興趣的同窗能夠看下 Caddy 的插件代碼實現。  

  3. 它的 DNS 協議庫採用是由 Google 工程師 Meikg 開發的 DNS 庫,他同時也是 SkyDNS 的開發者。

  4. 後端能夠採用 UDP/TCP、TLS 或者 gRPC 做爲後端數據查詢。上面有個Google工程師用 gRPC 作了一個 CoreDNS 插件的後端數據查詢例子,有興趣的同窗能夠看下。




640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


OK,既然 CoreDNS 的 Plugins 這麼強大,咱們可不能夠用它來實現咱們剛纔說到的 Renew DNS的機制。 答案很顯然是能夠。


咱們看下上面的圖,實現CoreDNS 的插件很簡單,只須要繼承上面的接口就能夠了。 CoreDNS 官網有具體的教程在教咱們怎麼寫一個插件。這個就不具體的展開了。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


  1. 到了咱們最關鍵的點了:咱們應該怎麼更新咱們的DNS。其實這點 CoreDNS 社區裏面已經有人提出需求用 REST API 的形式提供更新 DNS 的接口。

  2. 互聯網任務工程小組也早在 rfc2136 定義了標準的 DNS UPDATE。 Google Cloud 和AWS 都有相應的實現。

  3. CoreDNS 社區其實已經把接口實現了,可是後端存儲是基於file 的,數據沒有落地。 螞蟻和UC 這邊擴展了 ETCD 插件的接口,把對應 DNS UPDATE 接口給實現了,實現 DNS 數據寫入ETCD 裏面。

  4. 從圖中咱們能夠看到 rpc.cluster.local 這個域 和 k8s 域 cluster.local 是在不一樣的插件鏈上的。
    這樣在k8s域中沒有 dynapirest 插件,咱們就不能對k8s域中的DNS進行更新,這樣就把以前Kube-DNS改造以後會對k8s域裏面形成影響給去除了,更加的安全。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


咱們能夠看下 CoreDNS 後端存儲的接口,其實和咱們以前對數據操做的接口是沒有什麼差異的。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


目前 CoreDNS 的 DynAPI 還在主庫代碼沒合併的狀態。以後 DynAPI 這個項目會獨立成一個插件項目。咱們能夠看下 CoreDNS 社區的 DynAPI 插件進展。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


OK,咱們來看下咱們的DynAPI 實現DNS 更新的一個效果。從圖中咱們能夠看出 record.json 裏面的一個域名的更新。經過 DynAPI 咱們成功把 record.json 的DNS 記錄給更新進去而且dns正常工做了。到如今咱們經過CoreDNS 的插件就把DNS 更新的需求給解決了。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


其實CoreDNS 官網還有許多有趣的插件,能夠豐富 CoreDNS 的功能和提高 CoreDNS 的性能。 你們能夠看下中間的 autopath 插件,他把咱們屢次的在 searchdomain 拼湊的 DNS 記錄的查詢在在服務器上給實現了。 避免了屢次的 Client 端和 Server 端的數據交互。有興趣的同窗能夠看下 A-Deep-Dive-into-CoreDNS-2018


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


咱們把 CoreDNS 的功能開發完了,上線的話不少人關注它的性能。 咱們這邊作了一個簡單的性能測試,能夠看出 CoreDNS 和 Bind DNS 這種如今比較通用的DNS的性能仍是有點差距的。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


可是,咱們經過上面的圖能夠看到在必定的QPS 下,CoreDNS 的延時是很低的。 咱們能夠看到全部的延時都落在4ms 以內。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


爲了解決QPS的問題,咱們經過 Kubernetes 的 HPA 給 CoreDNS 進行橫向的擴展。


一開始咱們只是經過CPU的維度給 CoreDNS 擴展,但發現波動有點大。 以後咱們切換成經過QPS的維度來進行擴容。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


CoreDNS 將會在Kubernetes 1.13 以後成爲 Kubernetes 的默認的DNS服務。咱們將會緊跟社區實施咱們的方案而且反饋給社區。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


DNS尋址方案的後續規劃

咱們再來看下咱們後續的一些規劃。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


能夠看到咱們的 DynAPI 其實在安全上仍是有欠缺的。咱們後續會把 HTTP 增強成 HTTPS 協議來加強 DynAPI 的安全性。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


還有若是咱們 CoreDNS 的後端變化的更新的 Watch 因爲 Watch的範圍過大的話,會返回過多的數據。這樣會影響到 Watch 的性能,CoreOS 在 ETCD3.2 增長了proxy 可讓咱們根據不一樣的 ETCD KeySpace 去Watch,這樣大大的提升了Watch的性能。


640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


最後一個,咱們建議在建立 Kubernetes 集羣的時候把 idc 的信息給帶進Kubernetes的後綴域名中。這樣咱們以後能夠經過 kubernetai 插件把不一樣的 Kubernetes 集羣的域名進行整合經過本 IDC 緩存提升跨 IDC DNS 的訪問速度。


總結

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


最後咱們總結下,整體方面小劍老師給咱們講了螞蟻金服主站 Service Mesh 的漸進式演進路線和實現平滑遷移的幾個關鍵。 具體細節方面咱們經過CoreDNS 的單點突破解決了 SOFAMesh 的 DNS 尋址的問題。


感謝你們,但願此次演講能讓你們有所收穫。


視頻回放與資料下載

地址:https://tech.antfin.com/activities/2/review(點擊閱讀原文可跳轉到該網頁)


相關連接:

SOFA 文檔:  http://www.sofastack.tech/

SOFA:  https://github.com/alipay

SOFAMosn:

https://github.com/alipay/sofa-mosn

SOFAMesh:

https://github.com/alipay/sofa-mesh


640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1



來自 「 ITPUB博客 」 ,連接:http://blog.itpub.net/31560885/viewspace-2284592/,如需轉載,請註明出處,不然將追究法律責任。

轉載於:http://blog.itpub.net/31560885/viewspace-2284592/