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

Reddit的Envoy代理實踐

Reddit是個社交新聞站點,其使用者(也叫redditors)能夠瀏覽並且可以提交因特網上內容的連結或釋出自己的原創或有關使用者提交文字的帖子。其他的使用者可對釋出的連結進行高分或低分的投票,得分突出的連結會被放到首頁。
Reddit的工程師團隊以及產品複雜度在過去三年急劇上升。能有這樣的提升,是因為在Reddit後端基礎架構上進行了很多最佳化改進。一個主要的改進方面就是採用了面向服務的架構,其中最重要的部分是改進了服務發現與服務通訊。
隨著服務資料的增長,服務之間的互動以及遺傳系統變得越來越複雜。和在單個應用程式中進行功能除錯以及模組呼叫不同,工程師現在需要深入到多服務之間的RPC請求。和關註於異常處理、錯誤輸入這些通常問題不同,工程師現在需要更加關註客戶端請求行為以及如何透過重試機制、熔斷以及細粒度路由控制來進行適當防禦。
最近,我們選擇Envoy作為我們L4/L7的服務代理,用以努力解決開發與維護穩定產品服務過程中日益增長的需求。本文主要內容包括:
  • Reddit早期的服務通訊方式

  • 我們選擇Envoy的原因

  • 在我們基礎架構限制因素下,我們如何應用和管理Envoy的部署

網格化:Reddit服務發現基礎

 

自從我們開始從原有整體應用服務中分離功能並構建新服務,Reddit後端基礎架構就一直使用Airbnb的SmartStack作為基本的Service Mesh。選擇SmartStack的原因是它的設計以及使用場景非常符合我們的架構體系,使用它能夠讓我們很自然地轉變成面向服務的基礎架構。對這個架構進行簡要的瞭解有助於理解我們最終是如何遷移到Envoy以及如何降低任務本身的難度。
今天,我們大多數服務都跑在AWS AutoScaling Groups中的EC2實體上,每天服務的擴縮容都是透過SmartStack的Nerve元件進行服務註冊。Nerve是一個Ruby行程,作為sidecar執行在每個實體中,並將實體註冊到中央ZooKeeper叢集,而服務應用自身負責健康檢查並決定是否進行註冊。我們大多數服務都使用了Baseplate[1]這個開發框架,它提供了一些共享工具,例如health-check介面[2]用以直接對接Nerve,而對服務開發人員是透明的。
基本的Service Mesh還包括服務發現,用來給上游客戶端服務提供新的可用下游服務。和Nerve類似,Synapse也是執行在每個實體中的Ruby行程,用來管理服務端點的服務發現。Synapse從ZooKeeper中獲取Nerve推送的服務註冊串列,將服務端點入口寫入本地HAProxy的配置檔案。HAProxy同樣作為sidecar行程執行,負責請求代理以及下游服務流量負載均衡。

當我們大部分服務架構不斷更新時,Reddit中SmartStack的部署幾乎不需要進行更新,還穩定運行了3年的時間。服務註冊元件Nerve還作為內部工具,用來檢查AWS實體是否健康以及監控新主機的引導過程。儘管SmartStack穩定且成熟,但是我們不斷演進的系統開始觸達它立即可用的侷限性,因此我們決定調研評估Service Mesh生態,並確定是否能夠使用新技術替換SmartStack。

 

網格演進:遷移到Envoy

 

隨著這些年我們服務架構的演變,在SmartStack方面我們遇到幾個痛點,主要是在於它對單個元件缺乏控制。Nerve和Synapse只接受靜態配置,因此任何服務註冊更新(例如新增或者刪除服務),都需要Puppet配置的改變和更新。Synapse對接HAProxy寫配置功能只提供一些基本的路由定義,而我們有一些透過HAProxy觀察流量的上層需求,但它無法理解我們主要的內部協議Thrift。
服務之間的行為複雜性不斷加深,我們瞭解到開發人員被迫在應用程式程式碼中完成複雜的通訊行為。每個應用程式都開始在程式碼中管理下游服務的重試處理、超時、熔斷,有時甚至一個相同的端點需要接收來自4到5個上游客戶端的不同行為。我們知道這種方式是不可擴充套件的,我們需要像網路代理一樣在一個共享的網路層管理這些通訊行為。
既然我們確定了Service Mesh的標的,我們就需要找到最適合Reddit的方案。我們評估了很多代理和網格化方案,主要是關註如下幾個方面:
  • 效能:避免增加效能瓶頸,任何在代理層的效能損失都需要透過相當大的功能增益來彌補。我們主要是考慮的是資源利用率以及網路延遲。我們網格化方案是在每臺機器上以sidecar方式執行代理,所以我們需要的方案是能夠在每臺機器以及網路的每一跳上執行。

  • 功能:所有方案選項中最大的區分點就是代理是否支援L7層的Thrift協議。Thrift是我們服務內部使用的主要RPC協議,如果在service mesh中不支援這種行為控制,那和我們現在使用HAProxy進行基本的TCP負載均衡差別不大。我們將在下一小節討論這一點。

  • 整合和擴充套件性:還有個核心要求是實用的工具能夠進行奉獻或與請求整合,並且能夠擴充套件開箱即用的功能。網路代理需要能夠隨著Reddit的服務需求和開發人員的功能請求而演變。

 

Envoy以及它的生態系統滿足了我們遷移方案的所有需求。雖然我們需要完全改變服務發現棧以及在生產環境中使用新的流量代理,但是Envoy的低佔有率和可擴充套件性(特別是支援Thrift過濾器)為我們基礎架構的改進提供了重大的機會。下麵我們將介紹Envoy的部署方案以及在實際生產環境中的使用過程。

 

替換HAProxy:使用Envoy的第一步

 

前文提到過,HAProxy作為服務流量代理部署在Reddit的SmartStack中,只是它只能管控L4層的流量,而使用Envoy最大的不同就是它能夠為我們管控L7層的流量。雖然現在HTTP和gRPC都特別成熟,但Reddit的服務主要是使用Thrift,所以我們首先要確定的就是Envoy能夠支援Thrift。在那時,Turbine Labs剛剛宣佈他們將支援Envoy併為Envoy開發產品,我們註意到他們正在為Envoy做貢獻,所以我們去和他們協商在Envoy中合作開發支援Thrift。四個月後,Envoy能夠較好地支援Thrift,引入了Thrif代理、路由、請求/響應指標以及速率限制。
與此同時,我們內部主要致力於為生產服務部署和執行Envoy奠定基礎。 由於內部服務通訊不依賴這一層,我們在改變系統某一部分時必須小心翼翼,更不用說整個系統。經過深思熟慮,我們決定首先使用Envoy替代HAProxy作為基本的TCP代理,然後仍然使用Nerve和Synapse負責服務註冊和服務發現。這就意味著我們只會替換系統的一小部分,也意味著我們將不會使用Envoy的動態發現服務。為瞭解決這個問題,我們在Synapse中為Envoy的配置寫了一個配置生成器 ConfigGenerator[3]外掛,同時也寫了一些額外的配置指令碼,使用Envoy的熱重啟機制[4]來管理它。
這項工作使我們能夠保持大部分服務發現系統的完整性,同時仍然將Envoy投入生產環境,這反過來又為遷移本身提供了很大的靈活性。我們能夠一次為每個服務回滾代理變更,併在每臺伺服器上透過更改應用程式配置來管理使用Envoy端點與下游服務進行通訊。在遷移過程中,我們並行執行HAProxy和Envoy用於監聽不同的埠,使用Synapse管理它們的配置。這讓我們能夠為客戶端遷移每個服務,觀察行為並且在出現任務問題時進行即使回滾,同時,還能夠透過HAProxy的配置來審計Envoy的配置。經過兩個月,我們為每個服務部署了Envoy,替代HAProxy向下遊服務傳送請求,監控並確保沒有任務行為以及效能的差異。

遷移過程也不是一帆風順,在我們定製化Synapse與Envoy的整合以及它的靜態配置管理上出現過一些問題。Envoy的網路連線處理(尤其是熱重啟機制)與HAProxy有很大的不同,所以在我們應用程式連線控制程式碼中引發了一些非預期的錯誤。不過問題不大,沒有影響遷移過程,Envoy也穩定運行了將近4個月。
在效能方面,與HAProxy相比,Envoy對我們的服務延遲沒有產生可衡量的影響。HAProxy仍然作為sidecar執行,用來應對節日期間的緊急流量需求,而且我們的工程師人力有限,所以我們還不能衡量資源利用率對我們主機的影響。不過,Envoy在網路層面為我們提供了更豐富的可觀察性,特別是我們在一些內部服務開啟Thrift過濾器。感謝過濾器機制,在不需要修改應用程式程式碼的情況下,Envoy開始提供我們之前無法獲取的請求/響應指標。這些小而重要的提升以及整體的穩定性讓我們在2019年Service Mesh路線上充滿信心。

 

下一步

 

隨著Envoy在代理層面以及L4層流量管理的成功實施,我們將在2019年的前一段時間鞏固運營工具,以便開始真正利用Envoy的控制功能。我們計劃部署Envoy的發現服務API,該API由集中式配置儲存支援,可以為我們的Envoy部署帶來動態配置管理,也給開發人員提供介面在每個服務上管理這些配置。同時,對於內部服務我們會更多使用Kubernetes,所以Envoy部署部分在2019年早期將得到更多的開發,比較有意思的地方是我們會利用Envoy的路由管理工具將服務遷移到Kubernetes。
最後,雖然Envoy目前應用於我們的大多數後端服務通訊,但我們仍然將AWS ELB用於一些外部入口點,並使用HAProxy作為Reddit核心後端應用程式的主要外部負載平衡器和路由管理。在邊緣上執行Envoy將提供更多的可觀察性和服務路由控制,我們希望在繼續將服務從整體中分離出更小且更易於管理的服務時,能夠進行複雜的請求管理操作,例如遮蔽入站流量和邊緣流量轉移。
2018年Reddit在生產環境中實施Envoy是一項艱巨的任務,如果沒有大量的內外部支援就不可能做到這一點。我們要感謝Envoy社群建立和維護大量軟體,以及Turbine Labs(尤其是Mark McBride,TR Jordan和Stephan Zuercher)為Envoy的Thrift功能奠定基礎。如果沒有整個工程團隊的內部支援,尤其是u/alienth,u/cshoesnoo,u/NomDeSnoo和u/spladug,Envoy也不可能在Reddit成功實施。我們將繼續圍繞Reddit的網路可觀察性和控制進行開發,請持續關註。
相關連結:
  1. https://github.com/reddit/baseplate

  2. https://baseplate.readthedocs.io/en/stable/cli/healthcheck.html

  3. https://github.com/airbnb/synapse/tree/master/lib/synapse/config_generator

  4. https://blog.envoyproxy.io/envoy-hot-restart-1d16b14555b5

原文連結:https://redditblog.com/2018/12/18/envoy-proxy-at-reddit/

已同步到看一看
贊(0)

分享創造快樂