Istio Circuit Breaker:停用故障的容器

假期結束了,我們帶著 Istio 服務網格系列的第二篇文章回來了。

Istio Circuit Breaker:停用故障的容器

今天的主題是Circuit Breaker,翻譯成俄語電氣工程的意思是“斷路器”,通俗的說法就是“斷路器”。 僅在 Istio 中,該機器不會斷開短路或過載電路,但會斷開故障容器。

理想情況下這應該如何運作

當微服務由 Kubernetes 管理時(例如在 OpenShift 平台內),它們會根據負載自動擴展和縮小。 由於微服務在 Pod 中運行,因此一個端點上可以有容器化微服務的多個實例,Kubernetes 將在它們之間路由請求和負載平衡。 而且 - 理想情況下 - 所有這一切都應該完美地運作。

我們記得微服務很小而且短暫。 短暫性在這裡意味著出現和消失的容易程度,但常常被低估。 Pod 中另一個微服務實例的誕生和消亡是意料之中的事情,OpenShift 和 Kubernetes 很好地處理了這個問題,一切都運作良好 - 但同樣是在理論上。

它是如何運作的

現在想像一下,微服務的一個特定實例(即容器)已變得不可用:要么它不響應(錯誤 503),要么更令人不快的是,它響應了,但速度太慢。 換句話說,它會出現故障或不回應請求,但不會自動從池中刪除。 這種情況該怎麼辦? 要重試嗎? 我應該將其從路由方案中刪除嗎? 「太慢」是什麼意思──具體有多少,由誰決定? 也許先休息一下,稍後再試? 如果是的話,多久之後?

Istio 中的池噴射是什麼

Istio 的斷路器保護機器來救援,它會暫時從路由和負載平衡資源池中刪除故障的容器,從而實現池彈出程序。

Istio 使用異常值偵測策略來偵測超出範圍的曲線 pod,並將它們從資源池中刪除一段指定的時間(稱為睡眠視窗)。

為了展示它在 OpenShift 平台上的 Kubernetes 中的工作原理,讓我們從儲存庫中範例中正常運作的微服務的螢幕截圖開始 紅帽開發人員演示。 這裡我們有兩個 pod,v1 和 v2,每個運行一個容器。 當不使用 Istio 路由規則時,Kubernetes 預設採用均勻平衡的循環路由:

Istio Circuit Breaker:停用故障的容器

為崩潰做好準備

在進行 Pool Ejection 之前,您需要建立 Istio 路由規則。 假設我們希望以 50/50 的比例在 Pod 之間分配請求。 此外,我們會將 v2 容器的數量從 XNUMX 個增加到 XNUMX 個,如下所示:

oc scale deployment recommendation-v2 --replicas=2 -n tutorial

現在我們設定一個路由規則,以便流量在 Pod 之間以 50/50 的比例分配。

Istio Circuit Breaker:停用故障的容器
此規則的結果如下所示:

Istio Circuit Breaker:停用故障的容器
你可能會發現這個畫面不是 50/50,而是 14:9,但隨著時間的推移,情況會有所改善。

製造一個小故障

現在讓我們停用兩個 v2 容器之一,這樣我們就有一個正常的 v1 容器、一個正常的 v2 容器和一個故障的 v2 容器:

Istio Circuit Breaker:停用故障的容器

修復故障

所以,我們有一個有缺陷的容器,現在是池彈出的時候了。 使用一個非常簡單的配置,我們將從任何路由方案中排除這個失敗的容器 15 秒,希望它能夠恢復到健康狀態(重新啟動或恢復效能)。 這是此配置的外觀及其工作結果:

Istio Circuit Breaker:停用故障的容器
Istio Circuit Breaker:停用故障的容器
正如您所看到的,失敗的 v2 容器不再用於路由請求,因為它已從池中刪除。 但15秒後它會自動返回池中。 實際上,我們只是展示了池彈出的工作原理。

讓我們開始建立架構

池彈出與 Istio 的監控功能相結合,使您可以開始建立自動替換故障容器的框架,以減少(如果不能消除的話)停機時間和故障。

美國宇航局有一句響亮的座右銘——失敗不是一種選擇,這句話的作者被認為是飛行指揮 吉恩·克蘭茲。 它可以翻譯成俄語,意思是“失敗不是一種選擇”,這裡的意思是,如果你有足夠的意志,一切都可以成功。 然而,在現實生活中,失敗不僅會發生,而且是不可避免的,無所不在、無所不在。 那麼在微服務的情況下該如何處理呢? 我們認為,最好不要依靠意志力,而是依靠容器的能力, Kubernetes, 紅帽OpenShiftIstio.

正如我們上面所寫,Istio 實現了斷路器的概念,該概念已經在物理世界中得到了很好的證明。 就像斷路器關閉電路的問題部分一樣,Istio 的軟體斷路器會在端點出現問題時打開請求流和問題容器之間的連接,例如,當伺服器崩潰或開始運行時減速。

此外,在第二種情況下,只會出現更多問題,因為一個容器的煞車不僅會導致存取它的服務出現一連串的延遲,從而降低整個系統的性能,還會產生重複的性能。向運行速度已經很慢的服務發出請求,這只會讓情況變得更糟。

理論上的斷路器

斷路器是一個控制端點請求流的代理。 當該點停止工作或根據指定的設定開始變慢時,代理程式將斷開與容器的連接。 然後,由於負載平衡,流量被重定向到其他容器。 連接在給定的睡眠視窗(例如兩分鐘)內保持開啟狀態,然後被視為半開啟。 發送下一個請求的嘗試決定了連線的進一步狀態。 如果服務一切正常,連線將恢復工作狀態並再次關閉。 如果服務仍然存在問題,則連線將斷開並重新啟用睡眠視窗。 簡化的斷路器狀態圖如下所示:

Istio Circuit Breaker:停用故障的容器
這裡要注意的是,這一切都發生在系統架構的層面。 因此,在某些時候,您必須教導您的應用程式使用斷路器,例如提供預設值作為回應,或者如果可能的話,忽略服務的存在。 為此使用了艙壁圖案,但這超出了本文的範圍。

斷路器的實際應用

例如,我們將在 OpenShift 上執行兩個版本的建議微服務。 版本 1 可以正常工作,但在 v2 中,我們將建立延遲來模擬伺服器上的減速。 若要查看結果,請使用該工具 圍城:

siege -r 2 -c 20 -v customer-tutorial.$(minishift ip).nip.io

Istio Circuit Breaker:停用故障的容器
一切似乎都有效,但代價是什麼? 乍一看,我們有 100% 的可用性,但仔細看看——最大事務持續時間長達 12 秒。 這顯然是一個瓶頸,需要擴大。

為此,我們將使用 Istio 來消除對慢速容器的呼叫。 這是使用斷路器的相應配置:

Istio Circuit Breaker:停用故障的容器
httpMaxRequestsPerConnection 參數的最後一行表示,當嘗試在現有連線之外建立另一個(第二個)連線時,應中斷連線。 由於我們的容器模擬的是慢速服務,因此這種情況會定期出現,然後 Istio 會傳回 503 錯誤,但這就是 siege 會顯示的內容:

Istio Circuit Breaker:停用故障的容器

好的,我們有了斷路器,下一步是什麼?

因此,我們實現了自動關閉,而根本不觸及服務本身的原始碼。 使用上述的斷路器和池彈出過程,我們可以從資源池中刪除制動容器,直到它們恢復正常,並以指定的頻率檢查它們的狀態- 在我們的示例中,這是兩分鐘(sleepWindow 參數) 。

請注意,應用程式回應 503 錯誤的能力仍然是在原始碼層級設定的。 使用Circuit Breaker的策略有很多種,視情況而定。

在下一篇文章中: 我們將討論 Istio 中已內建或輕鬆添加的追蹤和監控,以及如何故意將錯誤引入系統。

來源: www.habr.com

添加評論