如何在Kubernetes中使用OpenTelemetry的沙盒
譯文譯者 | 李睿
審校 | 重樓
51CTO讀者成長計劃社群招募,咨詢小助手(微信號:CTOjishuzhan)
OpenTelemetry項目于2019年推出,是之前就已經(jīng)存在的OpenTracing和OpenCensus這兩個項目的結(jié)合,其目標是成為從基于分布式微服務的應用程序中提取遙測數(shù)據(jù)的單一開放標準。該項目是一個規(guī)范、工具和庫的集合,旨在幫助以日志、度量和跟蹤的形式從應用程序收集遙測數(shù)據(jù),然后可以將其轉(zhuǎn)發(fā)到支持聚合、可視化和內(nèi)省這些數(shù)據(jù)的可觀察性工具。
本文將探索一個利用OpenTelemetry(縮寫為OTel)的新用例,特別是由OTel啟用的分布式場景傳播,以創(chuàng)建稱為“沙盒”的輕量級環(huán)境,然后可以用于以可擴展的方式啟用各種形式的微服務測試。此外,還將研究哪種類型的應用程序最自然地使用這個模型,以及它如何幫助用戶在開發(fā)生命周期的早期獲得高質(zhì)量的測試反饋。
一、超越OpenTelemetry的可觀察性
OTel的設計用例之一是跟蹤。跟蹤提供了對分布式系統(tǒng)如何處理用戶或應用程序請求的理解,該分布式系統(tǒng)涉及許多獨立的組件。
1.跟蹤的工作原理
每個微服務在處理請求時,都會發(fā)出一些被稱為“span”的信息,其中包含一些關(guān)于它正在處理的請求的場景。而一旦所有這些span被發(fā)送到某個后端,它們就可以拼接在一起,告訴整個請求流,這被稱為“跟蹤”。跟蹤可用于了解特定請求發(fā)生了什么,也可用于在聚合場景中發(fā)現(xiàn)和處理可能影響某些請求子集的模式。這些關(guān)于請求通過由多個微服務組成的系統(tǒng)所經(jīng)過路徑的信息,可以有效地隔離和推斷生產(chǎn)問題發(fā)生時的根本原因。
2.廣義場景傳播
當查看下面的圖表時,可以看到每個單獨的服務只發(fā)出它自己的“span”,這與它在本地處理請求的方式有關(guān)。因此,為了將屬于單個請求的范圍綁定到單個跟蹤中,需要在這些標識請求本身的服務之間傳播某種形式的場景,這被稱為跟蹤場景。
OTel通過它的庫來實現(xiàn)這一點,它負責沿著同步/異步請求鏈在服務之間傳遞跟蹤標識符。更重要的是,對于一些動態(tài)語言,它只需要放入相應的OTel庫,該庫“自動檢測”字節(jié)代碼以透明地執(zhí)行分布式場景傳播。
這種沿請求流傳播場景片段的想法雖然起源于跟蹤,但并不是專門與跟蹤相關(guān)。
它是一種更通用的機制,可以利用它在微服務之間傳播更多與跟蹤相關(guān)的信息。有關(guān)Baggage規(guī)格的解釋明確地說明了這一點。
該規(guī)范定義了一個標準,用于表示和傳播一組與分布式請求或工作流執(zhí)行相關(guān)的應用程序定義的屬性。這是獨立于跟蹤場景規(guī)范的。無論是否使用分布式跟蹤,都可以使用Baggage。
該規(guī)范標準化了應用程序定義的屬性的表示和傳播。與其相反,跟蹤場景規(guī)范標準化了啟用分布式跟蹤場景所需元數(shù)據(jù)的表示和傳播。
現(xiàn)在開始利用這個機制來實現(xiàn)超越遙測和追蹤的用例。
二、使用OpenTelemetry的沙盒
沙盒是一種輕量級環(huán)境,可用于測試和驗證對堆棧中微服務子集的更改。沙盒與傳統(tǒng)環(huán)境的關(guān)鍵區(qū)別之一是,沙盒使用一組未更改的共享依賴項(其名稱為“基線”),以測試一些已經(jīng)更改的服務。
這個屬性使得沙盒資源的效率很高,并且設置起來也很快。反過來,這意味著用戶可以啟動一個沙盒來測試單個提交,或者對每個微服務的單個更改,這在具有中等規(guī)模(>20左右)的傳統(tǒng)微服務環(huán)境中變得成本高昂。
這種方法的另一個關(guān)鍵優(yōu)勢是,這些沙盒可以部署到現(xiàn)有的環(huán)境中,例如部署或生產(chǎn)環(huán)境中,以針對最新的依賴項測試更改,從而消除了過時依賴關(guān)系的問題,以及由于它們之間的差異而不得不在“更高”的環(huán)境中反復重新測試的問題。
以下將了解如何利用OTel中的分布式場景傳播在Kubernetes中創(chuàng)建沙盒。
1.請求路由
由于采用OTel庫和工具,一旦應用程序能夠跨請求攜帶任意場景片段,現(xiàn)在就可以開始考慮使用它來隔離請求及其相互影響。
可以通過利用請求級多租戶來創(chuàng)建沙盒。這是通過為每個請求分配一個特定的“租戶”來完成的。租戶只是指與每個請求相關(guān)聯(lián)的標識符,告訴系統(tǒng)如何處理和路由特定的請求。在下面的示例中,租賃由“租戶”標頭(或者說L7協(xié)議元數(shù)據(jù))指定,并具有一個值,該值標識應將其路由到服務的哪個特定測試版本。該租賃元數(shù)據(jù)使用OTel中的Baggage機制在服務之間傳遞,并在后臺使用HTTP/gRPC標頭。
以一個簡單的微服務應用程序為例,它包含一個前端和后端,可以設置如下內(nèi)容:
可以教會前端根據(jù)租約有條件地將正在發(fā)出的出站請求路由到后端。在Kubernetes中,做出路由決策是很簡單的,因為有幾種機制可以在應用程序不參與決策的情況下處理它。例如,可以使用服務網(wǎng)格(如Istio),這使得這種路由操作很容易在網(wǎng)格本身的規(guī)則中表示。創(chuàng)建一個Sidecar容器,利用特使或自定義代碼來攔截請求,并在每個微服務上透明地代理請求,這是非常簡單的。
上面創(chuàng)建的這個設置也可以擴展到測試中的多個工作負載。這種設置可以很容易地在現(xiàn)有的登臺和生產(chǎn)集群中進行設置,只需很少的工作。登臺和生產(chǎn)通常已經(jīng)有一個持續(xù)部署(CD)流程,用于更新服務的穩(wěn)定版本(基線),并且在同一集群中部署這些沙盒們能夠在不測試這些依賴關(guān)系時重用它們。
只需使用上面所示的請求隔離,這個沙盒就可以用于測試對無狀態(tài)服務的更改、運行API測試等。但是它仍然有局限性,因為還沒有解決隔離可能產(chǎn)生副作用的數(shù)據(jù)突變、通過消息隊列隔離異步工作流或調(diào)用第三方API的問題。以下將解決這些問題,使沙盒更加健壯,并能夠在微服務環(huán)境中支持更多類型的測試。
2.狀態(tài)隔離
使用這種方法在更多用例中執(zhí)行更復雜的測試的一個重要步驟是解決狀態(tài)隔離問題。在這里需要注意的一點是,并不是每個涉及微服務測試的用例都需要額外的狀態(tài)隔離。例如,在人工或使用自動化為特定流運行API或E2E測試時,如果在特定流中,能夠創(chuàng)建和清理在測試中使用的實體,那么已經(jīng)實現(xiàn)了氣密測試,而實際上不需要額外的狀態(tài)隔離。
但是,在有些情況下需要額外的隔離,例如在數(shù)據(jù)存儲上執(zhí)行DDL更改,或者如果可能執(zhí)行一些有副作用的突變。在這些情況下,可能希望部署可能受到影響的數(shù)據(jù)存儲的隔離版本,并使沙盒工作負載使用它們,而不是基線環(huán)境使用的數(shù)據(jù)存儲。
人們可以看到,在實踐中,盡可能地使用邏輯隔離而不是基礎(chǔ)設施隔離要有效得多。例如,在像MySQL和PostgreSQL這樣的數(shù)據(jù)庫以及大多數(shù)托管云計算數(shù)據(jù)庫中,數(shù)據(jù)基礎(chǔ)設施本身提供了一個內(nèi)置的邏輯隔離概念。這種邏輯隔離的選擇使沙盒保持輕量級、資源高效,并且仍然能夠在幾秒鐘內(nèi)啟動,而這對于大多數(shù)情況來說已經(jīng)足夠了。當然,如果有必要,總是可以啟動新的物理基礎(chǔ)設施來與沙盒相關(guān)聯(lián),但在實踐中發(fā)現(xiàn)這種需求非常罕見。
建立基礎(chǔ)設施只是解決方案的一部分;播種數(shù)據(jù)是關(guān)鍵,必須在環(huán)境啟動時/之前執(zhí)行??梢詫⑺羞@些短暫數(shù)據(jù)存儲的生命周期與環(huán)境本身的生命周期聯(lián)系起來,也可以選擇設置和維護預先預熱的數(shù)據(jù)存儲,這些數(shù)據(jù)存儲是根據(jù)需要提供給服務的測試版本的。后一種使用預熱測試數(shù)據(jù)存儲的方法可以幫助準備好高質(zhì)量的數(shù)據(jù),并且在實踐中,即使對于大型微服務堆棧,需要保留的此類測試數(shù)據(jù)存儲數(shù)量也不是特別多。一些沙盒方法的高級用戶更進一步,實現(xiàn)了將租賃與特定類型的數(shù)據(jù)集相關(guān)聯(lián)的機制,例如在Uber關(guān)于SLATE的博客文章中。
使用短暫的隔離數(shù)據(jù)存儲,可以提供高質(zhì)量的數(shù)據(jù)進行開發(fā)/測試,同時確保在環(huán)境之外沒有可見的副作用。使用邏輯隔離的想法特別有助于擴展沙盒的數(shù)量,同時將額外的基礎(chǔ)設施或運營成本降至最低。與環(huán)境選擇最高隔離級別作為默認隔離級別的流行概念相反,可以根據(jù)應用程序的用例和性質(zhì)為沙盒選擇最合適的隔離類型。
3.消息隊列
消息隊列在現(xiàn)代微服務堆棧中無處不在,當涉及到這些沙盒時,它提出了一個有趣的挑戰(zhàn)??紤]到消息隊列,消息隊列的大多數(shù)(如果不是全部)實現(xiàn)允許在消息中設置一些報頭/元數(shù)據(jù)。這意味著消息本身包含一些關(guān)于它們來自哪里的請求/流的標識的信息,這提供了一些關(guān)于如何進行消息路由的想法。
對于消息隊列,通常也首選邏輯隔離,而不是物理隔離。因此,如果Kafka是消息隊列,更愿意設置單獨的主題,而不是建立新的孤立的Kafka集群。
雖然這個解決方案保證有效,但實際上,在大型微服務環(huán)境中有許多生產(chǎn)者和消費者,這使得它不太理想,這是因為它可能最終要求孤立地支持每個微服務。一種更清潔的隔離方法是教會消費者更有選擇性地以“租戶意識”的方式消費。
這種讓使用者能夠感知租戶的方法需要在應用程序?qū)舆M行一些更改。該功能可以很容易地封裝到一個“消息路由器”庫中,可以與使用者客戶端一起使用。這個庫將根據(jù)使用者服務的標識(它是基線嗎?它屬于哪個沙盒?)和包含租賃信息的消息元數(shù)據(jù)。這個庫需要了解集群中不同沙盒的狀態(tài)信息,以便在每個使用者中做出決策,這要求它與運行在Kubernetes集群中的某些路由控制器(或服務網(wǎng)格)進行對接。
這種方法解決了一個長期存在的問題,即消息隊列在微服務堆棧中難以測試,它為具有租戶意識的消費者提供了一種多路復用不同流的干凈方式,并且不需要額外的基礎(chǔ)設施設置,這使得它的設置非常快。
4.第三方API
現(xiàn)代微服務棧利用許多第三方API和外部服務來提供重要的功能,例如支付、集成等,這些功能可以通過外部API端點和Webhook與Kubernetes中的微服務進行對接。在第三方API中,傳播租戶信息的方法因系統(tǒng)而異。
在許多情況下,這些API只是“即發(fā)即棄”,或者具有由應用程序本身控制的副作用,在這種情況下,可能不需要通過外部系統(tǒng)進行租賃傳播。
在需要外部系統(tǒng)回調(diào)或Webhook在微服務中執(zhí)行一些額外處理的系統(tǒng)中,HTTP回調(diào)URL中的查詢參數(shù)可以用于傳播租賃信息。Kubernetes集群內(nèi)部的路由機制將查找包含租賃信息的特定查詢字符串,并使用該查詢字符串將這些回調(diào)請求路由到適當?shù)纳澈泄ぷ髫撦d。
在實踐中,這種機制通常需要對應用層進行一些較小的修改。微服務還必須知道它自己的租期。也就是說,擁有關(guān)于它所屬的沙盒的信息,這樣它就可以在回調(diào)時設置適當?shù)淖馄谠獢?shù)據(jù)。
三、在實踐中實現(xiàn)沙盒
沙盒方法已經(jīng)在Lyft、Uber和Doordash的數(shù)百個微服務中大規(guī)模實現(xiàn),這允許一個非常有效和可擴展的機制來快速測試和迭代。用戶在與企業(yè)合作中吸取了一些經(jīng)驗教訓,可以幫助他們在自己的基礎(chǔ)設施中采用沙盒。
在實踐中,對于想要開始采用這種方法的用戶,驗證的最簡單的方法是首先將沙盒集成到一些微服務的持續(xù)集成(CI)流程中。這些沙盒可以在現(xiàn)有的登臺環(huán)境中創(chuàng)建,這只需要很少的額外設置,并消除了與共享登臺環(huán)境相關(guān)的瓶頸。從這一點開始,隨著OTel在企業(yè)內(nèi)的采用和場景傳播中的空白被填補,很容易擴展沙盒,以在不同微服務之間進行變更的預合并測試、端到端測試和性能測試。隨著采用率的增長,隨著越來越多的用例可以更快、更容易地使用沙盒解決,對額外測試環(huán)境或staging環(huán)境的需求急劇下降是很典型的。
此外還發(fā)現(xiàn),服務之間的合并前測試,例如將屬于不同服務的測試沙盒放在一起,并通過它們運行流量,在開發(fā)生命周期中非常有用,并且在開發(fā)迭代和反饋方面比目前常見的合并后測試要快得多。
在生產(chǎn)環(huán)境中使用沙盒進行測試是終極目標,它最終能夠完全消除分段。一旦租賃控制和數(shù)據(jù)隔離機制在組織內(nèi)足夠成熟,這最終是可能的,但對于希望使用沙盒的組織來說,這通常不是最佳的起點。
雖然大多數(shù)微服務通信模式都很適合這個范例,但也有一些模式是困難的,例如,測試Kubernetes基礎(chǔ)設施組件或在自定義協(xié)議上使用低級網(wǎng)絡的組件。對于這些情況,更傳統(tǒng)的設置環(huán)境的方式或不同的隔離方法可能比使用沙盒更合適。
四、結(jié)論
本文探索了沙盒的范例,沙盒是一種利用請求級隔離來提供可擴展的微服務測試輕量級環(huán)境。還研究了在內(nèi)部實現(xiàn)有效沙盒解決方案的不同技術(shù),例如使用OTel傳播場景、請求路由、狀態(tài)隔離以及處理消息隊列和第三方API。最后還研究了對于希望在內(nèi)部實現(xiàn)沙盒的組織的一些實際考慮。
沙盒方法已經(jīng)在一些行業(yè)中被有效地使用,以幫助加快和改進開發(fā)生命周期。Signadot正在構(gòu)建一個Kubernetes原生解決方案,使創(chuàng)建和部署沙盒變得容易,能夠幫助實現(xiàn)這一點。
原文鏈接:https://dzone.com/articles/sandboxes-in-kubernetes-using-opentelemetry