K8S 中的健康檢查機(jī)制

image

概述

健康檢查(Health Check)用于檢測(cè)您的應(yīng)用實(shí)例是否正常工作仗岖,是保障業(yè)務(wù)可用性的一種傳統(tǒng)機(jī)制逃延,一般用于負(fù)載均衡下的業(yè)務(wù),如果實(shí)例的狀態(tài)不符合預(yù)期轧拄,將會(huì)把該實(shí)例“摘除”真友,不承擔(dān)業(yè)務(wù)流量。

Kubernetes中的健康檢查使用存活性探針(liveness probes)和就緒性探針(readiness probes)來(lái)實(shí)現(xiàn)紧帕,service即為負(fù)載均衡,k8s保證 service 后面的 pod 都可用桅打,是k8s中自愈能力的主要手段是嗜,基于這兩種探測(cè)機(jī)制,可以實(shí)現(xiàn)如下需求:

  • 異常實(shí)例自動(dòng)剔除挺尾,并重啟新實(shí)例
  • 多種類型探針檢測(cè)鹅搪,保證異常pod不接入流量
  • 不停機(jī)部署,更安全的滾動(dòng)升級(jí)

目前支持的探測(cè)方式包括:

  • HTTP
  • TCP
  • Exec命令

k8s 中的 示例配置如下:

image

探針類型

默認(rèn)機(jī)制:

如果把 k8s 對(duì) pod 的crash 狀態(tài)判斷也能稱之為“健康檢查”的話遭铺,那算是默認(rèn)的健康檢查機(jī)制了丽柿,

每個(gè)容器啟動(dòng)時(shí)都會(huì)執(zhí)行一個(gè)主進(jìn)程,如果進(jìn)程退出返回碼不是0魂挂,則認(rèn)為容器異常甫题,即pod異常,k8s 會(huì)根據(jù)restartPolicy策略選擇是否殺掉 pod涂召,再重新啟動(dòng)一個(gè)坠非。

restartPolicy分為三種:

  • Always:當(dāng)容器終止退出后,總是重啟容器果正,默認(rèn)策略炎码。
  • Onfailure:當(dāng)容器異常退出(退出碼非0)時(shí),才重啟容器秋泳。
  • Never:當(dāng)容器終止退出時(shí)潦闲,才不重啟容器。

存活探針

上面的默認(rèn)機(jī)制中迫皱,容器進(jìn)程返回值非0則認(rèn)為容器發(fā)生故障歉闰,需要重啟。但很多情況下服務(wù)出現(xiàn)問(wèn)題,進(jìn)程卻沒(méi)有退出新娜,如系統(tǒng)超載 5xx 錯(cuò)誤赵辕,資源死鎖等。這種情況下就需要健康檢查機(jī)制出場(chǎng)了

存活探針(Liveness probe):讓Kubernetes知道你的應(yīng)用程序是否健康概龄,如果你的應(yīng)用程序不健康还惠,Kubernetes將刪除Pod并啟動(dòng)一個(gè)新的替換它。這里的“健康”不再是進(jìn)程狀態(tài)私杜,而是用戶自定義探測(cè)方式:HTTP蚕键、TCP、Exec

舉例說(shuō)明:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness
spec:
  restartPolicy: OnFailure
  containers:
  - name: liveness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -fr /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 10
      periodSeconds: 5

啟動(dòng)進(jìn)程首先創(chuàng)建文件 /tmp/healthy衰粹,30 秒后刪除锣光,在我們的設(shè)定中,如果 /tmp/healthy 文件存在铝耻,則認(rèn)為容器處于正常狀態(tài)誊爹,反正則發(fā)生故障。

livenessProbe 部分定義如何執(zhí)行 Liveness 探測(cè):

  1. 探測(cè)的方法是:通過(guò) cat 命令檢查 /tmp/healthy 文件是否存在瓢捉。如果命令執(zhí)行成功频丘,返回值為0,Kubernetes 則認(rèn)為本次 Liveness 探測(cè)成功泡态;如果命令返回值非0搂漠,本次 Liveness 探測(cè)失敗。

  2. initialDelaySeconds: 10某弦,指定容器啟動(dòng) 10s 之后開始執(zhí)行 Liveness 探測(cè)桐汤,我們一般會(huì)根據(jù)應(yīng)用啟動(dòng)的準(zhǔn)備時(shí)間來(lái)設(shè)置。比如某個(gè)應(yīng)用正常啟動(dòng)要花 30 秒靶壮,那么 initialDelaySeconds 的值就應(yīng)該大于 30怔毛。

  3. periodSeconds: 5, 指定每 5 秒執(zhí)行一次 Liveness 探測(cè)亮钦。Kubernetes 如果連續(xù)執(zhí)行 3 次 Liveness 探測(cè)均失敗馆截,則會(huì)殺掉并重啟容器。3次是可以配置的蜂莉,參數(shù)為failureThreshold蜡娶,含義后面解釋

使用上面的 yaml 創(chuàng)建 pod:

image

剛開始的 30s,健康檢查能通過(guò)映穗。

image

此時(shí)的events 顯示正常

image

30s 后窖张,日志會(huì)顯示 /tmp/healthy 已經(jīng)不存在,Liveness 探測(cè)失敗蚁滋。再過(guò)幾十秒宿接,幾次探測(cè)都失敗后赘淮,容器會(huì)被重啟。events 中可以看到重試 了 3次探測(cè)睦霎,每次間隔 10s梢卸,單次探測(cè)的超時(shí)時(shí)間為 1s。

image

liveness 的配置來(lái)自 v1中的Probe資源副女,所有屬性含義如下:

  • httpGet:對(duì)應(yīng)HTTPGetAction對(duì)象蛤高,屬性包括:host、httpHeaders碑幅、path戴陡、port、scheme
  • initialDelaySeconds:容器啟動(dòng)后開始探測(cè)之前需要等多少秒沟涨,如應(yīng)用啟動(dòng)一般30s的話恤批,就設(shè)置為 30s
  • periodSeconds:執(zhí)行探測(cè)的頻率(多少秒執(zhí)行一次)。默認(rèn)為10秒裹赴。最小值為1喜庞。
  • successThreshold:探針失敗后,最少連續(xù)成功多少次才視為成功棋返。默認(rèn)值為1赋荆。最小值為1。
  • failureThreshold:最少連續(xù)多少次失敗才視為失敗懊昨。默認(rèn)值為3。最小值為1春宣。
  • timeoutSeconds:探測(cè)的超時(shí)時(shí)間酵颁,默認(rèn) 1s,最小 1s
  • tcpSocket:對(duì)應(yīng)TCPSocketAction對(duì)象月帝,TCPSocket指定端口躏惋。尚不支持TCP hook
  • exec:對(duì)應(yīng)ExecAction對(duì)象,需要執(zhí)行的內(nèi)容

動(dòng)圖說(shuō)明:

https://storage.googleapis.com/gweb-cloudblog-publish/original_images/google-kubernetes-probe-livenessae14.GIF

探針執(zhí)行方式

HTTP

HTTP探針可能是最常見的自定義Liveness探針類型嚷辅。 即使您的應(yīng)用程序不是HTTP服務(wù)簿姨,您也可以在應(yīng)用程序內(nèi)創(chuàng)建輕量級(jí)HTTP服務(wù)以響應(yīng)Liveness探針。 Kubernetes去訪問(wèn)一個(gè)路徑簸搞,如果它得到的是200或300范圍內(nèi)的HTTP響應(yīng)扁位,它會(huì)將應(yīng)用程序標(biāo)記為健康。 否則它被標(biāo)記為不健康趁俊。

httpGet配置項(xiàng):

  • host:連接的主機(jī)名域仇,默認(rèn)連接到pod的IP。你可能想在http header中設(shè)置"Host"而不是使用IP寺擂。
  • scheme:連接使用的schema暇务,默認(rèn)HTTP泼掠。
  • path: 訪問(wèn)的HTTP server的path。
  • httpHeaders:自定義請(qǐng)求的header垦细。HTTP運(yùn)行重復(fù)的header择镇。
  • port:訪問(wèn)的容器的端口名字或者端口號(hào)。端口號(hào)必須介于1和65535之間括改。
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3

Exec

對(duì)于Exec探針腻豌,Kubernetes則只是在容器內(nèi)運(yùn)行命令。 如果命令以退出代碼0返回叹谁,則容器標(biāo)記為健康饲梭。 否則,它被標(biāo)記為不健康焰檩。 當(dāng)您不能或不想運(yùn)行HTTP服務(wù)時(shí)憔涉,此類型的探針則很有用,但是必須是運(yùn)行可以檢查您的應(yīng)用程序是否健康的命令析苫。

Exec 的配置項(xiàng)(exec):

  • command:需要執(zhí)行的命令兜叨,需要符合命令的格式
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

TCP

最后一種類型的探針是TCP探針,Kubernetes嘗試在指定端口上建立TCP連接衩侥。 如果它可以建立連接国旷,則容器被認(rèn)為是健康的;否則被認(rèn)為是不健康的茫死。

如果您有HTTP探針或Command探針不能正常工作的情況跪但,TCP探測(cè)器會(huì)派上用場(chǎng)。 例如峦萎,gRPC或FTP服務(wù)是此類探測(cè)的主要候選者屡久。

TCP 的配置項(xiàng)(tcpSocket):

  • host:探測(cè)的主機(jī),默認(rèn)為本pod ip
  • port:端口爱榔,1到65535
apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

就緒探針

就緒探針(Readiness probe):讓Kubernetes知道您的應(yīng)用是否準(zhǔn)備好其流量服務(wù)被环。 Kubernetes確保Readiness探針檢測(cè)通過(guò),然后允許服務(wù)將流量發(fā)送到Pod详幽。 如果Readiness探針開始失敗筛欢,Kubernetes將停止向該容器發(fā)送流量,直到它通過(guò)唇聘。 判斷容器是否處于可用Ready狀態(tài), 達(dá)到ready狀態(tài)表示pod可以接受請(qǐng)求, 如果不健康版姑, 從service的后端endpoint列表中把pod隔離出去

用戶通過(guò) Liveness 探測(cè)可以告訴 Kubernetes 什么時(shí)候通過(guò)重啟容器實(shí)現(xiàn)自愈;而就緒探針Readiness則是告訴 Kubernetes 什么時(shí)候可以將容器加入到 Service 負(fù)載均衡中迟郎,對(duì)外提供服務(wù)漠酿。

Readiness 探測(cè)的配置語(yǔ)法與 Liveness 探測(cè)完全一樣,這里不再贅述谎亩。

如果連續(xù) n 次 Readiness 探測(cè)均失敗后炒嘲,READY被設(shè)置為不可用宇姚。

status 為 running,但是 ready 數(shù)為 0/1

動(dòng)圖示例:

https://storage.googleapis.com/gweb-cloudblog-publish/original_images/google-kubernetes-probe-readiness6ktf.GIF

兩種探針對(duì)比

  1. Liveness 探測(cè)和 Readiness 探測(cè)是兩種 Health Check 機(jī)制夫凸,如果不特意配置浑劳,Kubernetes 將對(duì)兩種探測(cè)采取相同的默認(rèn)行為,即通過(guò)判斷容器啟動(dòng)進(jìn)程的返回值是否為零來(lái)判斷探測(cè)是否成功夭拌。

  2. 兩種探測(cè)的配置方法完全一樣魔熏,支持的配置參數(shù)也一樣。不同之處在于探測(cè)失敗后的行為:Liveness 探測(cè)是重啟容器鸽扁;Readiness 探測(cè)則是將容器設(shè)置為不可用蒜绽,不接收 Service 轉(zhuǎn)發(fā)的請(qǐng)求。

  3. Liveness 探測(cè)和 Readiness 探測(cè)是獨(dú)立執(zhí)行的桶现,二者之間沒(méi)有依賴躲雅,所以可以單獨(dú)使用,也可以同時(shí)使用骡和。

  4. 用 Liveness 探測(cè)判斷容器是否需要重啟以實(shí)現(xiàn)自愈相赁;用 Readiness 探測(cè)判斷容器是否已經(jīng)準(zhǔn)備好對(duì)外提供服務(wù)。Readiness可用于指定容器啟動(dòng)后慰于,判斷容器各服務(wù)是否已正常啟動(dòng)(如啟動(dòng)腳本執(zhí)行后寫指定內(nèi)容至特定文件)

使用場(chǎng)景

擴(kuò)縮容

對(duì)于生產(chǎn)環(huán)境中重要的應(yīng)用都建議配置 Health Check钮科,保證處理客戶請(qǐng)求的容器都是準(zhǔn)備就緒的 Service backend。如果 Liveness不通過(guò)婆赠,則應(yīng)該縮掉異常 pod绵脯,重新啟動(dòng)新 pod

示例:

對(duì)于 http://[container_ip]:8080/healthy,應(yīng)用則可以實(shí)現(xiàn)自己的判斷邏輯休里,比如檢查所依賴的數(shù)據(jù)庫(kù)是否就緒桨嫁,示例代碼如下:

image

健康檢查的步驟為:

  1. 容器啟動(dòng) 10 秒之后開始探測(cè)。
  2. 如果 http://[container_ip]:8080/healthy 返回代碼不是 200-400份帐,表示容器沒(méi)有就緒,不接收 Service web-svc 的請(qǐng)求楣导。
  3. 每隔 5 秒再探測(cè)一次废境。
  4. 直到返回代碼為 200-400,表明容器已經(jīng)就緒筒繁,然后將其加入到 web-svc 的負(fù)責(zé)均衡中噩凹,開始處理客戶請(qǐng)求。
  5. 探測(cè)會(huì)繼續(xù)以 5 秒的間隔執(zhí)行毡咏,如果連續(xù)發(fā)生 3 次失敗驮宴,容器又會(huì)從負(fù)載均衡中移除,直到下次探測(cè)成功重新加入呕缭。
image

滾動(dòng)更新

現(xiàn)有一個(gè)正常運(yùn)行的多副本應(yīng)用堵泽,接下來(lái)對(duì)應(yīng)用進(jìn)行更新(比如使用更高版本的 image)修己,Kubernetes 會(huì)啟動(dòng)新副本,然后發(fā)生了如下事件:

  1. 正常情況下新副本需要 10 秒鐘完成準(zhǔn)備工作迎罗,在此之前無(wú)法響應(yīng)業(yè)務(wù)請(qǐng)求睬愤。
  2. 但由于人為配置錯(cuò)誤,副本始終無(wú)法完成準(zhǔn)備工作(比如無(wú)法連接后端數(shù)據(jù)庫(kù))纹安。

如果沒(méi)有配置健康檢查尤辱,則有問(wèn)題的新副本將替換老副本,導(dǎo)致集群服務(wù)異常厢岂。

如果正確配置了 Health Check光督,新副本只有通過(guò)了 Readiness 探測(cè),才會(huì)被添加到 Service塔粒;如果沒(méi)有通過(guò)探測(cè)结借,現(xiàn)有副本不會(huì)被全部替換,業(yè)務(wù)仍然正常進(jìn)行窗怒。

實(shí)現(xiàn)原理

liveness 和 readiness 的探測(cè)都是由kubelet執(zhí)行映跟。

exec方式

func (pb *prober) runProbe(p *v1.Probe, pod *v1.Pod, status v1.PodStatus, container v1.Container, containerID kubecontainer.ContainerID) (probe.Result, string, error) {
.....        
        command := kubecontainer.ExpandContainerCommandOnlyStatic(p.Exec.Command, container.Env)
        return pb.exec.Probe(pb.newExecInContainer(container, containerID, command, timeout))
......
        
func (pb *prober) newExecInContainer(container v1.Container, containerID kubecontainer.ContainerID, cmd []string, timeout time.Duration) exec.Cmd {
    return execInContainer{func() ([]byte, error) {
        return pb.runner.RunInContainer(containerID, cmd, timeout)
    }}
}
        
......
func (m *kubeGenericRuntimeManager) RunInContainer(id kubecontainer.ContainerID, cmd []string, timeout time.Duration) ([]byte, error) {
    stdout, stderr, err := m.runtimeService.ExecSync(id.ID, cmd, 0)
    return append(stdout, stderr...), err
}

由kubelet,通過(guò)CRI接口的ExecSync接口扬虚,在對(duì)應(yīng)容器內(nèi)執(zhí)行拼裝好的cmd命令努隙。獲取返回值。

func (pr execProber) Probe(e exec.Cmd) (probe.Result, string, error) {
    data, err := e.CombinedOutput()
    glog.V(4).Infof("Exec probe response: %q", string(data))
    if err != nil {
        exit, ok := err.(exec.ExitError)
        if ok {
            if exit.ExitStatus() == 0 {
                return probe.Success, string(data), nil
            } else {
                return probe.Failure, string(data), nil
            }
        }
        return probe.Unknown, "", err
    }
    return probe.Success, string(data), nil
}

kubelet是根據(jù)執(zhí)行命令的退出碼來(lái)決定是否探測(cè)成功辜昵。當(dāng)執(zhí)行命令的退出碼為0時(shí)荸镊,認(rèn)為執(zhí)行成功,否則為執(zhí)行失敗堪置。如果執(zhí)行超時(shí)躬存,則狀態(tài)為Unknown。

http探測(cè)

func DoHTTPProbe(url *url.URL, headers http.Header, client HTTPGetInterface) (probe.Result, string, error) {
    req, err := http.NewRequest("GET", url.String(), nil)
    ......
    if res.StatusCode >= http.StatusOK && res.StatusCode < http.StatusBadRequest {
        glog.V(4).Infof("Probe succeeded for %s, Response: %v", url.String(), *res)
        return probe.Success, body, nil
    }
    ......

http探測(cè)是通過(guò)kubelet請(qǐng)求容器的指定url舀锨,并根據(jù)response來(lái)進(jìn)行判斷岭洲。 當(dāng)返回的狀態(tài)碼在200到400(不含400)之間時(shí),也就是狀態(tài)碼為2xx和3xx坎匿,認(rèn)為探測(cè)成功盾剩。否則認(rèn)為失敗。

tcp探測(cè)

func DoTCPProbe(addr string, timeout time.Duration) (probe.Result, string, error) {
    conn, err := net.DialTimeout("tcp", addr, timeout)
    if err != nil {
        // Convert errors to failures to handle timeouts.
        return probe.Failure, err.Error(), nil
    }
    err = conn.Close()
    if err != nil {
        glog.Errorf("Unexpected error closing TCP probe socket: %v (%#v)", err, err)
    }
    return probe.Success, "", nil
}

tcp探測(cè)是通過(guò)探測(cè)指定的端口替蔬。如果可以連接告私,則認(rèn)為探測(cè)成功,否則認(rèn)為失敗承桥。

其他

執(zhí)行命令探測(cè)失敗的原因主要可能是容器未成功啟動(dòng)驻粟,或者執(zhí)行命令失敗。當(dāng)然也可能docker或者docker-shim存在故障凶异。

由于http和tcp都是從kubelet自node節(jié)點(diǎn)上發(fā)起的蜀撑,向容器的ip進(jìn)行探測(cè)挤巡。 所以探測(cè)失敗的原因除了應(yīng)用容器的問(wèn)題外,還可能是從node到容器ip的網(wǎng)絡(luò)不通屯掖。

readiness檢查結(jié)果會(huì)通過(guò)SetContainerReadiness函數(shù)玄柏,設(shè)置到pod的status中,從而更新pod的ready condition贴铜。

liveness和readiness除了最終的作用不同粪摘,另外一個(gè)很大的區(qū)別是它們的初始值不同。

 switch probeType {
    case readiness:
        w.spec = container.ReadinessProbe
        w.resultsManager = m.readinessManager
        w.initialValue = results.Failure
    case liveness:
        w.spec = container.LivenessProbe
        w.resultsManager = m.livenessManager
        w.initialValue = results.Success
    }

liveness的初始值為成功绍坝。這樣防止在應(yīng)用還沒(méi)有成功啟動(dòng)前徘意,就被誤殺。如果在規(guī)定時(shí)間內(nèi)還未成功啟動(dòng)轩褐,才將其設(shè)置為失敗椎咧,從而觸發(fā)容器重建。

而readiness的初始值為失敗把介。這樣防止應(yīng)用還沒(méi)有成功啟動(dòng)前就向應(yīng)用進(jìn)行流量的導(dǎo)入勤讽。如果在規(guī)定時(shí)間內(nèi)啟動(dòng)成功,才將其設(shè)置為成功拗踢,從而將流量向應(yīng)用導(dǎo)入脚牍。

liveness與readiness二者作用不能相互替代。

例如只配置了liveness巢墅,那么在容器啟動(dòng)诸狭,應(yīng)用還沒(méi)有成功就緒之前,這個(gè)時(shí)候pod是ready的(因?yàn)槿萜鞒晒?dòng)了)君纫。那么流量就會(huì)被引入到容器的應(yīng)用中驯遇,可能會(huì)導(dǎo)致請(qǐng)求失敗。雖然在liveness檢查失敗后蓄髓,重啟容器叉庐,此時(shí)pod的ready的condition會(huì)變?yōu)閒alse。但是前面會(huì)有一些流量因?yàn)殄e(cuò)誤狀態(tài)導(dǎo)入会喝。

當(dāng)然只配置了readiness是無(wú)法觸發(fā)容器重啟的陡叠。

因?yàn)槎叩淖饔貌煌趯?shí)際使用中好乐,可以根據(jù)實(shí)際的需求將二者進(jìn)行配合使用。

新探針:?jiǎn)?dòng)探針

設(shè)計(jì)文檔:[https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/20190221-livenessprobe-holdoff.md]

目的:

對(duì)于慢啟動(dòng)容器來(lái)說(shuō)瓦宜,現(xiàn)有的健康檢查機(jī)制不太好用

慢啟動(dòng)容器:指需要大量時(shí)間(一到幾分鐘)啟動(dòng)的容器蔚万。啟動(dòng)緩慢的原因可能有多種:

  • 長(zhǎng)時(shí)間的數(shù)據(jù)初始化:只有第一次啟動(dòng)會(huì)花費(fèi)很多時(shí)間
  • 負(fù)載很高:每次啟動(dòng)都花費(fèi)很多時(shí)間
  • 節(jié)點(diǎn)資源不足/過(guò)載:即容器啟動(dòng)時(shí)間取決于外部因素

這種容器的主要問(wèn)題在于,在livenessProbe失敗之前临庇,應(yīng)該給它們足夠的時(shí)間來(lái)啟動(dòng)它們反璃。對(duì)于這種問(wèn)題昵慌,現(xiàn)有的機(jī)制的處理方式為:

  • 方法一:livenessProbe中把延遲初始時(shí)間initialDelaySeconds設(shè)置的很長(zhǎng),以允許容器啟動(dòng)(即initialDelaySeconds大于平均啟動(dòng)時(shí)間)淮蜈。雖然這樣可以確保livenessProbe不會(huì)檢測(cè)失敗斋攀,但是不知道initialDelaySeconds應(yīng)該配置為多少,啟動(dòng)時(shí)間不是一個(gè)固定值梧田。另外淳蔼,因?yàn)閘ivenessProbe在啟動(dòng)過(guò)程還沒(méi)運(yùn)行,因此pod 得不到反饋裁眯,events 看不到內(nèi)容,如果你initialDelaySeconds是 10 分鐘,那這 10 分鐘內(nèi)你不知道在發(fā)生什么渠脉。
  • 方法二:增加livenessProbe的失敗次數(shù)寻拂。即failureThreshold*periodSeconds的乘積足夠大,簡(jiǎn)單粗暴逢艘,同時(shí)容器在初次成功啟動(dòng)后旦袋,就算死鎖或以其他方式掛起,livenessProbe也會(huì)不斷探測(cè)

方法二可以解決這個(gè)問(wèn)題它改,但不夠優(yōu)雅疤孕。

因?yàn)閘ivenessProbe的設(shè)計(jì)是為了在 pod 啟動(dòng)成功后進(jìn)行健康探測(cè),最好前提是 pod 已經(jīng)啟動(dòng)成功搔课,否則啟動(dòng)階段的多次失敗是沒(méi)有意義的胰柑,因此官方提出了一種新的探針:即startupProbe,startupProbe并不是一種新的數(shù)據(jù)結(jié)構(gòu)爬泥,他完全復(fù)用了livenessProbe柬讨,只是名字改了下,多了一種概念袍啡,關(guān)于這個(gè) probe 的提議討論可以參考issue

使用方式:startup-probes

ports:
- name: liveness-port
  containerPort: 8080
  hostPort: 8080

livenessProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 1
  periodSeconds: 10

startupProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 30
  periodSeconds: 10

這個(gè)配置的含義是:

startupProbe首先檢測(cè)踩官,該應(yīng)用程序最多有5分鐘(30 * 10 = 300s)完成啟動(dòng)。一旦startupProbe成功一次境输,livenessProbe將接管蔗牡,以對(duì)后續(xù)運(yùn)行過(guò)程中容器死鎖提供快速響應(yīng)。如果startupProbe從未成功嗅剖,則容器將在300秒后被殺死辩越。

k8s 1.16 才開始支持startupProbe這個(gè)特性

最佳實(shí)踐

上述的擴(kuò)縮容和滾動(dòng)升級(jí)場(chǎng)景都需要用戶對(duì)應(yīng)用的健康檢查足夠了解,并且配置合適的策略信粮。主要工作是:

  1. 給用戶程序開發(fā)一個(gè)/healthy 接口黔攒,來(lái)獲取世界可用狀態(tài)(僅僅是 http服務(wù))
  2. 定義合理的健康檢查組合

注意事項(xiàng):

  • periodSeconds探測(cè)周期不能太短,否則會(huì)發(fā)送很多請(qǐng)求,也不能太長(zhǎng)督惰,否則會(huì)導(dǎo)致發(fā)現(xiàn)不了異常 pod
  • 合理配置failureThreshold和successThreshold不傅,否則會(huì)導(dǎo)致在 ready 和 not ready 直接反復(fù)擺動(dòng)

改造服務(wù)

如果你的服務(wù)無(wú)法提供 http 的健康檢查接口,可能需要修改你的業(yè)務(wù)代碼:如 grpc 服務(wù)赏胚,后面會(huì)提到

image

sidecar 形式做健康檢查

如果你不想更改你的業(yè)務(wù)邏輯访娶,您的應(yīng)用程序容器優(yōu)沒(méi)有公開HTTP接口以進(jìn)行健康檢查,那么您可以將另一個(gè)容器部署在pod內(nèi)并調(diào)用您的應(yīng)用程序的觉阅,即sidecar模式

image

之所以可行崖疤,是因?yàn)镻od的所有容器都在同一個(gè)環(huán)回接口(localhost)中。您無(wú)需將此端口暴露給外界留拾。

Cli 工具

image

你的應(yīng)用雖然不提供端點(diǎn)戳晌,但是可以通過(guò)exec 的方式執(zhí)行容器內(nèi)預(yù)裝的 cli 工具來(lái)實(shí)現(xiàn)健康檢查,其實(shí)就是腳本形式痴柔,變相的 exec

系統(tǒng)探針

image

你的應(yīng)用不提供端點(diǎn)沦偎,但是可以側(cè)面顯示應(yīng)用的使用狀態(tài),如 cpu內(nèi)存使用率咳蔚,通過(guò)系統(tǒng)指標(biāo)來(lái)側(cè)面反映服務(wù)的狀態(tài)豪嚎,如機(jī)器學(xué)習(xí)作業(yè)會(huì)使GPU升溫,從而導(dǎo)致計(jì)算速度變慢谈火。檢測(cè)不通過(guò)侈询,將作業(yè)移到其他節(jié)點(diǎn)可以解決此問(wèn)題。

如何支持 gprc 的健康檢查

GRPC正在成為云原生微服務(wù)之間通信的通用語(yǔ)言糯耍。如果您今天要將gRPC應(yīng)用程序部署到Kubernetes扔字,您可能想知道配置運(yùn)行狀況檢查的最佳方法。在本文中温技,我們將討論grpc-health-probe革为,一種Kubernetes本地健康檢查gRPC應(yīng)用程序的方法。

kubernetes本身不支持gRPC健康檢查舵鳞。這使得gRPC開發(fā)人員在部署到Kubernetes時(shí)有以下三種方法:

image
  • httpGet probe: 不能與gRPC原生使用震檩。您需要重構(gòu)您的應(yīng)用程序以同時(shí)提供gRPC和HTTP / 1.1協(xié)議(在不同的端口號(hào)上)。
  • tcpSocket probe: 打開套接字到gRPC服務(wù)器是沒(méi)有意義的蜓堕,因?yàn)樗鼰o(wú)法讀取響應(yīng)正文抛虏。
  • exec probe: 這會(huì)定期調(diào)用容器生態(tài)系統(tǒng)中的程序。對(duì)于gRPC套才,這意味著您自己實(shí)現(xiàn)健康RPC迂猴,然后使用編寫客戶端工具,并將客戶端工具與容器打包到一起背伴。

為了標(biāo)準(zhǔn)化上面提到的“exec探針”方法沸毁,我們需要:

  • 標(biāo)準(zhǔn)的健康檢查“協(xié)議”儡率,可以輕松地在任何gRPC服務(wù)器中實(shí)現(xiàn)。
  • 標(biāo)準(zhǔn)的健康檢查“工具”以清,可以輕松查詢健康協(xié)議。

得慶幸的是崎逃,gRPC有一個(gè)標(biāo)準(zhǔn)的健康檢查協(xié)議掷倔。它可以從任何語(yǔ)言輕松使用。生成的代碼和用于設(shè)置運(yùn)行狀況的實(shí)用程序幾乎都在gRPC的所有語(yǔ)言實(shí)現(xiàn)中提供个绍。

如果在gRPC應(yīng)用程序中實(shí)現(xiàn)此運(yùn)行狀況檢查協(xié)議勒葱,則可以使用標(biāo)準(zhǔn)/通用工具調(diào)用此Check()方法來(lái)確定服務(wù)器狀態(tài)。

下面你需要的是“標(biāo)準(zhǔn)工具”巴柿,它是grpc-health-probe凛虽。

image

使用此工具,您可以在所有g(shù)RPC應(yīng)用程序中使用相同的運(yùn)行狀況檢查配置广恢。這種方法需要你:

  • 選擇您喜歡的語(yǔ)言找到gRPC“health”模塊并開始使用它(例如Go庫(kù))凯旋。
  • 將grpc_health_probe二進(jìn)制文件打到容器中。
  • 配置Kubernetes“exec”探針以調(diào)用容器中的“grpc_health_probe”工具钉迷。

或者參考:https://github.com/americanexpress/grpc-k8s-health-check

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末至非,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子糠聪,更是在濱河造成了極大的恐慌荒椭,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舰蟆,死亡現(xiàn)場(chǎng)離奇詭異趣惠,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)身害,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門味悄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人题造,你說(shuō)我怎么就攤上這事傍菇。” “怎么了界赔?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵丢习,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我淮悼,道長(zhǎng)咐低,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任袜腥,我火速辦了婚禮见擦,結(jié)果婚禮上钉汗,老公的妹妹穿的比我還像新娘。我一直安慰自己鲤屡,他們只是感情好损痰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酒来,像睡著了一般卢未。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上堰汉,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天辽社,我揣著相機(jī)與錄音,去河邊找鬼翘鸭。 笑死滴铅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的就乓。 我是一名探鬼主播汉匙,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼生蚁!你這毒婦竟也來(lái)了盹兢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤守伸,失蹤者是張志新(化名)和其女友劉穎绎秒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尼摹,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡见芹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蠢涝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玄呛。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖和二,靈堂內(nèi)的尸體忽然破棺而出徘铝,到底是詐尸還是另有隱情,我是刑警寧澤惯吕,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布惕它,位于F島的核電站,受9級(jí)特大地震影響废登,放射性物質(zhì)發(fā)生泄漏淹魄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一堡距、第九天 我趴在偏房一處隱蔽的房頂上張望甲锡。 院中可真熱鬧兆蕉,春花似錦、人聲如沸缤沦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)缸废。三九已至劝术,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間呆奕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工衬吆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留梁钾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓逊抡,卻偏偏與公主長(zhǎng)得像姆泻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冒嫡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容