文章轉載自:https://www.kuboard.cn/learning/k8s-intermediate/workload/pod-health.html
介紹
Liveness 指針是存活指針,它用來判斷容器是否存活、判斷 pod 是否 running。如果 Liveness 指針判斷容器不健康,此時會通過 kubelet 殺掉相應的 pod,並根據重啟策略來判斷是否重啟這個容器。如果默認不配置 Liveness 指針,則默認情況下認為它這個探測默認返回是成功的。
Readiness 指針用來判斷這個容器是否啟動完成,即 pod 的 condition 是否 ready。如果探測的一個結果是不成功,那么此時它會從 pod 上 Endpoint 上移除,也就是說從接入層上面會把前一個 pod 進行摘除,直到下一次判斷成功,這個 pod 才會再次掛到相應的 endpoint 之上。
檢測失敗
對於檢測失敗上面來講 Liveness 指針是直接殺掉這個 pod,而 Readiness 指針是切掉 endpoint 到這個 pod 之間的關聯關系,也就是說它把這個流量從這個 pod 上面進行切掉。
適用場景
Liveness 指針適用場景是支持那些可以重新拉起的應用,而 Readiness 指針主要應對的是啟動之后無法立即對外提供服務的這些應用。
應用健康狀態-初識 Liveness 與 Readiness
Readiness probe 也叫就緒指針,用來判斷一個 pod 是否處在就緒狀態。當一個 pod 處在就緒狀態的時候,它才能夠對外提供相應的服務,也就是說接入層的流量才能打到相應的 pod。當這個 pod 不處在就緒狀態的時候,接入層會把相應的流量從這個 pod 上面進行摘除。
來看一下簡單的一個例子:
如下圖其實就是一個 Readiness 就緒的一個例子:
當這個 pod 指針判斷一直處在失敗狀態的時候,其實接入層的流量不會打到現在這個 pod 上。
當這個 pod 的狀態從 FAIL 的狀態轉換成 success 的狀態時,它才能夠真實地承載這個流量。
Liveness 指針也是類似的,它是存活指針,用來判斷一個 pod 是否處在存活狀態。當一個 pod 處在不存活狀態的時候,會出現什么事情呢?
這個時候會由上層的判斷機制來判斷這個 pod 是否需要被重新拉起。那如果上層配置的重啟策略是 restart always 的話,那么此時這個 pod 會直接被重新拉起。
應用健康狀態-使用方式
探測方式
第一種是 httpGet。它是通過發送 http Get 請求來進行判斷的,當返回碼是 200-399 之間的狀態碼時,標識這個應用是健康的;
第二種探測方式是 Exec。它是通過執行容器中的一個命令來判斷當前的服務是否是正常的,當命令行的返回結果是 0,則標識容器是健康的;
第三種探測方式是 tcpSocket 。它是通過探測容器的 IP 和 Port 進行 TCP 健康檢查,如果這個 TCP 的鏈接能夠正常被建立,那么標識當前這個容器是健康的。
探測結果
從探測結果來講主要分為三種:
第一種是 success,當狀態是 success 的時候,表示 container 通過了健康檢查,也就是 Liveness probe 或 Readiness probe 是正常的一個狀態;
第二種是 Failure,Failure 表示的是這個 container 沒有通過健康檢查,如果沒有通過健康檢查的話,那么此時就會進行相應的一個處理,那在 Readiness 處理的一個方式就是通過 service。service 層將沒有通過 Readiness 的 pod 進行摘除,而 Liveness 就是將這個 pod 進行重新拉起,或者是刪除。
第三種狀態是 Unknown,Unknown 是表示說當前的執行的機制沒有進行完整的一個執行,可能是因為類似像超時或者像一些腳本沒有及時返回,那么此時 Readiness-probe 或 Liveness-probe 會不做任何的一個操作,會等待下一次的機制來進行檢驗。
那在 kubelet 里面有一個叫 ProbeManager 的組件,這個組件里面會包含 Liveness-probe 或 Readiness-probe,這兩個 probe 會將相應的 Liveness 診斷和 Readiness 診斷作用在 pod 之上,來實現一個具體的判斷。
應用健康狀態-Pod Probe Spec
下面介紹這三種方式不同的檢測方式的一個 yaml 文件的使用。
首先先看一下 exec,exec 的使用其實非常簡單。如下圖所示,大家可以看到這是一個 Liveness probe,它里面配置了一個 exec 的一個診斷。接下來,它又配置了一個 command 的字段,這個 command 字段里面通過 cat 一個具體的文件來判斷當前 Liveness probe 的狀態,當這個文件里面返回的結果是 0 時,或者說這個命令返回是 0 時,它會認為此時這個 pod 是處在健康的一個狀態。
那再來看一下這個 httpGet,httpGet 里面有一個字段是路徑,第二個字段是 port,第三個是 headers。這個地方有時需要通過類似像 header 頭的一個機制做 health 的一個判斷時,需要配置這個 header,通常情況下,可能只需要通過 health 和 port 的方式就可以了。
第三種是 tcpSocket,tcpSocket 的使用方式其實也比較簡單,你只需要設置一個檢測的端口,像這個例子里面使用的是 8080 端口,當這個 8080 端口 tcp connect 審核正常被建立的時候,那 tecSocket,Probe 會認為是健康的一個狀態。
此外還有如下的五個參數,是 Global 的參數。
第一個參數叫 initialDelaySeconds,它表示的是說這個 pod 啟動延遲多久進行一次檢查,比如說現在有一個 Java 的應用,它啟動的時間可能會比較長,因為涉及到 jvm 的啟動,包括 Java 自身 jar 的加載。所以前期,可能有一段時間是沒有辦法被檢測的,而這個時間又是可預期的,那這時可能要設置一下 initialDelaySeconds;
第二個是 periodSeconds,它表示的是檢測的時間間隔,正常默認的這個值是 10 秒;
第三個字段是 timeoutSeconds,它表示的是檢測的超時時間,當超時時間之內沒有檢測成功,那它會認為是失敗的一個狀態;
第四個是 successThreshold,它表示的是:當這個 pod 從探測失敗到再一次判斷探測成功,所需要的閾值次數,默認情況下是 1 次,表示原本是失敗的,那接下來探測這一次成功了,就會認為這個 pod 是處在一個探針狀態正常的一個狀態;
最后一個參數是 failureThreshold,它表示的是探測失敗的重試次數,默認值是 3,表示的是當從一個健康的狀態連續探測 3 次失敗,那此時會判斷當前這個pod的狀態處在一個失敗的狀態。
應用健康狀態-Liveness 與 Readiness 總結
注意事項
在使用 Liveness 指針和 Readiness 指針的時候有一些注意事項。因為不論是 Liveness 指針還是 Readiness 指針都需要配置合適的探測方式,以免被誤操作。
第一個是調大超時的閾值,因為在容器里面執行一個 shell 腳本,它的執行時長是非常長的,平時在一台 ecs 或者在一台 vm 上執行,可能 3 秒鍾返回的一個腳本在容器里面需要 30 秒鍾。所以這個時間是需要在容器里面事先進行一個判斷的,那如果可以調大超時閾值的方式,來防止由於容器壓力比較大的時候出現偶發的超時;
第二個是調整判斷的一個次數,3 次的默認值其實在比較短周期的判斷周期之下,不一定是最佳實踐,適當調整一下判斷的次數也是一個比較好的方式;
第三個是 exec,如果是使用 shell 腳本的這個判斷,調用時間會比較長,比較建議大家可以使用類似像一些編譯性的腳本 Golang 或者一些 C 語言、C++ 編譯出來的這個二進制的 binary 進行判斷,那這種通常會比 shell 腳本的執行效率高 30% 到 50%;
第四個是如果使用 tcpSocket 方式進行判斷的時候,如果遇到了 TLS 的服務,那可能會造成后邊 TLS 里面有很多這種未健全的 tcp connection,那這個時候需要自己對業務場景上來判斷,這種的鏈接是否會對業務造成影響。