pod健康檢查詳解(liveness,readiness,滾動更新)

環境介紹

主機 IP地址 服務
master 192.168.1.21 k8s+httpd+nginx
node01 192.168.1.22 k8s
node02 192.168.1.23 k8s

基於[ https://blog.51cto.com/14320361/2464655]() 的實驗繼續進行

一、Pod的liveness和readiness探針

  Kubelet使用liveness probe(存活探針)來確定何時重啓容器。例如,當應用程序處於運行狀態但無法做進一步操作,liveness探針將捕獲到deadlock,重啓處於該狀態下的容器,使應用程序在存在bug的情況下依然能夠繼續運行下去
  Kubelet使用readiness probe(就緒探針)來確定容器是否已經就緒可以接受流量。只有當Pod中的容器都處於就緒狀態時kubelet纔會認定該Pod處於就緒狀態。該信號的作用是控制哪些Pod應該作爲service的後端。如果Pod處於非就緒狀態,那麼它們將會被從service的load balancer中移除。

Probe支持以下三種檢查方法:

<1>exec-命令

在用戶容器內執行一次命令,如果命令執行的退出碼爲0,則認爲應用程序正常運行,其他任務應用程序運行不正常。

  livenessProbe:
    exec:
      command:
      - cat
      - /home/laizy/test/hostpath/healthy

<2>TCPSocket

將會嘗試打開一個用戶容器的Socket連接(就是IP地址:端口)。如果能夠建立這條連接,則認爲應用程序正常運行,否則認爲應用程序運行不正常。

livenessProbe:
tcpSocket:
   port: 8080

<3>HTTPGet

調用容器內Web應用的web hook,如果返回的HTTP狀態碼在200和399之間,則認爲應用程序正常運行,否則認爲應用程序運行不正常。每進行一次HTTP健康檢查都會訪問一次指定的URL。

  httpGet: #通過httpget檢查健康,返回200-399之間,則認爲容器正常
    path: / #URI地址
    port: 80 #端口號
    #host: 127.0.0.1 #主機地址
    scheme: HTTP #支持的協議,http或者https
  httpHeaders:’’ #自定義請求的header

參數說明

initialDelaySeconds:容器啓動後第一次執行探測是需要等待多少秒。

periodSeconds:執行探測的頻率。默認是10秒,最小1秒。

timeoutSeconds:探測超時時間。默認1秒,最小1秒。

successThreshold:探測失敗後,最少連續探測成功多少次才被認定爲成功。默認是1。對於liveness必須是1。最小值是1。

探針探測的結果有以下三者之一:

Success:Container通過了檢查。
Failure:Container未通過檢查。
Unknown:未能執行檢查,因此不採取任何措施。

1. LivenessProbe(活躍度)

(1)編寫一個livenss的yaml文件

[root@node02 ~]# vim livenss.yaml
kind: Pod
apiVersion: v1
metadata:
  name: liveness
  labels:
    test: liveness
spec:
  restartPolicy: OnFailure
  containers:
  - name: liveness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300
    livenessProbe:              #存活探測
      exec:                     #通過執行命令來檢查服務是否正常
        command:                #命令模式
        - cat
        - /tmp/test
      initialDelaySeconds: 10    #pod運行10秒後開始探測
      periodSeconds: 5           #檢查的頻率,每5秒探測一次

該配置文件給Pod配置了一個容器。periodSeconds 規定kubelet要每隔5秒執行一次liveness probe。initialDelaySeconds 告訴kubelet在第一次執行probe之前要的等待10秒鐘。探針檢測命令是在容器中執行 cat /tmp/healthy 命令。如果命令執行成功,將返回0,kubelet就會認爲該容器是活着的並且很健康。如果返回非0值,kubelet就會殺掉這個容器並重啓它。

(2)運行一下

[root@master ~]# kubectl apply -f liveness.yaml 

(3)查看一下

[root@master ~]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

Liveness活躍度探測,根據探測某個文件是否存在,來確定某個服務是否正常運行,如果存在則正常,負責,它會根據你設置的Pod的重啓策略操作Pod。

2. Readiness(敏感探測、就緒性探測)

ReadinessProbe探針的使用場景livenessProbe稍有不同,有的時候應用程序可能暫時無法接受請求,比如Pod已經Running了,但是容器內應用程序尚未啓動成功,在這種情況下,如果沒有ReadinessProbe,則Kubernetes認爲它可以處理請求了,然而此時,我們知道程序還沒啓動成功是不能接收用戶請求的,所以不希望kubernetes把請求調度給它,則使用ReadinessProbe探針。
ReadinessProbe和livenessProbe可以使用相同探測方式,只是對Pod的處置方式不同,ReadinessProbe是將Pod IP:Port從對應的EndPoint列表中刪除,而livenessProbe則Kill容器並根據Pod的重啓策略來決定作出對應的措施。
ReadinessProbe探針探測容器是否已準備就緒,如果未準備就緒則kubernetes不會將流量轉發給此Pod。
ReadinessProbe探針與livenessProbe一樣也支持exec、httpGet、TCP的探測方式,配置方式相同,只不過是將livenessProbe字段修改爲ReadinessProbe。

(1)編寫一個readiness的yaml文件

[root@master ~]# vim readiness.yaml 
kind: Pod
apiVersion: v1
metadata:
  name: readiness
  labels:
    test: readiness
spec:
  restartPolicy: Never
  containers:
  - name: readiness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300
    readinessProbe:
      exec:
        command:
        - cat
        - /tmp/test
      initialDelaySeconds: 10
      periodSeconds: 5

(2)運行一下

[root@master ~]# kubectl apply -f readiness.yaml 

(3)查看一下

[root@master ~]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

3. 總結liveness和readiness探測

(1)liveness和readiness是兩種健康檢查機制,k8s將兩種探測採取相同的默認行爲,即通過判斷容器啓動進程的返回值是否爲零,來判斷探測是否成功。

(2)兩種探測配置方法完全一樣,不同之處在於探測失敗後的行爲。

liveness探測是根據重啓策略操作容器,大多數是重啓容器。

readiness則是將容器設置爲不可用,不接收Service轉發的請求。

(3)兩種探測方法可建議獨立存在,也可以同時存在。用livensess判斷是否需要重啓,實現自愈;用readiness判斷容器是否已經準備好對外提供服務。

二、 檢測的應用

1. 在scale(擴容/縮容) 中的應用。

(1)編寫一個readiness的yaml文件

[root@master ~]# vim hcscal.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: web
spec:
  replicas: 3
  template: 
    metadata:
      labels:
        run: web
    spec:
      containers:
      - name: web
        image: httpd
        ports:
        - containerPort: 80
        readinessProbe:
          httpGet:
            scheme: HTTP   #探測的協議
            path: /healthy  #訪問的目錄
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 5

---
kind: Service
apiVersion: v1
metadata:
  name: web-svc
spec:
  type: NodePort
  selector:
    run: web
  ports:
  - protocol: TCP
    port: 90
    targetPort: 80
    nodePort: 30321

在配置文件中,使用httpd鏡像,創建出一個Pod,其中periodSeconds字段指定kubelet每5秒執行一次探測,initialDelaySeconds字段告訴kubelet延遲等待10秒,探測方式爲向容器中運行的服務發送HTTP GET請求,請求8080端口下的/healthz, 任何大於或等於200且小於400的代碼表示成功。任何其他代碼表示失敗。

(2) httpGet探測方式有如下可選的控制字段

host:要連接的主機名,默認爲Pod IP,可以在http request head中設置host頭部。
scheme: 用於連接host的協議,默認爲HTTP。
path:http服務器上的訪問URI。
httpHeaders:自定義HTTP請求headers,HTTP允許重複headers。
port: 容器上要訪問端口號或名稱。

(3)運行一下

[root@master ~]# kubectl apply -f readiness.yaml 

(4)查看一下

[root@master ~]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

[root@master ~]# kubectl get pod -o wide

pod健康檢查詳解(liveness,readiness,滾動更新)

[root@master ~]# kubectl get service -o wide

pod健康檢查詳解(liveness,readiness,滾動更新)

(5)訪問一下

[root@master ~]# curl  10.244.1.21/healthy

pod健康檢查詳解(liveness,readiness,滾動更新)

(6)pod在指定目錄創建一個文件

[root@master ~]# kubectl exec web-69d659f974-7s9bc touch /usr/local/apache2/htdocs/healthy

(7)查看一下

[root@master ~]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

2. 在更新過程中的使用

(1)編寫一個readiness的yaml文件

[root@master ~]# vim app.v1.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 10
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 10; touch /tmp/healthy; sleep 3000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5

(2)運行一下並記錄版本信息

[root@master ~]# kubectl apply -f readiness.yaml --record 
查看一下
[root@master ~]# kubectl rollout history deployment app 

pod健康檢查詳解(liveness,readiness,滾動更新)

(3)查看一下

[root@master ~]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

3.升級一下Deployment

(1)編寫一個readiness的yaml文件

[root@master ~]# cp app.v1.yaml app.v2.yaml 
[root@master ~]# vim app.v2.yaml 

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 10
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 3000        #修改命令
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5

(2)運行一下並記錄版本信息

[root@master ~]# kubectl apply -f readiness.yaml --record 
查看一下
[root@master ~]# kubectl rollout history deployment app 

pod健康檢查詳解(liveness,readiness,滾動更新)

(3)查看一下

[root@master ~]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

(4)再次升級一下deployment

<1> 編寫一個readiness的yaml文件
[root@master ~]# cp app.v1.yaml app.v3.yaml 
[root@master ~]# vim app.v2.yaml 

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 10
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 3000        #修改命令
<2> 運行一下並記錄版本信息
[root@master ~]# kubectl apply -f readiness.yaml --record 
查看一下
[root@master ~]# kubectl rollout history deployment app 

pod健康檢查詳解(liveness,readiness,滾動更新)

<3> 查看一下
[root@master ~]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

4. 回滾v2版本

[root@master ~]# kubectl rollout undo deployment app --to-revision=2

查看一下

[root@master ~]# kubectl get pod

pod健康檢查詳解(liveness,readiness,滾動更新)

(1)編寫一個readiness的yaml文件

[root@master ~]# vim app.v2.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  strategy:
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 2
  replicas: 10
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 3000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5

參數介紹

minReadySeconds:

Kubernetes在等待設置的時間後才進行升級
如果沒有設置該值,Kubernetes會假設該容器啓動起來後就提供服務了
如果沒有設置該值,在某些極端情況下可能會造成服務服務正常運行

maxSurge:

升級過程中最多可以比原先設置多出的POD數量
例如:maxSurage=1,replicas=5,則表示Kubernetes會先啓動1一個新的Pod後才刪掉一箇舊的POD,整個升級過程中最多會有5+1個POD。

maxUnavaible:

升級過程中最多有多少個POD處於無法提供服務的狀態
當maxSurge不爲0時,該值也不能爲0
例如:maxUnavaible=1,則表示Kubernetes整個升級過程中最多會有1個POD處於無法服務的狀態。

(2) 運行一下並記錄版本信息

[root@master ~]# kubectl apply -f app.v2.yaml --record 
查看一下
[root@master ~]# kubectl rollout history deployment app 

pod健康檢查詳解(liveness,readiness,滾動更新)

(3) 查看一下

[root@master ~]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

三、小實驗

1)寫一個Deployment資源對象,要求2個副本,nginx鏡像。使用Readiness探測,自定義文件/test是否存在,容器開啓之後10秒開始探測,時間間隔爲10秒。

(1)編寫一個readiness的yaml文件
[root@master yaml]# vim nginx.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: web
spec:
  replicas: 2
  template:
    metadata:
      labels:
        run: web
    spec:
      containers:
      - name: readiness
        image: 192.168.1.21:5000/nginx:v1
        readinessProbe:
          exec:
            command:
            - cat
            - /usr/share/nginx/html/test
          initialDelaySeconds: 10
          periodSeconds: 10
(2)運行一下並記錄版本信息
[root@master ~]# kubectl apply -f nginx.yaml --record 
查看一下
[root@master ~]# kubectl rollout history deployment web 

pod健康檢查詳解(liveness,readiness,滾動更新)

(3)查看一下
[root@master ~]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

2)在運行之後兩個Pod裏,進入一個Pod,創建文件/test。

[root@master yaml]# kubectl exec -it web-864c7cf7fc-gpxq4  /bin/bash
root@web-68444bff8-xm22z:/# touch /usr/share/nginx/html/test

查看一下

[root@master yaml]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

3)創建一個Service資源對象,跟上述Deployment進行關聯,運行之後,查看Service資源詳細信息,確認EndPoint負載均衡後端Pod。

(1)編寫service的yaml文件

[root@master yaml]# vim nginx-svc.yaml
kind: Service
apiVersion: v1
metadata:
  name: web-svc
spec:
  type: NodePort
  selector:
    run: web
  ports:
  - protocol: TCP
    port: 90
    targetPort: 80
    nodePort: 30321

(2)執行一下

[root@master yaml]# kubectl apply -f nginx-svc.yaml 

(3)給兩個pod剛更改頁面

查看一下pod
[root@master yaml]# kubectl get pod -o wide
更改頁面
[root@master yaml]# kubectl exec -it  web-864c7cf7fc-gpxq4  /bin/bash
root@web-864c7cf7fc-gpxq4:/# echo "123">/usr/share/nginx/html/test
root@web-864c7cf7fc-gpxq4:/# exit

[root@master yaml]# kubectl exec -it  web-864c7cf7fc-pcrs9   /bin/bash
root@web-864c7cf7fc-pcrs9:/# echo "321">/usr/share/nginx/html/test
root@web-864c7cf7fc-pcrs9:/# exit

4)觀察狀態之後,嘗試將另一個Pod也寫入/test文件,然後再去查看SVC對應的EndPoint的負載均衡情況。

(1)查看一下service

[root@master yaml]# kubectl get service

pod健康檢查詳解(liveness,readiness,滾動更新)

(2)訪問一下

[root@master ~]# curl 192.168.1.21:30321/test

pod健康檢查詳解(liveness,readiness,滾動更新)

5)通過httpGet的探測方式,重新運行一下deployment資源,總結對比一下這兩種Readiness探測方式。

(1)修改deployment的yaml文件

[root@master yaml]# vim nginx.yaml 
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: web
spec:
  replicas: 2
  template:
    metadata:
      labels:
        run: web
    spec:
      containers:
      - name: readiness
        image: 192.168.1.21:5000/nginx:v1
        readinessProbe:
          httpGet:
            scheme: HTTP
            path: /usr/share/nginx/html/test
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 10

(2)執行一下

[root@master yaml]# kubectl apply -f nginx.yaml 

(3)查看一下pod

[root@master yaml]# kubectl get pod -w

pod健康檢查詳解(liveness,readiness,滾動更新)

maxSurge:此參數控制滾動更新過程中,副本總數超過預期數的值。可以是整數,也可以是百分比,默認是1。所以現在是3臺pod

(4)訪問一下

[root@master yaml]# curl 192.168.1.21:30321/test

pod健康檢查詳解(liveness,readiness,滾動更新)

6)總結對比liveness和readiness探測的相同和不同之處,以及它們的使用場景。

<1>readiness和liveness的核心區別

實際上readiness 和liveness 就如同字面意思。readiness 就是意思是否可以訪問,liveness就是是否存活。如果一個readiness 爲fail 的後果是把這個pod 的所有service 的endpoint裏面的改pod ip 刪掉,意思就這個pod對應的所有service都不會把請求轉到這pod來了。但是如果liveness 檢查結果是fail就會直接kill container,當然如果你的restart policy 是always 會重啓pod。

<2>什麼樣才叫readiness/liveness檢測失敗呢?

實際上k8s提供了3中檢測手段,

http get 返回200-400算成功,別的算失敗
tcp socket 你指定的tcp端口打開,比如能telnet 上
cmd exec 在容器中執行一個命令 推出返回0 算成功。
每中方式都可以定義在readiness 或者liveness 中。比如定義readiness 中http get 就是意思說如果我定義的這個path的http get 請求返回200-400以外的http code 就把我從所有有我的服務裏面刪了吧,如果定義在liveness裏面就是把我kill 了。

<3>readiness和readiness的使用環境

比如如果一個http 服務你想一旦它訪問有問題我就想重啓容器。那你就定義個liveness 檢測手段是http get。反之如果有問題我不想讓它重啓,只是想把它除名不要讓請求到它這裏來。就配置readiness。

注意,liveness不會重啓pod,pod是否會重啓由你的restart policy(重啓策略)控制。

參考:
https://www.jianshu.com/p/16a375199cf2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章