idou老師教你學Istio :5分鐘簡析Istio異常檢測

CCE_huawei發表於2019-02-22

異常檢測


異常檢測和踢出異常主機是一個動態檢查上游主機是否正常工作,對不健康主機進行移除的過程。異常檢測是一種被動健康

檢查,根據返回狀態碼來判斷是否滿足移除條件,最後將主機移除,首先我們來了解下驅逐演算法。


從上圖中,可以看出來主機異常時首先會檢查是不是有主機已經被移除了,如果沒有被移除,那麼直接移除這個不健康的主

機,如果有主機被移除,則會率先檢測是否超過移除閾值(maxEjectionPercent),如果超過這個閾值,則不會有任何行為

發生,如果沒超過這個閾值,那麼則會將該主機移除一段時間,這段時間後則會將主機放入負載均衡池中供下游主機選擇並

分發請求。


什麼是Panic_Threshold?


在負載均衡的過程中,Envoy只會考慮健康的上游主機。然而,如果健康主機的比例過低,Envoy將會無視健康狀態分發所有

的請求,這就是所謂的Panic Threshold,這個閾值預設為50%。這個設計的目的是防止大規模主機崩潰導致整個叢集負載

過高。Panic閾值需要和優先順序一起配合工作。如果在某個優先順序下健康主機數少了,Envoy將會將一些流量轉移到低優先順序

的主機。如果在低優先順序主機中,Envoy發現足夠數量的的健康主機。Envoy將會無視Panic閾值。如果各個優先順序健康程度

都是100%。Envoy將忽略panic閾值而根據既定負載均衡演算法路由流量。如果整體健康程度低100%,envoy認定沒有足夠數

量健康的宿主機,但是他仍會給所有優先順序的主機分發流量。但是如果給定優先順序的健康宿主機比例低於了Panic閾值,這時

候對於這部分優先順序的宿主機,所有流量將會分發給這部分宿主機而不考慮他們的健康狀態。


我們定位到程式碼中來看下Panic Threshold是如何配置和工作的。


如圖,我們可以看出healthy_panic_threshold被預設設定為50%。


在判斷流程當中,Envoy先會拿到實時的panic_threshold值,然後透過計算健康的hosts數量與總hosts的數量比值來比較。


在Envoy種有一個hostSourceToUse的方法,這個方法則是作為負載均衡的一部分,來將可用的hosts作為物件返回給呼叫方。

其中包含很多種情況,我們在此只列舉處在panic狀態下的情況。如下圖,若isGlobalPanic方法返回True也就是說叢集內處

在Panic模式,首先統計資料上會記錄一次相應的資料,再次可用hosts列表將會包含所有存在的hosts而無視他們的健康狀態。



熔斷的觸發與實現


Istio現在本身支援的四個引數是:連續錯誤個數,檢測週期,主機移除比例以及基本移除時間。這四個引數看上去可以大致

歸類一下,連續錯誤個數和檢測週期有點像是觸發條件,但實際上真正的觸發條件只有一個連續錯誤個數也就是

consecutive_5xx。主機移除比例和基本移除時間,更像是熔斷結果。我們接下來將這四個引數逐一分析下作用和實現。


Consecutive_5xx:設定的是5xx以上錯誤的個數。Envoy中的putHttpResponseCode方法根據請求結果的http狀態碼來進行

統計。如果返回狀態碼不高於500則會設定envoy統計資料中consecutive_5xx為0並且結束方法,若返回碼高於500則需要進

行兩次判斷。首先判斷狀態碼是否是502,503以及504,如果是則會首先將gateway failure 統計資料自增1,而後判斷是否

觸發了gateway failure的熔斷,這部分和istio設定的引數關係不大,我們暫不展開。同樣即便是Gateway failure或者返回值

為500,501,consecutive_5xx這個統計資料也會自增1然後和設定的熔斷條件進行比較(consecutive_errors)。



如過consecutive_5xx和配置中的比較相等,則會觸發相應的onConsecutive5xx方法,這個方法則是通知主執行緒,這個主機

發生了觸發了5xx錯誤熔斷。


有趣的是我們沒展開的gateway failure達到觸發條件也是會觸發這個通知主執行緒函式,只不過引數上傳入的是gateway 

failure這個引數。這個通知方法內會觸發onConsecutiveErrorWorker,正是這個方法最重隔離主機。


我們在分析隔離主機之前先來分析另一個引數MaxEjectionPercent,這個引數是最大主機隔離比例。在ejectHost這個方法

中,首先會獲得已配置的max_ejection_percent這個引數的值,若果沒有配置則會引用預設的10%。在截圖中,我們可以看

出如果ejected_percent如果小於max_ejection_percent,就會對主機進行移除操作。此時我們分析下,如果我們設定為

1%,即便移除後ejected_percent比例高於max_ejection_percent也會執行移除行為,類似向上取整。例如,10個主機,

設定移除比例為11%,則最多會移除2個主機而不是1個。如果我們將max_ejection_percent設成0又會發生什麼呢?是否

像我們想象的那樣一個都不移除因為畢竟0<0這個條件是不成立的。


我在Istio中對應的destinationrule中將max_ejection_percent設定為0,但是發現還是會熔斷1個。進而去查詢istio-proxy的

配置,發現max_ejection_percent並未配置下去,也就是說這個值採用的預設10%。在查詢Istio中的程式碼applyOutlier

Detection方法中找到。


只有在maxEjectionPercent大於0的時候才會採用這個值,否則不會採用該值,也就是說如果我們配了0下去,這個數值不會

轉配到Envoy上,這也就解釋了為什麼Envoy中的configure_dump中並沒有找到maxEjectionPercent所配置的0,並且還解

釋了為什麼我們認為配置了0,還是會有上游主機熔斷這個情況發生,因為使用了Envoy預設的10%。



Interval


Interval限定的是檢測週期,即多久會檢測一次上游主機返回的Http code來斷定是否需要對齊採取熔斷策略。其實檢測的這

種行為都是由Detector來執行的,interval就是賦予detector的一個定時基準。 


首先在armIntervalTimer方法中,啟用定時器,定時器時間會讀取配置的interval,如果沒有這個配置則會啟用預設的10s,

如下圖:


當detector initialize的時候會直接啟動這個定時器,也就是每過預設的一段時間detector會檢查所有的主機的狀態。


若這個主機沒有處在eject狀態則不會做任何行為,如果這個主機處於被隔離的狀態,則會檢測他移除時間和現在時間相比,

是否滿足召回條件。上圖中的checkHostForUneject就是專門檢查主機狀態和判斷是否要召回的方法。


介紹這個方法就要提到熔斷的最後一個引數baseEjectionTime這個引數意味最小隔離時間,實際隔離時間為最小隔離時間與

隔離次數的乘積。在checkHostForUneject這個方法中,如果主機的健康檢查為健康則會直接return不作任何行為,如果主

機的健康檢查並不健康,則會讀取baseEjectionTime而後透過計算與隔離次數的乘積得出應當被隔離的時間。當前時刻的時

間會以引數的形式傳遞進來,now和主機最後一次移除相減得出實際隔離的時間。如果應當被隔離的時間小於等於實際被隔

離的時間則會將主機召回並且重置統計引數,反之則不會有任何行為。


異常點檢查仍有許多istio未開放的引數,例如GatewayFailure、SuccessRate、最小健康例項數等。其實現上和負載均衡,

健康檢查等特性有較強的關聯,許多細節仍需分析和實驗。


相關服務請訪問https://support.huaweicloud.com/cce/index.html?cce_helpcenter_2019


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69908804/viewspace-2636663/,如需轉載,請註明出處,否則將追究法律責任。

相關文章