溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Liveness和Readiness兩種Health Check手段在Kubernetes中的使用

發(fā)布時(shí)間:2020-06-19 14:30:58 來源:網(wǎng)絡(luò) 閱讀:3270 作者:耕耘實(shí)錄 欄目:云計(jì)算

一.概述

強(qiáng)大的自愈能力是Kubernetes這一類容器編排管理引擎的一個(gè)重要特性。通常情況下,Kubernetes通過重啟發(fā)生故障的容器來實(shí)現(xiàn)自愈。除此之外,我們還有其他方式來實(shí)現(xiàn)基于Kubernetes編排的容器的健康檢查嗎?Liveness和Readiness就是不錯(cuò)的選擇。

二.實(shí)踐步驟

2.1 系統(tǒng)默認(rèn)的健康檢查。

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: healthcheck
  name: healthcheck
spec:
  restartPolicy: OnFailure
  containers:
  - name: healthcheck
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10;exit 1

創(chuàng)建一個(gè)內(nèi)容如上所述的yaml文件,命名為HealthCheck.yaml,apply:

[root@k8s-m health-check]# kubectl apply -f HealthCheck.yaml
pod/healthcheck created
[root@k8s-m health-check]# kubectl get pod
NAME          READY   STATUS             RESTARTS   AGE
healthcheck   0/1     CrashLoopBackOff   3          4m52s

我們可以看到,這個(gè)pod并未正常運(yùn)行,重啟了3次。具體的重啟日志我們可以通過describe命令來查看,此處不再贅述。我們來執(zhí)行一下以下命令:

[root@k8s-m health-check]# sh -c "sleep 2;exit 1"
[root@k8s-m health-check]# echo $?
1

我們可以看到,命令正常執(zhí)行,返回值為1。默認(rèn)情況下,Linux命令執(zhí)行之后返回值為0說明命令執(zhí)行成功。因?yàn)閳?zhí)行成功后的返回值不為0,Kubernetes默認(rèn)為容器發(fā)生故障,不斷重啟。然而,也有不少情況是服務(wù)實(shí)際發(fā)生了故障,但是進(jìn)程未退出。這種情況下,重啟往往是簡單而有效的手段。例如:訪問web服務(wù)時(shí)顯示500服務(wù)器內(nèi)部錯(cuò)誤,很多原因會(huì)造成這樣的故障,重啟可能就能迅速修復(fù)故障。

2.2 在Kubernetes中,可以通過Liveness探測告訴kebernetes什么時(shí)候?qū)崿F(xiàn)重啟自愈。

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

創(chuàng)建名為Liveness.yaml的文件,創(chuàng)建Pod:

[root@k8s-m health-check]# kubectl apply -f Liveness.yaml
pod/liveness created
[root@k8s-m health-check]# kubectl get pod
NAME       READY   STATUS    RESTARTS   AGE
liveness   1/1     Running   1          5m50s

從yaml文件中,我們可以看出,容器啟動(dòng)后創(chuàng)建/tmp/healthcheck文件,30s后刪除,刪除后sleep該進(jìn)程600s。通過cat /tmp/healthcheck來探測容器是否發(fā)生故障。如果該文件存在,則說明容器正常,該文件不存在,則殺該容器并重啟。

initialDelaySeconds:10指定容器啟動(dòng)10s之后執(zhí)行探測。一般該值要大于容器的啟動(dòng)時(shí)間。periodSeconds:5表示每5s執(zhí)行一次探測,如果連續(xù)三次執(zhí)行Liveness探測均失敗,那么會(huì)殺死該容器并重啟。

2.3 Readiness則可以告訴Kubenentes什么時(shí)候可以將容器加入到Service的負(fù)載均衡池中,對(duì)外提供服務(wù)。

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

apply該文件:

[root@k8s-m health-check]# kubectl apply -f Readiness.yaml
pod/readiness created
[root@k8s-m health-check]# kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
readiness   0/1     Running   0          84s
[root@k8s-m health-check]# kubectl get pod
NAME        READY   STATUS      RESTARTS   AGE
readiness   0/1     Completed   0          23m

從yaml文件中我們可以看出,Readiness和Liveness兩種探測的配置基本是一樣的,只需稍加改動(dòng)就可以套用。通過kubectl get pod我們發(fā)現(xiàn)這兩種Health Check主要不同在于輸出的第二列和第三列。Readiness第三列一直都是running,第二列一段時(shí)間后由1/1變?yōu)?/1。當(dāng)?shù)诙袨?/1時(shí),則說明容器不可用。具體可以通過以下命令來查看一下:

[root@k8s-m health-check]# while true;do kubectl describe pod readiness;done

Liveness和Readiness是兩種Health Check機(jī)制,不互相依賴,可以同時(shí)使用。

三.拓展

3.1 Health Check在Scale Up中的應(yīng)用。

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  template:
    metadata:
      labels:
        run: web
    spec:
      containers:
      - name: web
        image: httpd
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            scheme: HTTP
            path: /health-check
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  selector:
    run: web
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80

通過以上yaml,創(chuàng)建了一個(gè)名為web-svc的服務(wù)和名為web的Deployment。

[root@k8s-m health-check]# kubectl apply -f HealthCheck-web-deployment.yaml
deployment.apps/web unchanged
service/web-svc created
[root@k8s-m health-check]# kubectl get service web-svc
NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
web-svc   ClusterIP   10.101.1.6   <none>        8080/TCP   2m20s
[root@k8s-m health-check]# kubectl get deployment web
NAME   DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
web    3         3         3            0           3m26s
[root@k8s-m health-check]# kubectl get pod
NAME                   READY   STATUS    RESTARTS   AGE
web-7d96585f7f-q5p4d   0/1     Running   0          3m35s
web-7d96585f7f-w6tqx   0/1     Running   0          3m35s
web-7d96585f7f-xrqwm   0/1     Running   0          3m35s

重點(diǎn)關(guān)注一下17-23行,第17行指出本案例中使用的Health Check機(jī)制為Readiness,探測方法為httpGet。Kubernetes對(duì)于該方法探測成功的判斷條件時(shí)http請(qǐng)求返回值在200-400之間。schema指定了協(xié)議,可以為http(默認(rèn))和https。path指定訪問路徑,port指定端口。

容器啟動(dòng)10s后開始探測,如果 http://container_ip:8080/health-check 的返回值不是200-400,表示容器沒有準(zhǔn)備就緒,不接收Service web-svc的請(qǐng)求。/health-check則是我們實(shí)現(xiàn)探測的代碼。探測結(jié)果示例如下:

[root@k8s-m health-check]# kubectl describe pod web
Warning  Unhealthy  57s (x219 over 19m)  kubelet, k8s-n2    Readiness probe failed: Get http://10.244.2.61:8080/healthy: dial tcp 10.244.2.61:8080: connect: connection refused

3.2 Health Check在滾動(dòng)更新(Rolling Update)中的應(yīng)用。

默認(rèn)情況下,在Rolling Update過程中,Kubernetes會(huì)認(rèn)為容器已經(jīng)準(zhǔn)備就緒,進(jìn)而會(huì)逐步替換舊副本。如果新版本的容器出現(xiàn)故障,那么在版本更新完成之后可能導(dǎo)致整個(gè)應(yīng)用無法處理請(qǐng)求,無法對(duì)外提供服務(wù)。此類事件若發(fā)生在生產(chǎn)環(huán)境中,后果會(huì)非常嚴(yán)重。正確配置了Health Check,只有通過了Readiness探測的新副本才能添加到Service,如果沒有通過探測,現(xiàn)有副本就不會(huì)唄替換,業(yè)務(wù)依然正常運(yùn)行。

接下來,我們分別創(chuàng)建yaml文件app.v1.yaml和app.v2.yaml:

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 8
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 10;touch /tmp/health-check;sleep 30000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/health-check
          initialDelaySeconds: 10
          periodSeconds: 5
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 8
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 3000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/health-check
          initialDelaySeconds: 10
          periodSeconds: 5

apply文件app.v1.yaml:

[root@k8s-m health-check]# kubectl apply -f app.v1.yaml --record
deployment.apps/app created
[root@k8s-m health-check]# kubectl get pod
NAME                  READY   STATUS    RESTARTS   AGE
app-844b9b5bf-9nnrb   1/1     Running   0          2m52s
app-844b9b5bf-b8tw2   1/1     Running   0          2m52s
app-844b9b5bf-j2n9c   1/1     Running   0          2m52s
app-844b9b5bf-ml8c5   1/1     Running   0          2m52s
app-844b9b5bf-mtgr9   1/1     Running   0          2m52s
app-844b9b5bf-n4dn8   1/1     Running   0          2m52s
app-844b9b5bf-ppzh7   1/1     Running   0          2m52s
app-844b9b5bf-z55d4   1/1     Running   0          2m52s

更新到app.v2.yaml:

[root@k8s-m health-check]# kubectl apply -f app.v2.yaml --record
deployment.apps/app configured
[root@k8s-m health-check]# kubectl get pod
NAME                  READY   STATUS              RESTARTS   AGE
app-844b9b5bf-9nnrb   1/1     Running             0          3m30s
app-844b9b5bf-b8tw2   1/1     Running             0          3m30s
app-844b9b5bf-j2n9c   1/1     Running             0          3m30s
app-844b9b5bf-ml8c5   1/1     Terminating         0          3m30s
app-844b9b5bf-mtgr9   1/1     Running             0          3m30s
app-844b9b5bf-n4dn8   1/1     Running             0          3m30s
app-844b9b5bf-ppzh7   1/1     Terminating         0          3m30s
app-844b9b5bf-z55d4   1/1     Running             0          3m30s
app-cd49b84-bxvtc     0/1     ContainerCreating   0          6s
app-cd49b84-gkkj8     0/1     ContainerCreating   0          6s
app-cd49b84-jfzcm     0/1     ContainerCreating   0          6s
app-cd49b84-xl8ws     0/1     ContainerCreating   0          6s

稍后再觀察:

[root@k8s-m health-check]# kubectl get pod
NAME                  READY   STATUS    RESTARTS   AGE
app-844b9b5bf-9nnrb   1/1     Running   0          4m59s
app-844b9b5bf-b8tw2   1/1     Running   0          4m59s
app-844b9b5bf-j2n9c   1/1     Running   0          4m59s
app-844b9b5bf-mtgr9   1/1     Running   0          4m59s
app-844b9b5bf-n4dn8   1/1     Running   0          4m59s
app-844b9b5bf-z55d4   1/1     Running   0          4m59s
app-cd49b84-bxvtc     0/1     Running   0          95s
app-cd49b84-gkkj8     0/1     Running   0          95s
app-cd49b84-jfzcm     0/1     Running   0          95s
app-cd49b84-xl8ws     0/1     Running   0          95s

此刻狀態(tài)全部為running,但是依然有4個(gè)Pod的READY為0/1,再看一下:

[root@k8s-m health-check]# kubectl get deployment app
NAME   DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
app    8         10        4            6           7m20s

DESIRED表示期待的副本數(shù)為8,CURRENT表示當(dāng)前副本數(shù)為10,UP-TO-DATE表示升級(jí)了的副本數(shù)為4,AVAILABLE表示可用的副本數(shù)為6。如果不進(jìn)行更改,該狀態(tài)將一直保持下去。在此,需要注意的是,Rolling Update中刪除了2個(gè)舊副本,創(chuàng)建建了4個(gè)新副本。這里留到最后再討論。

版本回滾到v1:

[root@k8s-m health-check]# kubectl rollout history deployment app
deployment.extensions/app
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=app.v1.yaml --record=true
2         kubectl apply --filename=app.v2.yaml --record=true

[root@k8s-m health-check]# kubectl rollout undo deployment app --to-revision=1
deployment.extensions/app
[root@k8s-m health-check]# kubectl get pod
NAME                  READY   STATUS    RESTARTS   AGE
app-844b9b5bf-8qqhk   1/1     Running   0          2m37s
app-844b9b5bf-9nnrb   1/1     Running   0          18m
app-844b9b5bf-b8tw2   1/1     Running   0          18m
app-844b9b5bf-j2n9c   1/1     Running   0          18m
app-844b9b5bf-mtgr9   1/1     Running   0          18m
app-844b9b5bf-n4dn8   1/1     Running   0          18m
app-844b9b5bf-pqpm5   1/1     Running   0          2m37s
app-844b9b5bf-z55d4   1/1     Running   0          18m

四.總結(jié)

4.1 Liveness和Readiness是Kubernetes中兩種不同的Health Check方式,他們非常類似,但又有區(qū)別。可以兩者同時(shí)使用,也可以單獨(dú)使用。具體差異在上文已經(jīng)提及。

4.2 在上一篇關(guān)于Rolling Update的文章中,我曾經(jīng)提到滾動(dòng)更新過程中的替換規(guī)則。在本文中我們依然使用了默認(rèn)方式進(jìn)行更新。maxSurge和maxUnavailable兩個(gè)參數(shù)決定了更新過程中各個(gè)狀態(tài)下的副本個(gè)數(shù),這兩個(gè)參數(shù)的默認(rèn)值都是25%。更新后,總副本數(shù)=8+8*0.25=10;可用副本數(shù):8-8*0.25=6。此過程中,銷毀了2個(gè)副本,創(chuàng)建了4個(gè)新副本。

4.3 在一般生產(chǎn)環(huán)境上線時(shí),盡量使用Health Check來確保業(yè)務(wù)不受影響。這個(gè)過程的實(shí)現(xiàn)手段多樣化,需要根據(jù)實(shí)際情況進(jìn)行總結(jié)和選用。

五.相關(guān)資料

5.1 官方文檔:關(guān)于Liveness和Readiness

5.2 官方文檔:關(guān)于maxSurge和maxUnavailable

5.3 文中涉及到的代碼

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI