k8s健康檢查(9)

1、默認的健康檢查

  強大的自愈能力是 Kubernetes 這類容器編排引擎的一個重要特性。自愈的默認實現方式是自動重啓發生故障的容器。除此以外,用戶還能夠利用 LivenessReadiness 探測機制設置更精細的健康檢查,進而實現以下需求:web

  (1)零停機部署。docker

  (2)避免部署無效的鏡像。數據庫

  (3)更加安全的滾動升級。後端

  每一個容器啓動時都會執行一個進程,此進程由 Dockerfile 的 CMD 或 ENTRYPOINT 指定。若是進程退出時返回碼非零,則認爲容器發生故障,Kubernetes 就會根據 restartPolicy 重啓容器。api

一、模擬一個容器發生故障的場景,Pod 配置文件以下:緩存

[root@ren7 yaml]# cat pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: healthcheck
  labels:
    test: healthcheck
spec:
  containers:
    - name: healthcheck
      image: reg.yunwei.com/learn/busybox:latest
      args: 
      - /bin/sh
      - -c
      - sleep 10; exit 1
  restartPolicy: OnFailure

  Pod 的 restartPolicy 設置爲 OnFailure,默認爲 Always。安全

  sleep 10; exit 1 模擬容器啓動 10 秒後發生故障。、服務器

二、執行 kubectl apply 建立 Pod,命名爲 healthcheck。app

[root@ren7 yaml]# kubectl apply -f pod1.yaml 
pod/healthcheck created

三、過幾分鐘查看 Pod 的狀態:負載均衡

[root@ren7 yaml]# kubectl get pod -o wide
NAME          READY   STATUS             RESTARTS   AGE    IP              NODE           NOMINATED NODE   READINESS GATES
healthcheck   0/1     CrashLoopBackOff   3          101s   172.20.72.142   192.168.11.5   <none>           <none>

  可看到容器當前已經重啓了 3次。

  在上面的例子中,容器進程返回值非零,Kubernetes 則認爲容器發生故障,須要重啓。但有很多狀況是發生了故障,但進程並不會退出。好比訪問 Web 服務器時顯示 500 內部錯誤,多是系統超載,也多是資源死鎖,此時 httpd 進程並無異常退出,在這種狀況下重啓容器多是最直接最有效的解決方案,那咱們如何利用 Health Check 機制來處理這類場景呢?

2、Liveness探測

  Liveness 探測讓用戶能夠自定義判斷容器是否健康的條件。若是探測失敗,Kubernetes 就會重啓容器。

一、建立以下 Pod:

[root@ren7 yaml]# cat pod2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: liveness
  labels:
    test: liveness
spec:
  containers:
    - name: liveness
      image: reg.yunwei.com/learn/busybox:latest
      args: 
      - /bin/sh
      - -c
      - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 livenessProbe: exec: command: - cat
          - /tmp/healthy initialDelaySeconds: 10 periodSeconds: 5
  restartPolicy: OnFailure

  啓動進程首先建立文件 /tmp/healthy,30 秒後刪除,在咱們的設定中,若是 /tmp/healthy 文件存在,則認爲容器處於正常狀態,反之則發生故障。

  livenessProbe 部分定義如何執行 Liveness 探測:

  探測的方法是:經過 cat 命令檢查 /tmp/healthy 文件是否存在。若是命令執行成功,返回值爲零,Kubernetes 則認爲本次 Liveness 探測成功;若是命令返回值非零,本次 Liveness 探測失敗。

  initialDelaySeconds: 10 指定容器啓動 10 以後開始執行 Liveness 探測,咱們通常會根據應用啓動的準備時間來設置。好比某個應用正常啓動要花 30 秒,那麼 initialDelaySeconds 的值就應該大於 30。

  periodSeconds: 5 指定每 5 秒執行一次 Liveness 探測。Kubernetes 若是連續執行 3 次 Liveness 探測均失敗,則會殺掉並重啓容器。

二、下面建立 Pod liveness:

[root@ren7 yaml]# kubectl apply -f pod2.yaml 
pod/liveness created

  從配置文件可知,最開始的 30 秒,/tmp/healthy 存在,cat 命令返回 0,Liveness 探測成功

三、這段時間 kubectl describe pod liveness 的 Events部分會顯示正常的日誌。

[root@ren7 yaml]# kubectl describe pod liveness
Name:         liveness
Namespace:    default
Node:         192.168.11.5/192.168.11.5
Start Time:   Sat, 26 Oct 2019 10:59:15 +0800
Labels:       test=liveness
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"test":"liveness"},"name":"liveness","namespace":"default"},"spec":...
Status:       Running
IP:           172.20.72.141
Containers:
  liveness:
    Container ID:  docker://abcecd2fe5d291ac028d8eebbb59ef37b22a558d451b0c401da44c1bcd7962e0
    Image:         reg.yunwei.com/learn/busybox:latest
    Image ID:      docker-pullable://reg.yunwei.com/learn/busybox@sha256:dd97a3fe6d721c5cf03abac0f50e2848dc583f7c4e41bf39102ceb42edfd1808
    Port:          <none>
    Host Port:     <none>
    Args:
      /bin/sh
      -c
      touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    State:          Running
      Started:      Sat, 26 Oct 2019 10:59:17 +0800
    Ready:          True
    Restart Count:  0
    Liveness:       exec [cat /tmp/healthy] delay=10s timeout=1s period=5s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-qvqql (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-qvqql:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-qvqql
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     <none>
Events:
  Type    Reason     Age   From                   Message
  ----    ------     ----  ----                   -------
  Normal  Scheduled  18s   default-scheduler      Successfully assigned default/liveness to 192.168.11.5
  Normal  Pulling    17s   kubelet, 192.168.11.5  Pulling image "reg.yunwei.com/learn/busybox:latest"
  Normal  Pulled     16s   kubelet, 192.168.11.5  Successfully pulled image "reg.yunwei.com/learn/busybox:latest"
  Normal  Created    16s   kubelet, 192.168.11.5  Created container liveness
  Normal  Started    16s   kubelet, 192.168.11.5  Started container liveness

四、35秒後再次查看日誌

  35 秒以後,日誌會顯示 /tmp/healthy 已經不存在,Liveness 探測失敗。再過幾十秒,幾回探測都失敗後,容器會被重啓。

[root@ren7 yaml]# kubectl describe pod liveness
Name:         liveness
Namespace:    default
Node:         192.168.11.5/192.168.11.5
Start Time:   Sat, 26 Oct 2019 10:59:15 +0800
Labels:       test=liveness
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"test":"liveness"},"name":"liveness","namespace":"default"},"spec":...
Status:       Running
IP:           172.20.72.141
Containers:
  liveness:
    Container ID:  docker://abcecd2fe5d291ac028d8eebbb59ef37b22a558d451b0c401da44c1bcd7962e0
    Image:         reg.yunwei.com/learn/busybox:latest
    Image ID:      docker-pullable://reg.yunwei.com/learn/busybox@sha256:dd97a3fe6d721c5cf03abac0f50e2848dc583f7c4e41bf39102ceb42edfd1808
    Port:          <none>
    Host Port:     <none>
    Args:
      /bin/sh
      -c
      touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    State:          Running
      Started:      Sat, 26 Oct 2019 10:59:17 +0800
    Ready:          True
    Restart Count:  0
    Liveness:       exec [cat /tmp/healthy] delay=10s timeout=1s period=5s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-qvqql (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-qvqql:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-qvqql
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     <none>
Events:
  Type     Reason     Age                From                   Message
  ----     ------     ----               ----                   -------
  Normal   Scheduled  63s                default-scheduler      Successfully assigned default/liveness to 192.168.11.5
  Normal   Pulling    62s                kubelet, 192.168.11.5  Pulling image "reg.yunwei.com/learn/busybox:latest"
  Normal   Pulled     61s                kubelet, 192.168.11.5  Successfully pulled image "reg.yunwei.com/learn/busybox:latest"
  Normal   Created    61s                kubelet, 192.168.11.5  Created container liveness
  Normal   Started    61s                kubelet, 192.168.11.5  Started container liveness
  Warning  Unhealthy  19s (x3 over 29s)  kubelet, 192.168.11.5  Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Killing    19s                kubelet, 192.168.11.5  Container liveness failed liveness probe, will be restarted

五、查看pod

  能夠發現容器開始被重啓

[root@ren7 yaml]# kubectl get pod -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP              NODE           NOMINATED NODE   READINESS GATES
liveness   1/1     Running   1          76s   172.20.72.141   192.168.11.5   <none>           <none>

3、Readiness 探測 

  除了 Liveness 探測,Kubernetes Health Check 機制還包括 Readiness 探測。

  用戶經過 Liveness 探測能夠告訴 Kubernetes 何時經過重啓容器實現自愈;Readiness 探測則是告訴 Kubernetes 何時能夠將容器加入到 Service 負載均衡池中,對外提供服務。

一、Readiness 探測的配置語法與 Liveness 探測徹底同樣

[root@ren7 yaml]# cat pod-read.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: readiness
  labels:
    test: readiness
spec:
  containers:
    - name: readiness
      image: reg.yunwei.com/learn/busybox:latest
      args: 
      - /bin/sh
      - -c
      - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 readinessProbe:
        exec:
          command:
          - cat
          - /tmp/healthy
        initialDelaySeconds: 10
        periodSeconds: 5
  restartPolicy: OnFailure

  這個配置文件只是將前面例子中的 liveness 替換爲了 readiness,咱們看看有什麼不一樣的效果。

二、部署

[root@ren7 yaml]# kubectl get pod readiness
NAME        READY   STATUS    RESTARTS   AGE
readiness   0/1     Running   0          14s
[root@ren7 yaml]# kubectl get pod readiness
NAME        READY   STATUS    RESTARTS   AGE
readiness   1/1     Running   0          26s
[root@ren7 yaml]# kubectl get pod readiness
NAME        READY   STATUS    RESTARTS   AGE
readiness   0/1     Running   0          76s

  Pod readiness 的 READY 狀態經歷了以下變化:

  剛被建立時,READY 狀態爲不可用。

  15 秒後(initialDelaySeconds + periodSeconds),第一次進行 Readiness 探測併成功返回,設置 READY 爲可用。

  30 秒後,/tmp/healthy 被刪除,連續 3 次 Readiness 探測均失敗後,READY 被設置爲不可用。

三、經過 kubectl describe pod readiness 也能夠看到 Readiness 探測失敗的日誌。

[root@ren7 yaml]# kubectl describe pod readiness
Name:         readiness
Namespace:    default
Node:         192.168.11.5/192.168.11.5
Start Time:   Sat, 26 Oct 2019 11:10:24 +0800
Labels:       test=readiness
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"test":"readiness"},"name":"readiness","namespace":"default"},"spec...
Status:       Running
IP:           172.20.72.143
Containers:
  readiness:
    Container ID:  docker://7fc2db813b612e71a82b27d7a63fe1860982f4c20fbc1e110a92f3118b08fa82
    Image:         reg.yunwei.com/learn/busybox:latest
    Image ID:      docker-pullable://reg.yunwei.com/learn/busybox@sha256:dd97a3fe6d721c5cf03abac0f50e2848dc583f7c4e41bf39102ceb42edfd1808
    Port:          <none>
    Host Port:     <none>
    Args:
      /bin/sh
      -c
      touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    State:          Running
      Started:      Sat, 26 Oct 2019 11:10:26 +0800
    Ready:          False
    Restart Count:  0
    Readiness:      exec [cat /tmp/healthy] delay=10s timeout=1s period=5s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-qvqql (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             False 
  ContainersReady   False 
  PodScheduled      True 
Volumes:
  default-token-qvqql:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-qvqql
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     <none>
Events:
  Type     Reason     Age                 From                   Message
  ----     ------     ----                ----                   -------
  Normal   Scheduled  2m18s               default-scheduler      Successfully assigned default/readiness to 192.168.11.5
  Normal   Pulling    2m17s               kubelet, 192.168.11.5  Pulling image "reg.yunwei.com/learn/busybox:latest"
  Normal   Pulled     2m16s               kubelet, 192.168.11.5  Successfully pulled image "reg.yunwei.com/learn/busybox:latest"
  Normal   Created    2m16s               kubelet, 192.168.11.5  Created container readiness
  Normal   Started    2m16s               kubelet, 192.168.11.5  Started container readiness
  Warning  Unhealthy  3s (x21 over 103s)  kubelet, 192.168.11.5  Readiness probe failed: cat: can't open '/tmp/healthy': No such file or directory

  下面對 Liveness 探測和 Readiness 探測作個比較:

  Liveness 探測和 Readiness 探測是兩種 Health Check 機制,若是不特地配置,Kubernetes 將對兩種探測採起相同的默認行爲,即經過判斷容器啓動進程的返回值是否爲零來判斷探測是否成功。

  兩種探測的配置方法徹底同樣,支持的配置參數也同樣。不一樣之處在於探測失敗後的行爲:Liveness 探測是重啓容器;Readiness 探測則是將容器設置爲不可用,不接收 Service 轉發的請求。

  Liveness 探測和 Readiness 探測是獨立執行的,兩者之間沒有依賴,因此能夠單獨使用,也能夠同時使用。用 Liveness 探測判斷容器是否須要重啓以實現自愈;用 Readiness 探測判斷容器是否已經準備好對外提供服務。

4、健康檢測在scale up中的應用

  對於多副本應用,當執行 Scale Up 操做時,新副本會做爲 backend 被添加到 Service 的負載均衡中,與已有副本一塊兒處理客戶的請求。考慮到應用啓動一般都須要一個準備階段,好比加載緩存數據,鏈接數據庫等,從容器啓動到真正可以提供服務是須要一段時間的。咱們能夠經過 Readiness 探測判斷容器是否就緒,避免將請求發送到尚未 ready 的 backend。

一、下面是示例應用的配置文件。

[root@ren7 yaml]# cat healthy.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  template:
    metadata:
      labels:
        name: web
        run: web
    spec:
      containers:
      - name: web
        image: reg.yunwei.com/learn/httpd:latest
        ports:
        - containerPort: 80 readinessProbe: httpGet: scheme: HTTP path: /healthy port: 8080 initialDelaySeconds: 10 periodSeconds: 5

---
apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  ports: 
    - port: 8080
      targetPort: 80
      protocol: TCP
  selector:
    run: web

  重點關注 readinessProbe 部分。這裏咱們使用了不一樣於 exec 的另外一種探測方法 -- httpGet。Kubernetes 對於該方法探測成功的判斷條件是 http 請求的返回代碼在 200-400 之間。

  schema 指定協議,支持 HTTP(默認值)和 HTTPS。

  path 指定訪問路徑。

  port 指定端口。

上面配置的做用是:

  容器啓動 10 秒以後開始探測。

  若是 http://[container_ip]:8080/healthy 返回代碼不是 200-400,表示容器沒有就緒,不接收 Service web-svc 的請求。

  每隔 5 秒再探測一次。

  直到返回代碼爲 200-400,代表容器已經就緒,而後將其加入到 web-svc 的負載均衡中,開始處理客戶請求。

  探測會繼續以 5 秒的間隔執行,若是連續發生 3 次失敗,容器又會從負載均衡中移除,直到下次探測成功從新加入。

5、健康檢測在滾動更新中的應用

  現有一個正常運行的多副本應用,接下來對應用進行更新(好比使用更高版本的 image),Kubernetes 會啓動新副本,而後發生了以下事件:

  正常狀況下新副本須要 10 秒鐘完成準備工做,在此以前沒法響應業務請求。

  但因爲人爲配置錯誤,副本始終沒法完成準備工做(好比沒法鏈接後端數據庫)。

  思考一個問題:若是沒有配置 Health Check,會出現怎樣的狀況?

  由於新副本自己沒有異常退出,默認的 Health Check 機制會認爲容器已經就緒,進而會逐步用新副本替換現有副本,其結果就是:當全部舊副本都被替換後,整個應用將沒法處理請求,沒法對外提供服務。若是這是發生在重要的生產系統上,後果會很是嚴重。

  若是正確配置了 Health Check,新副本只有經過了 Readiness 探測,纔會被添加到 Service;若是沒有經過探測,現有副本不會被所有替換,業務仍然正常進行。

一、用以下配置文件 app.v1.yml 模擬一個 10 副本的應用:

[root@ren7 yaml]# cat app.v1.yml 
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 10
  template:
    metadata:
      labels:
        name: app
        run: app
    spec:
      containers:
      - name: app
        image: reg.yunwei.com/learn/busybox:latest
        args: 
        - /bin/sh
        - -c
        - sleep 10; touch /tmp/healthy; sleep 30000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5

  10秒後副本可以經過readiness探測

二、執行部署操做

[root@ren7 yaml]# kubectl apply -f app.v1.yml 
deployment.apps/app created
[root@ren7 yaml]# kubectl get deployment app
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
app    10/10   10           10          39s
[root@ren7 yaml]# kubectl get po -o wide
NAME                   READY   STATUS    RESTARTS   AGE   IP              NODE           NOMINATED NODE   READINESS GATES
app-577d86d68d-2qb4c   1/1     Running   0          50s   172.20.72.147   192.168.11.5   <none>           <none>
app-577d86d68d-45fc2   1/1     Running   0          50s   172.20.72.149   192.168.11.5   <none>           <none>
app-577d86d68d-4mbdj   1/1     Running   0          50s   172.20.33.114   192.168.11.6   <none>           <none>
app-577d86d68d-8hvjx   1/1     Running   0          50s   172.20.33.111   192.168.11.6   <none>           <none>
app-577d86d68d-gnwkn   1/1     Running   0          50s   172.20.72.146   192.168.11.5   <none>           <none>
app-577d86d68d-gv64q   1/1     Running   0          50s   172.20.33.113   192.168.11.6   <none>           <none>
app-577d86d68d-mgvv9   1/1     Running   0          50s   172.20.72.145   192.168.11.5   <none>           <none>
app-577d86d68d-mlq22   1/1     Running   0          50s   172.20.33.115   192.168.11.6   <none>           <none>
app-577d86d68d-n9cxh   1/1     Running   0          50s   172.20.33.112   192.168.11.6   <none>           <none>
app-577d86d68d-qjj92   1/1     Running   0          50s   172.20.72.148   192.168.11.5   <none>           <none>

三、接下來滾動更新應用,配置文件 app.v2.yml 以下:

[root@ren7 yaml]# cat app.v2.yml 
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 10
  template:
    metadata:
      labels:
        name: app
        run: app
    spec:
      containers:
      - name: app
        image: reg.yunwei.com/learn/busybox:latest
        args: 
        - /bin/sh
        - -c
        - sleep 30000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5

  很顯然,因爲新副本中不存在 /tmp/healthy,是沒法經過 Readiness 探測的。

四、查看探測結果

[root@ren7 yaml]# kubectl apply -f app.v2.yml --record
deployment.apps/app configured
[root@ren7 yaml]# kubectl get deployment app
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
app    8/10    5            8           3m57s
[root@ren7 yaml]# kubectl get deployment app
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
app    8/10    5            8           4m25s
[root@ren7 yaml]# kubectl get po -o wide
NAME                   READY   STATUS    RESTARTS   AGE     IP              NODE           NOMINATED NODE   READINESS GATES
app-577d86d68d-2qb4c   1/1     Running   0          4m31s   172.20.72.147   192.168.11.5   <none>           <none>
app-577d86d68d-4mbdj   1/1     Running   0          4m31s   172.20.33.114   192.168.11.6   <none>           <none>
app-577d86d68d-8hvjx   1/1     Running   0          4m31s   172.20.33.111   192.168.11.6   <none>           <none>
app-577d86d68d-gnwkn   1/1     Running   0          4m31s   172.20.72.146   192.168.11.5   <none>           <none>
app-577d86d68d-gv64q   1/1     Running   0          4m31s   172.20.33.113   192.168.11.6   <none>           <none>
app-577d86d68d-mgvv9   1/1     Running   0          4m31s   172.20.72.145   192.168.11.5   <none>           <none>
app-577d86d68d-n9cxh   1/1     Running   0          4m31s   172.20.33.112   192.168.11.6   <none>           <none>
app-577d86d68d-qjj92   1/1     Running   0          4m31s   172.20.72.148   192.168.11.5   <none>           <none>
app-58ccc746ff-44kz6   0/1     Running   0          45s     172.20.33.116   192.168.11.6   <none>           <none>
app-58ccc746ff-4ndkq   0/1     Running   0          45s     172.20.72.151   192.168.11.5   <none>           <none>
app-58ccc746ff-5jfvr   0/1     Running   0          46s     172.20.72.150   192.168.11.5   <none>           <none>
app-58ccc746ff-qz7pn   0/1     Running   0          46s     172.20.33.117   192.168.11.6   <none>           <none>
app-58ccc746ff-z4h94   0/1     Running   0          46s     172.20.72.152   192.168.11.5   <none>           <none>
[root@ren7 yaml]# 

  先關注 kubectl get pod 輸出:

  從 Pod 的 AGE 欄可判斷,最後 5 個 Pod 是新副本,目前處於 NOT READY 狀態。

舊副本從最初 10 個減小到 8 個。

  再來看 kubectl get deployment app 的輸出:

  DESIRED 10 表示指望的狀態是 10 個 READY 的副本。

  CURRENT 13 表示當前副本的總數:即 8 箇舊副本 + 5 個新副本。

  UP-TO-DATE 5 表示當前已經完成更新的副本數:即 5 個新副本。

  AVAILABLE 8 表示當前處於 READY 狀態的副本數:即 8箇舊副本。

  在咱們的設定中,新副本始終都沒法經過 Readiness 探測,因此這個狀態會一直保持下去。

  上面咱們模擬了一個滾動更新失敗的場景。不過幸運的是:Health Check 幫咱們屏蔽了有缺陷的副本,同時保留了大部分舊副本,業務沒有因更新失敗受到影響。

  接下來咱們要回答:爲何新建立的副本數是 5 個,同時只銷毀了 2 箇舊副本?

  緣由是:滾動更新經過參數 maxSurge 和 maxUnavailable 來控制副本替換的數量。

maxSurge

  此參數控制滾動更新過程當中副本總數的超過 DESIRED 的上限。maxSurge 能夠是具體的整數(好比 3),也能夠是百分百,向上取整。maxSurge 默認值爲 25%。

  在上面的例子中,DESIRED 爲 10,那麼副本總數的最大值爲:

  roundUp(10 + 10 * 25%) = 13

  因此咱們看到 CURRENT 就是 13。

maxUnavailable

  此參數控制滾動更新過程當中,不可用的副本相佔 DESIRED 的最大比例。 maxUnavailable 能夠是具體的整數(好比 3),也能夠是百分百,向下取整。maxUnavailable 默認值爲 25%。

  在上面的例子中,DESIRED 爲 10,那麼可用的副本數至少要爲:

  10 - roundDown(10 * 25%) = 8

  因此咱們看到 AVAILABLE 就是 8。

  maxSurge 值越大,初始建立的新副本數量就越多;maxUnavailable 值越大,初始銷燬的舊副本數量就越多。

  理想狀況下,咱們這個案例滾動更新的過程應該是這樣的:

  首先建立 3 個新副本使副本總數達到 13 個。

  而後銷燬 2 箇舊副本使可用的副本數降到 8 個。

  當這 2 箇舊副本成功銷燬後,可再建立 2 個新副本,使副本總數保持爲 13 個。

  當新副本經過 Readiness 探測後,會使可用副本數增長,超過 8。

  進而能夠繼續銷燬更多的舊副本,使可用副本數回到 8。

  舊副本的銷燬使副本總數低於 13,這樣就容許建立更多的新副本。

  這個過程會持續進行,最終全部的舊副本都會被新副本替換,滾動更新完成。

6、更新失敗回退

[root@ren7 yaml]# kubectl rollout history deployment app
deployment.extensions/app 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl apply --filename=app.v2.yml --record=true
[root@ren7 yaml]# kubectl get deployment app
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
app    8/10    5            8           7m50s
[root@ren7 yaml]# kubectl rollout undo deployment app --to-revision=1
deployment.extensions/app rolled back
[root@ren7 yaml]# kubectl get deployment app
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
app    10/10   10           10          8m53s

  若是要定製 maxSurge 和 maxUnavailable,能夠以下配置:

[root@ren7 yaml]# cat app.v2.yml 
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  strategy: rollingUpdate: maxSurge: 35% maxUnavailable: 35%
  replicas: 10
  template:
    metadata:
      labels:
        name: app
        run: app
    spec:
      containers:
      - name: app
        image: reg.yunwei.com/learn/busybox:latest
        args: 
        - /bin/sh
        - -c
        - sleep 30000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5
相關文章
相關標籤/搜索