Netramesh - 輕量級服務網格解決方案

當我們從單體應用程式轉向微服務架構時,我們面臨著新的挑戰。

在單片應用程式中,通常很容易確定錯誤發生在系統的哪個部分。最有可能的是,問題出在單體應用程式本身的程式碼中,或出在資料庫中。但當我們開始尋找微服務架構的問題時,一切就不再那麼明顯了。我們需要找到請求從開始到結束的整個路徑,並從數百個微服務中選擇它。而且,其中許多還擁有自己的儲存設施,這也會導致邏輯錯誤,以及效能和容錯方面的問題。

Netramesh - 輕量級服務網格解決方案

我長期以來一直在尋找一種可以幫助解決此類問題的工具(我在 Habré 上寫過這一點: 1, 2),但最終我做了自己的開源解決方案。在本文中,我討論了服務網格方法的好處,並分享了用於其實現的新工具。

分散式追蹤是分散式系統中尋找錯誤問題的常見解決方案。但是,如果這種收集網路互動資訊的方法尚未在系統中實現,或者更糟的是,在系統的一部分中它已經正常工作,但在部分系統中卻不能正常工作,因為它還沒有添加到舊服務中,該怎麼辦?為了確定問題的確切根本原因,有必要全面了解系統中發生的情況。了解關鍵業務路徑中涉及哪些微服務尤其重要。

在這裡,服務網格方法可以為我們提供幫助,它將在低於服務本身運行的層級處理用於收集網路資訊的所有機制。這種方法使我們能夠攔截所有流量並對其進行動態分析。此外,應用程式甚至不需要了解任何相關資訊。

服務網格方法

服務網格方法的主要想法是在網路上添加另一個基礎設施層,這將允許我們做任何服務間互動的事情。大多數實現的工作原理如下:向每個微服務添加一個帶有透明代理的附加 sidecar 容器,服務的所有傳入和傳出流量都通過該容器傳遞。這正是我們可以進行客戶端平衡、應用安全策略、對請求數量施加限制以及收集有關生產中服務互動的重要資訊的地方。

Netramesh - 輕量級服務網格解決方案

Решения

這種方法已經有多種實作: Istio и 連結器d2。它們提供了許多開箱即用的功能。但同時,資源的開銷也很大。此外,運行此類系統的叢集越大,維護新基礎設施所需的資源就越多。在 Avito,我們營運的 kubernetes 叢集包含數千個服務實例(而且它們的數量仍在快速成長中)。在目前的實作中,Istio 每個服務實例消耗約 300Mb 的 RAM。由於有大量的可能性,透明平衡也會影響服務的整體回應時間(最多10ms)。

因此,我們仔細研究了我們現在需要什麼功能,並確定我們開始實施此類解決方案的主要原因是能夠透明地從整個系統收集追蹤資訊。我們也希望控制服務的交互,並對服務之間傳輸的標頭進行各種操作。

結果,我們做出了決定:  網網.

網網

網網 是一種輕量級服務網格解決方案,無論系統中的服務數量如何,都能夠無限擴展。

新解決方案的主要目標是低資源開銷和高效能。在主要功能中,我們立即希望能夠透明地將追蹤範圍傳送到我們的 Jaeger 系統。

如今,大多數雲端解決方案都是在 Golang 中實現的。當然,這是有原因的。在 Golang 中編寫與 I/O 非同步工作並根據需要跨核心擴展的網路應用程式既方便又簡單。而且,同樣非常重要的是,性能足以解決這個問題。這就是為什麼我們也選擇Golang。

Производительность

我們集中精力實現生產力最大化。對於部署在每個服務執行個體旁的解決方案,需要少量的 RAM 和 CPU 時間消耗。當然,反應延遲也應該很小。

讓我們看看我們得到了什麼結果。

內存

Netramesh 在沒有流量的情況下消耗約 10Mb,每個執行個體負載高達 50 RPS 時最大消耗 10000Mb。

在我們擁有數千個實例的叢集中,Istio Envoy 代理程式始終消耗約 300Mb 的資源。這不允許它擴展到整個叢集。

Netramesh - 輕量級服務網格解決方案

Netramesh - 輕量級服務網格解決方案

使用 Netramesh,我們的記憶體消耗減少了約 10 倍。

中央處理器

負載下CPU使用率相對相等。這取決於單位時間內向 sidecar 發出的請求數量。峰值時每秒 3000 個請求的值:

Netramesh - 輕量級服務網格解決方案

Netramesh - 輕量級服務網格解決方案

還有更重要的一點:Netramesh-一種沒有控制平面、沒有負載的解決方案,不消耗CPU時間。使用 Istio,sidecar 總是會更新服務端點。結果,我們可以在沒有負載的情況下看到這張圖:

Netramesh - 輕量級服務網格解決方案

我們使用 HTTP/1 進行服務之間的通訊。透過 Envoy 代理程式時,Istio 的回應時間增加了 5-10 毫秒,這對於準備在毫秒內回應的服務來說是相當多的。使用 Netramesh,這個時間已減少到 0.5-2 毫秒。

可擴展性

每個代理程式消耗的資源量很少,因此可以將其放置在每個服務旁邊。 Netramesh 特意創建為沒有控制平面組件,只是為了保持每個 sidecar 的輕量化。通常在服務網格解決方案中,控制平面將服務發現資訊分發到每個 sidecar。隨之而來的是有關超時和平衡設定的資訊。所有這些都允許您做很多有用的事情,但不幸的是,它使 sidecar 的尺寸變得臃腫。

服務發現

Netramesh - 輕量級服務網格解決方案

Netramesh 並沒有增加任何額外的服務發現機制。所有流量均透過 netra sidecar 透明代理。

Netramesh 支援 HTTP/1 應用協定。為了定義它,使用了可配置的連接埠清單。通常,系統有多個連接埠用於進行 HTTP 通訊。例如,我們使用80、8890、8080來進行服務和外部請求的交互,在這種情況下,可以使用環境變數來設定它們。 NETRA_HTTP_PORTS.

如果使用 Kubernetes 作為編排器及其 Service 實體機制來進行服務之間的叢集內通信,那麼該機制保持完全相同。首先,微服務使用 kube-dns 取得服務 IP 位址並開啟與其的新連線。此連線首先與本機 netra-sidecar 建立,所有 TCP 封包最初到達 netra。接下來,netra-sidecar 與原始目的地建立連接。節點上 pod IP 上的 NAT 與沒有 netra 時完全相同。

分散式追蹤和上下文轉發

Netramesh 提供傳送有關 HTTP 互動的追蹤範圍所需的功能。 Netra-sidecar 解析 HTTP 協議,測量請求延遲,並從 HTTP 標頭中提取必要的資訊。最終,我們在一個 Jaeger 系統中獲得了所有痕跡。對於細粒度的配置,也可以使用官方函式庫提供的環境變量 jaeger go 庫.

Netramesh - 輕量級服務網格解決方案

Netramesh - 輕量級服務網格解決方案

但有一個問題。在服務產生並發送特殊的 uber 標頭之前,我們不會在系統中看到連接的追蹤跨度。而這正是我們需要快速找到問題的原因。 Netramesh 再次提供了解決方案。代理程式讀取 HTTP 標頭,如果它們不包含 uber 追蹤 ID,則產生一個。 Netramesh 還將有關傳入和傳出請求的資訊儲存在 sidecar 中,並透過使用必要的傳出請求標頭豐富它們來匹配它們。您在服務中所需要做的就是僅發送一個標頭 X-Request-Id,可以使用環境變數進行配置 NETRA_HTTP_REQUEST_ID_HEADER_NAME。若要控制 Netramesh 中上下文的大小,可以設定下列環境變數: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (上下文將被儲存的時間)和 NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (上下文清理的頻率)。

也可以透過使用特殊的會話令牌標記它們來組合系統上的多個路徑。 Netra 讓您安裝 HTTP_HEADER_TAG_MAP 將 HTTP 標頭轉換為對應的追蹤範圍標記。這對於測試特別有用。通過功能測試後,可以透過對應的會話金鑰來查看系統的哪些部分受到了過濾的影響。

確定請求來源

若要確定請求的來源,您可以使用自動新增標頭和來源的功能。使用環境變數 NETRA_HTTP_X_SOURCE_HEADER_NAME 您可以指定將自動安裝的標頭名稱。透過使用 NETRA_HTTP_X_SOURCE_VALUE 您可以設定為所有傳出請求設定 X-Source 標頭的值。

這使得這個有用的報頭可以在整個網路中均勻分佈。然後您可以在服務中使用它並將其添加到日誌和指標中。

流量路由和 Netramesh 內部結構

Netramesh 由兩個主要元件組成。第一個是 netra-init,設定網路規則來攔截流量。他用 iptables 重定向規則 攔截 sidecar 上的全部或部分流量,這是 Netramesh 的第二個主要組件。您可以設定需要攔截傳入和傳出 TCP 會話的連接埠: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS.

該工具還有一個有趣的功能—機率路由。如果您專門使用 Netramesh 來收集追蹤範圍,那麼在生產環境中您可以節省資源並使用變數啟用機率路由 NETRA_INBOUND_PROBABILITY и NETRA_OUTBOUND_PROBABILITY (從 0 到 1)。預設值為 1(攔截所有流量)。

攔截成功後,netra sidecar接受新連線並使用 SO_ORIGINAL_DST 套接字選項來取得原始目的地。然後,Netra 打開與原始 IP 位址的新連接,並在雙方之間建立雙向 TCP 通信,以偵聽通過的所有流量。如果連接埠定義為 HTTP,Netra 會嘗試解析並追蹤它。如果 HTTP 解析失敗,Netra 將回退到 TCP 並透明地代理位元組。

建構依賴圖

在 Jaeger 中收到大量追蹤資訊後,我想獲得系統中互動的完整圖。但是,如果您的系統負載很大並且每天累積數十億個追蹤跨度,那麼聚合它們就不是一件容易的任務。有一個官方的方法可以做到這一點: Spark 依賴項。然而,建立完整的圖表需要幾個小時,並將迫使您從 Jaeger 下載過去 24 小時的整個資料集。

如果您使用 Elasticsearch 來儲存追蹤範圍,則可以使用 一個簡單的 Golang 實用程序,它將使用 Elasticsearch 的特性和功能在幾分鐘內建立相同的圖表。

Netramesh - 輕量級服務網格解決方案

如何使用Netramesh

Netra 可以輕鬆添加到任何運行任何編排器的服務中。你可以看一個例子 這裡.

目前,Netra 不具備自動將 sidecar 實現到服務的能力,但有實現計劃。

Netramesh 的未來

主要目標 網網 是為了實現最小的資源成本和高效能,提供服務間通訊的可觀察和控制的基本能力。

未來,Netramesh將支援除HTTP之外的其他應用層協定。 L7路由將在不久的將來推出。

如果您遇到類似問題,請使用 Netramesh,並寫信給我們提出問題和建議。

來源: www.habr.com

添加評論