爲Envoy v2構建Kubernetes Edge(Ingress)控制平面

爲Envoy v2構建Kubernetes Edge(Ingress)控制平面

作者:Daniel Bryant,Datawire產品架構師;Flynn,Datawire Ambassador首席開發者;Richard Li,Datawire首席執行官兼聯合創始人

Kubernetes已經成爲基於容器的微服務應用程序的事實上的運行引擎,但是這個編排框架本身並不提供運行分佈式系統所需的所有基礎結構。微服務通常通過第7層協議,如HTTP、gRPC或WebSockets,進行通信,因此能夠制定路由決策,操作協議元數據,以及在此層進行觀察至關重要。然而,傳統的負載平衡器和邊緣代理主要關注L3/4流量。這就是Envoy Proxy發揮作用的地方。

Envoy代理由Lyft工程團隊從頭開始設計爲通用數據平面,用於當今分佈式,以L7爲中心的世界,廣泛支持L7協議,用於管理其配置的實時API,一流的可觀察性,在小內存空間內實現高性能。然而,Envoy龐大的功能集和操作靈活性也使其配置非常複雜 - 從查看其豐富但冗長的控制平面語法可以看出這一點。

通過開源Ambassador API網關,我們想要解決創建新控制平面的挑戰,該控制平面側重於在Kubernetes集羣中部署Envoy作爲前向邊緣代理的用例,採用Kubernetes operator慣用的方式。在本文中,我們將介紹Ambassador設計的兩個主要迭代,以及我們如何將Ambassador與Kubernetes相結合。

2019年之前的Ambassador:Envoy v1 API、Jinja模板文件和熱重啓

Ambassador本身作爲Kubernetes服務部署在容器中,使用添加到Kubernetes Services的註釋作爲其核心配置模型。此方法使應用程序開發者能夠將路由作爲Kubernetes服務定義的一部分進行管理。由於當前Ingress API規範的限制,我們明確決定採用這種方式,我們也喜歡擴展Kubernetes服務的簡單性,而不是引入另一種自定義資源類型。這裏可以看到Ambassador註釋的一個例子:

kind: Service
apiVersion: v1
metadata:
  name: my-service
  annotations:
    getambassador.io/config: |
      ---
        apiVersion: ambassador/v0
        kind:  Mapping
        name:  my_service_mapping
        prefix: /my-service/
        service: my-service
spec:
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

將這個簡單的Ambassador註釋配置轉換爲有效的Envoy v1配置並不是一項簡單的任務。按照設計,Ambassador的配置不是基於與Envoy配置相同的概念模型 - 我們故意想要聚合和簡化操作和配置。因此,將一組概念轉換爲另一組概念涉及Ambassador內部的相當多的邏輯。

在Ambassador的第一次迭代中,我們創建了一個基於Python的服務,該服務監視Kubernetes API以更改Service對象。當檢測到新的或更新的Ambassador註釋時,這些註釋從Ambassador語法轉換爲中間表示(intermediate representation,IR),其體現了我們的核心配置模型和概念。接下來,Ambassador將此IR轉換爲Envoy配置,該配置在運行的Ambassador k8s服務相關聯的pod中被保存爲文件。Ambassador然後“熱重啓”在Ambassador pod內運行的Envoy進程,這引發了新配置的加載。

這個初始實現有很多好處。所涉及的機制基本上很簡單,將Ambassador配置轉換爲Envoy配置是可靠的,Envoy基於文件的熱重啓集成是可靠的。

但是,這一版本的Ambassador也面臨着顯着的挑戰。首先,雖然熱啓動對我們大多數客戶的用例有效,但速度並不快,一些客戶(特別是那些具有大量應用程序部署的客戶)發現它限制了更改配置的頻率。熱重啓也可以丟棄連接,尤其是長期連接,如WebSockets或gRPC流。

但更重要的是,IR的第一次實施允許快速原型設計,但有點原始,事實證明很難做出實質性的改變。雖然從一開始就是一個痛點,但當Envoy轉向Envoy v2 API時,它成了一個關鍵問題。顯然,v2 API將爲Ambassador提供許多好處 - 正如Matt Klein在他的博客文章中概述的“通用數據平面API” - 包括訪問新功能和上述連接丟棄問題的解決方案,但同時明確表示現有的IR實施無法實現跨越式發展。

Ambassador >= v0.50:Envoy v2 API(ADS)、使用KAT測試和Golang

在與Ambassador社區協商後,Datawire團隊在2018年對Ambassador內部進行了重新設計。這是由兩個關鍵目標驅動的。首先,我們希望集成Envoy的v2配置格式,這將支持SNI、速率限制和gRPC身份驗證API等功能。其次,我們還希望對Envoy配置進行更強大的語義驗證,因爲它的複雜性越來越高(特別是在大規模應用程序部署時)。

初始階段

我們首先通過多通道編譯器對Ambassador內部進行重組。類層次結構是爲了更密切地反映Ambassador配置資源、IR和Envoy配置資源之間的關注點分離(separation of concerns)。Ambassador的核心部分也進行了重新設計,以促進Datawire以外社區的貢獻。我們決定採用這種方法有幾個原因。首先,Envoy Proxy是一個非常快速發展的項目,我們意識到我們需要一種方法,即看似微小的Envoy配置變更不會導致Ambassador內部的重新設計。此外,我們希望能夠提供配置的語義驗證。

當我們開始與Envoy v2更緊密地合作時,很快就發現了測試挑戰。隨着Ambassador支持越來越多的功能,Ambassador處理不太常見但完全有效的功能組合時出現了越來越多的漏洞。這促使創建一個新的測試要求,這意味着Ambassador的測試套件需要重新設計,以自動管理許多功能組合,而不是依靠人手單獨編寫每個測試。此外,我們希望測試套件快速,以最大限度地提高工程效率。

因此,作爲Ambassador重構的一部分,我們引入了Kubernetes驗收測試(KAT)框架。KAT是一個可擴展的測試框架:

  • 將一堆服務(與Ambassador一起)部署到Kubernetes集羣
  • 針對啓動的API運行一系列驗證查詢
  • 對這些查詢結果執行一堆認定

KAT專爲性能而設計 - 它預先批量測試設置,然後在步驟3中與高性能客戶端異步運行所有查詢。KAT中的流量驅動程序使用Telepresence在本地運行,這使得調試問題變得更加容易。

將Golang引入Ambassador堆棧

隨着KAT測試框架到位,我們很快遇到了Envoy v2配置和熱重啓的一些問題,這提供了切換到使用Envoy的聚合發現服務(ADS)API而不是熱重啓的機會。這完全消除了重新配置更改的要求,我們發現這可能導致在高負載或長期連接下斷開連接。

然而,當我們考慮轉向ADS時,我們遇到了一個有趣的問題。ADS並不像人們想象的那麼簡單:在向Envoy發送更新時存在明確的排序依賴性。Envoy項目具有排序邏輯的參考實現,但僅限於Go和Java,而Ambassador主要使用Python。我們掙扎了一點,決定最簡單的方法是接受我們世界的多語言性質,並使用Go來實施我們的ADS。

我們還發現,在KAT的情況下,我們的測試已經達到了Python在許多網絡連接中的性能受到限制的程度,因此我們在這裏利用Go,主要使用Go編寫KAT的查詢和後端服務。畢竟,當你已經投入採取了Golang,另一個依賴是什麼?

通過新的測試框架、新的IR生成有效的Envoy v2配置和ADS,我們認爲我們完成了0.50Ambassador的主要體系結構更改。唉,我們又遇到了一個問題。在Azure Kubernetes服務上,不再檢測到Ambassador註釋更改。

與高度響應的AKS工程團隊合作,我們能夠確定問題 - 在AKS中的Kubernetes API服務器通過一系列代理公開,要求客戶端更新,以瞭解如何使用API的FQDN連接服務器,這是通過AKS中的變異webhook提供。不幸的是,官方Kubernetes Python客戶端沒有對此功能的支持,所以這是我們選擇切換到Go而不是Python的第三個原因。

這提出了一個有趣的問題,“爲什麼不放棄所有的Python代碼,只是完全用Go重寫Ambassador?”這是一個有效的問題。重寫的主要問題是Ambassador和Envoy在不同的概念層面上運作,而不是簡單地用不同的語法表達相同的概念。確信我們已經用新語言表達了概念橋樑並不是一個微不足道的挑戰,如果沒有真正優秀的測試覆蓋範圍就無法實行。

在這一點上,我們使用Go覆蓋非常具體、包含良好的函數,可以更容易地驗證它們的正確性,以便我們可以驗證完整的Golang重寫。在將來,誰知道?但是對於0.50.0,這個功能分坼讓我們既利用Golang的優勢,又讓我們對已經在0.50的所有變化保持更多信心。

得到的教訓

我們在建立Ambassador 0.50的過程中學到了很多東西。我們的一些關鍵要點:

  • Kubernetes和Envoy是非常強大的框架,但它們也是極其快速移動的目標 - 有時候無法替代閱讀源代碼並與維護者交談(幸運的是,所有人都非常容易訪問!)
  • Kubernetes/Envoy生態系統中最受支持的庫是用Go編寫的。雖然我們喜歡Python,但我們不得不採用Go,這樣我們就不會被迫自己維護太多的組件。
  • 有時需要重新設計測試工具來推動軟件的發展。
  • 重新設計測試工具的實際成本通常是將舊測試移植到新的線束實現中。
  • 爲邊緣代理用例設計(和實現)一個有效的控制平臺一直是一個挑戰,來自Kubernetes、Envoy和Ambassador的開源社區的反饋非常有用。

將Ambassador遷移到Envoy v2配置和ADS API是一個漫長而艱難的過程,需要大量的架構和設計討論,以及大量編碼,但結果的早期反饋是積極的。Ambassador 0.50現已發佈,因此你可以使用參加測試,並在我們的Slack頻道Twitter上與社區分享你的反饋。


KubeCon + CloudNativeCon中國論壇提案徵集(CFP)2月22日截止

KubeCon + CloudNativeCon 論壇讓用戶、開發人員、從業人員匯聚一堂,面對面進行交流合作。與會人員有 Kubernetes、Prometheus 及其他雲原生計算基金會 (CNCF) 主辦項目的領導,和我們一同探討雲原生生態系統發展方向。

Open Source Summit中國提案徵集(CFP)2月22日截止

在Open Source Summit中國,與會者將共同合作及共享信息,瞭解最新和最有趣的開源技術,包括Linux、IoT、區塊鏈、AI、網絡等;並獲得如何在開源社區中導向和引領的信息。

大會日期:

  • 提案徵集截止日期:太平洋標準時間 2 月 22 日,星期五,晚上 11:59
  • 提案徵集通知日期:2019 年 4 月 8 日
  • 會議日程通告日期:2019 年 4 月 10 日
  • 會議活動舉辦日期:2019 年 6 月 24 至 26 日

提醒:這是一場社區會議。因此,讓我們儘量避開公然推銷產品和/或供應商銷售宣傳。

KubeCon + CloudNativeCon和Open Source Summit贊助方案出爐

KubeCon + CloudNativeCon和Open Source Summit多元化獎學金現正接受申請

KubeCon + CloudNativeCon和Open Source Summit即將首次合體落地中國

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章