k8s探測機制之pod健康檢查

一:需求來源:

首先來看一下,整個需求的來源:當把應用遷移到 Kubernetes 以後,要如何去保障應用的健康與穩定呢?其實很簡單,能夠從兩個方面來進行加強:html

1,首先是提升應用的可觀測性;
2,第二是提升應用的可恢復能力。node

從可觀測性上來說,能夠在三個方面來去作加強:nginx

1,首先是應用的健康狀態上面,能夠實時地進行觀測;
2,第二個是能夠獲取應用的資源使用狀況;
3,第三個是能夠拿到應用的實時日誌,進行問題的診斷與分析。web

當出現了問題以後,首先要作的事情是要下降影響的範圍,進行問題的調試與診斷。最後當出現問題的時候,理想的情況是:能夠經過和 K8s 集成的自愈機制進行完整的恢復。 vim

二:介紹兩種探測方式:livenessProbe和ReadnessProbe

  • livenessProbe:[活躍度探測],就是根據用戶自定義的規則判斷容器是否健康。也叫存活指針,若是 Liveness 指針判斷容器不健康,此時會經過 kubelet 殺掉相應的 pod,並根據重啓策略來判斷是否重啓這個容器。若是默認不配置 Liveness 指針,則默認狀況下認爲它這個探測默認返回是成功的。api

  • ReadnessProbe:[敏捷探測],用來判斷這個容器是否啓動完成,即 pod 的 狀態(指望值)是否 爲ready。若是探測的一個結果是不成功,那麼此時它會從 pod 上 Endpoint 上移除,也就是說從接入層上面會把前一個 pod 進行摘除(設置pod爲不可用的狀態),直到下一次判斷成功,這個 pod 纔會再次掛到相應的 endpoint 之上。

什麼是Endpoint?
Endpoint是k8s集羣中的一個資源對象,存儲在etcd中,用來記錄一個service對應的全部pod的訪問地址。app

2,Liveness和Readness兩種探測機制的使用場景:
Liveness 指針適用場景是支持那些能夠從新拉起的應用,而 Readiness 指針主要應對的是啓動以後沒法當即對外提供服務的這些應用。curl

3,,Liveness和Readness兩種探測機制的相同點和不一樣點:
相同點是根據探測pod內某個應用或文件,來檢查pod的健康情況,不一樣點是liveness若是探測失敗會重啓pod,而readliness則在連續3次探測失敗以後,會將pod設置爲不可用的狀態,並不會重啓pod。tcp

4,Liveness 指針和 Readiness 指針支持三種不一樣的探測方式:ide

  • 1,第一種是 httpGet。它是經過發送 http Get 請求來進行判斷的,當返回碼是 200-399 之間的狀態碼時,標識這個應用是健康的;
  • 2,第二種探測方式是 Exec。它是經過執行容器中的一個命令來判斷當前的服務是不是正常的,當命令行的返回結果是 0,則標識容器是健康的;
  • 3,第三種探測方式是 tcpSocket 。它是經過探測容器的 IP 和 Port 進行 TCP 健康檢查,若是這個 TCP 的連接可以正常被創建,那麼標識當前這個容器是健康的。

第一種探測方式和第三種很是類似,通常經常使用的是第一和第二種的探測方式。

三,探測機制應用實例:

1,LivenessProbe:

方法1:使用exec探測方式,查看pod內某個指定的文件是否存在,若是存在則認爲狀態爲健康的,不然會根據設置的重啓重啓策略重啓pod。

###pod的配置文件:

[root@sqm-master yaml]# vim livenss.yaml
kind: Pod
apiVersion: v1
metadata:
  name: liveness
  labels:
    name: liveness
spec:
  restartPolicy: OnFailure    ##定義重啓策略,僅在pod對象出現錯誤時才重啓
  containers:
  - name: liveness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/test; sleep 30; rm -rf /tmp/test; sleep 300  #建立文件,而且在30秒後將文件進行刪除
    livenessProbe:      #執行活躍度探測
      exec:
        command:
        - cat              #探測/tmp目錄下是有test文件,若是有則表明健康,若是沒有則執行重啓pod策略。
        - /tmp/test
      initialDelaySeconds: 10        #當容器運行多久以後開始探測(單位是s)
      periodSeconds: 5     #探測頻率(單位s),每隔5秒探測一次。

探測機制中其餘的可選字段:

  • initialDelaySeconds:容器啓動後第一次執行探測是須要等待多少秒。
  • periodSeconds:執行探測的頻率。默認是10秒,最小1秒。
  • timeoutSeconds:探測超時時間。默認1秒,最小1秒。
  • successThreshold:探測失敗後,最少連續探測成功多少次才被認定爲成功。默認是1。對於liveness必須是1。最小值是1。
  • failureThreshold:探測成功後,最少連續探測失敗多少次才被認定爲失敗。默認是3。最小值是1。
//運行該pod進行測試:
[root@sqm-master yaml]# kubectl  apply -f  livenss.yaml 
pod/liveness created

//監測pod的狀態:
會在容器啓動10秒後開始探測,且每5s探測一次。
k8s探測機制之pod健康檢查
咱們能夠看到pod一直在重啓中,從上圖看到RESTARTS
的次數已經爲7次了,緣由是在啓動pod時執行了該命令:

/bin/sh -c "touch /tmp/test; sleep 30; rm -rf /tmp/test; sleep 300"

在容器生命的最初30秒內有一個 /tmp/test 文件,在這30秒內 cat /tmp/test命令會返回一個成功的返回碼。但30秒後, cat /tmp/test 將返回失敗的返回碼,會觸發pod的重啓策略。

//咱們來查看一下pod的Events信息:
[root@sqm-master ~]# kubectl  describe  pod liveness

k8s探測機制之pod健康檢查
從上面的事件中能夠發現,探測失敗,將重啓容器,緣由是在指定的目錄下沒有發現該文件。

方法2:使用httpGet探測方式,運行一個web服務,探測web網頁的根目錄下是否有指定的文件,也就等同於 「curl -I 容器ip地址:/healthy」。(這裏的目錄/,指定的是容器內提供web服務的主目錄。)

//pod的yaml文件:

[root@sqm-master yaml]# vim http-livenss.yaml
apiVersion: v1
kind: Pod
metadata:
  name: web
  labels:
    name: mynginx
spec:
  restartPolicy: OnFailure      #定義pod重啓策略
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    livenessProbe:       #定義探測機制
      httpGet:               #探測方式爲httpGet
        scheme: HTTP    #指定協議
        path: /healthy       #指定路徑下的文件,若是不存在,探測失敗
        port: 80
      initialDelaySeconds: 10       #當容器運行多久以後開始探測(單位是s)
      periodSeconds: 5       #探測頻率(單位s),每隔5秒探測一次
---
apiVersion: v1       #關聯一個service對象
kind: Service
metadata:
  name: web-svc
spec:
  selector:
    name: mynginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

httpGet探測方式有以下可選的控制字段:

  • host:鏈接的主機名,默認鏈接到pod的IP。你可能想在http header中設置」Host」而不是使用IP。
  • scheme:鏈接使用的schema,默認HTTP。
  • path: 訪問的HTTP server的path。
  • httpHeaders:自定義請求的header。HTTP運行重複的header。
  • port:訪問的容器的端口名字或者端口號。端口號必須介於1和65525之間。
//運行該pod:
[root@sqm-master yaml]# kubectl  apply -f  http-livenss.yaml 
pod/web created
service/web-svc created

##查看pod運行10秒前的狀況:
k8s探測機制之pod健康檢查
##最開始的10秒該容器是活着的,且返回的狀態碼爲200.
k8s探測機制之pod健康檢查

###10秒後當探測機制開始探測時再次查看pod的狀況:
k8s探測機制之pod健康檢查

//查看的pod的events:
[root@sqm-master yaml]# kubectl describe  pod web

k8s探測機制之pod健康檢查

能夠看到返回的狀態碼爲404,表示在網頁的根目錄下並無找到指定的文件,表示探測失敗,且重啓4次,狀態是completed(完成的狀態),說明pod是存在問題的。

2)接下來咱們繼續進行檢測,使其最終探測成功:
修改pod的配置文件:
[root@sqm-master yaml]# vim http-livenss.yaml
k8s探測機制之pod健康檢查

//從新運行pod:
[root@sqm-master yaml]# kubectl  delete -f  http-livenss.yaml 
pod "web" deleted
service "web-svc" deleted
[root@sqm-master yaml]# kubectl apply -f  http-livenss.yaml 
pod/web created
service/web-svc created
//最終咱們查看pod的狀態及Events信息:
[root@sqm-master yaml]# kubectl  get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
web    1/1     Running   0          5s    10.244.1.11   node01   <none>           <none>
[root@sqm-master yaml]# kubectl  describe  pod web 
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  71s   default-scheduler  Successfully assigned default/web to node01
  Normal  Pulling    71s   kubelet, node01    Pulling image "nginx"
  Normal  Pulled     70s   kubelet, node01    Successfully pulled image "nginx"
  Normal  Created    70s   kubelet, node01    Created container nginx
  Normal  Started    70s   kubelet, node01    Started container nginx

能夠看到pod的狀態時正常運行的。

##測試訪問網頁頭部信息:
[root@sqm-master yaml]# curl -I 10.244.1.11

k8s探測機制之pod健康檢查
返回的狀態碼爲200,表示這個pod的情況時健康的。

ReadnessProbe探測:

方法1:使用exec探測方式,與iveness相同,探測某個文件是否存在。
//pod的配置文件以下:

[root@sqm-master yaml]# vim readiness.yaml
kind: Pod
apiVersion: v1
metadata:
  name: readiness
  labels:
    name: readiness
spec:
  restartPolicy: OnFailure
  containers:
  - name: readiness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/test; sleep 30; rm -rf /tmp/test; sleep 300;
    readinessProbe:   #定義readiness探測方式
      exec:
        command:
        - cat
        - /tmp/test
      initialDelaySeconds: 10
      periodSeconds: 5
//運行該pod:
[root@sqm-master yaml]# kubectl apply -f  readiness.yaml 
pod/readiness created

//檢測pod的狀態:
k8s探測機制之pod健康檢查

//查看pod的Events:
[root@sqm-master yaml]# kubectl  describe  pod readiness

k8s探測機制之pod健康檢查
能夠看到找不到該文件,表示探測失敗,可是readiness機制與liveness機制不一樣,它並不會重啓pod,而是連續探測3次失敗後,則將容器設置爲不可用的狀態。

方法二:httpGet方式。

[root@sqm-master yaml]# vim http-readiness.yaml
apiVersion: v1
kind: Pod
metadata:
  name: web2
  labels:
    name: web2
spec:
  containers:
  - name: web2
    image: nginx
    ports:
    - containerPort: 81
    readinessProbe:
      httpGet:
        scheme: HTTP    #指定協議
        path: /healthy    #指定路徑,若是不存在,則須要進行建立,不然探測失敗
        port: 81
      initialDelaySeconds: 10
      periodSeconds: 5
---     
apiVersion: v1       
kind: Service
metadata:
  name: web-svc
spec:
  selector:
    name: web2
  ports:
  - protocol: TCP
    port: 81             
    targetPort: 81
//運行pod:
[root@sqm-master yaml]# kubectl apply -f  http-readiness.yaml 
pod/web2 created
service/web-svc created
//查看pod的狀態:
[root@sqm-master yaml]# kubectl  get pod -o wide
NAME        READY   STATUS      RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
readiness   0/1     Completed   0          37m     10.244.2.12   node02   <none>           <none>
web         1/1     Running     0          50m     10.244.1.11   node01   <none>           <none>
web2        0/1     Running     0          2m31s   10.244.1.14   node01   <none>           <none>

k8s探測機制之pod健康檢查
查看pod的Events信息,經過探測,能夠知道pod是不健康的,且http訪問失敗。
它並不會重啓,而是直接將pod設置爲不可用的狀態。

健康檢測在滾動更新過程當中的應用:

首先咱們經過explain工具來查看更新使用的字段:

[root@sqm-master ~]#  kubectl  explain deploy.spec.strategy.rollingUpdate

k8s探測機制之pod健康檢查
能夠看到在滾動更新的過程當中有兩個參數可用:

  • maxSurge:此參數控制滾動更新過程當中,副本總數超過預期pod數量的上限。能夠是百分比,也能夠是具體的值,默認爲1。若是該值設置爲3,則在更新的過程當中,一來則會直接增長三個pod進行更新(固然還要進行探測機制的驗證是否更新成功)。該值設置得越大、升級速度越快,但會消耗更多的系統資源。
  • maxUnavailable:此參數控制滾動更新過程當中,不可用的pod的數量,注意是在原pod數量中進行減小,不會計算maxSurge值的範圍。若當該值爲3時,若是探測失敗則在升級的過程當中會有3個pod不可用。該值設置得越大、升級速度越快,但會消耗更多的系統資源。

maxSurge和maxUnavailable的適用場景:
1,若是您但願在保證系統可用性和穩定性的前提下儘量快地進行升級,能夠將 maxUnavailable 設置爲 0,同時爲 maxSurge 賦予一個較大值。
2,若是系統資源比較緊張,pod 負載又比較低,爲了加快升級速度,能夠將 maxSurge 設置爲 0,同時爲 maxUnavailable 賦予一個較大值。須要注意的是,若是 maxSurge 爲 0maxUnavailable 爲 DESIRED,可能形成整個服務的不可用,此時 RollingUpdate 將退化成停機發布
1)首先咱們建立一個deployment資源對象:

[root@sqm-master ~]# vim app.v1.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-web
spec:
  replicas: 10              #定義副本數量爲10個
  template:
    metadata:
      labels:
        name: my-web
    spec:
       containers:
        - name: my-web
          image: nginx
          args:
          - /bin/sh
          - -c
          - touch /usr/share/nginx/html/test.html; sleep 300000; #建立文件,使其在探測時保持pod爲健康狀態
          ports:
          - containerPort: 80
          readinessProbe:       #使用readiness機制
            exec:
              command:
              - cat
              - /usr/share/nginx/html/test.html
            initialDelaySeconds: 10
            periodSeconds: 10
//運行該pod後,查看pod數量(10個):
[root@sqm-master yaml]# kubectl  get pod -o wide
NAME                      READY   STATUS      RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
my-web-7bbd55db99-2g6tp   1/1     Running     0          2m11s   10.244.2.44   node02   <none>           <none>
my-web-7bbd55db99-2jdbz   1/1     Running     0          118s    10.244.2.45   node02   <none>           <none>
my-web-7bbd55db99-5mhcv   1/1     Running     0          2m53s   10.244.1.40   node01   <none>           <none>
my-web-7bbd55db99-77b4v   1/1     Running     0          2m      10.244.1.44   node01   <none>           <none>
my-web-7bbd55db99-h888n   1/1     Running     0          2m53s   10.244.2.41   node02   <none>           <none>
my-web-7bbd55db99-j5tgz   1/1     Running     0          2m38s   10.244.2.42   node02   <none>           <none>
my-web-7bbd55db99-kjgm2   1/1     Running     0          2m25s   10.244.1.42   node01   <none>           <none>
my-web-7bbd55db99-kkmh2   1/1     Running     0          2m38s   10.244.1.41   node01   <none>           <none>
my-web-7bbd55db99-lr896   1/1     Running     0          2m13s   10.244.1.43   node01   <none>           <none>
my-web-7bbd55db99-rpd8v   1/1     Running     0          2m23s   10.244.2.43   node02   <none>

探測成功,10個副本所有運行。

2)第一次更新:
更新nginx鏡像版本,且設置滾動更新策略:

[root@sqm-master yaml]# vim app.v1.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-web
spec: 
  strategy:       #設置滾動更新策略,經過該字段下的rollingUpdate的子屬性來設置
    rollingUpdate:
      maxSurge: 3                 #指定在滾動更新過程當中最多可建立3個額外的 pod
      maxUnavailable: 3     #- 指定在滾動更新過程當中最多容許3 pod 不可用
  replicas: 10              
  template:
    metadata:
      labels:
        name: my-web
    spec:
       containers:
        - name: my-web
          image: 172.16.1.30:5000/nginx:v2.0    #更新的鏡像爲私有倉庫中的鏡像nginx:v2.0
          args:
          - /bin/sh
          - -c
          - touch /usr/share/nginx/html/test.html; sleep 300000; 
          ports:
          - containerPort: 80
          readinessProbe:       
            exec:
              command:
              - cat
              - /usr/share/nginx/html/test.html
            initialDelaySeconds: 10
            periodSeconds: 10
//執行yaml文件後,查看pod數量:
[root@sqm-master yaml]# kubectl  get pod -o wide
NAME                      READY   STATUS      RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
my-web-7db8b88b94-468zv   1/1     Running     0          3m38s   10.244.2.57   node02   <none>           <none>
my-web-7db8b88b94-bvszs   1/1     Running     0          3m24s   10.244.1.60   node01   <none>           <none>
my-web-7db8b88b94-c4xvv   1/1     Running     0          3m38s   10.244.2.55   node02   <none>           <none>
my-web-7db8b88b94-d5fvc   1/1     Running     0          3m38s   10.244.1.58   node01   <none>           <none>
my-web-7db8b88b94-lw6nh   1/1     Running     0          3m21s   10.244.2.59   node02   <none>           <none>
my-web-7db8b88b94-m9gbh   1/1     Running     0          3m38s   10.244.1.57   node01   <none>           <none>
my-web-7db8b88b94-q5dqc   1/1     Running     0          3m38s   10.244.1.59   node01   <none>           <none>
my-web-7db8b88b94-tsbmm   1/1     Running     0          3m38s   10.244.2.56   node02   <none>           <none>
my-web-7db8b88b94-v5q2s   1/1     Running     0          3m21s   10.244.1.61   node01   <none>           <none>
my-web-7db8b88b94-wlgwb   1/1     Running     0          3m25s   10.244.2.58   node02   <none>           <none>
//查看pod的版本信息:
[root@sqm-master yaml]# kubectl  get deployments. -o wide
NAME     READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                        SELECTOR
my-web   10/10   10           10          49m   my-web       172.16.1.30:5000/nginx:v2.0   name=my-web

探測成功,10個pod版本所有更新成功。

3)第二次更新:
將鏡像版本更新爲3.0版本,且設置滾動更新策略。(探測失敗)
pod的配置文件以下:

[root@sqm-master yaml]# vim app.v1.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-web
spec:
  strategy:
    rollingUpdate:
      maxSurge: 3                  #定義更新策略,數量依然都是保持3個
      maxUnavailable: 3
  replicas: 10                       #pod數量依然是10個
  template:
    metadata:
      labels:
        name: my-web
    spec:
       containers:
        - name: my-web
          image: 172.16.1.30:5000/nginx:v3.0   #測試鏡像版本更新爲3.0
          args:
          - /bin/sh
          - -c
          - sleep 300000;        #不在建立指定文件,使其探測失敗
          ports:
          - containerPort: 80
          readinessProbe:       
            exec:
              command:
              - cat
              - /usr/share/nginx/html/test.html
            initialDelaySeconds: 10
            periodSeconds: 5
//從新運行pod配置文件:
[root@sqm-master yaml]# kubectl apply -f  app.v1.yaml 
deployment.extensions/my-web configured
//查看pod更新後的數量:
[root@sqm-master yaml]# kubectl  get pod  -o wide
NAME                      READY   STATUS      RESTARTS   AGE    IP            NODE     NOMINATED NODE   READINESS GATES
my-web-7db8b88b94-468zv   1/1     Running     0          12m    10.244.2.57   node02   <none>           <none>
my-web-7db8b88b94-c4xvv   1/1     Running     0          12m    10.244.2.55   node02   <none>           <none>
my-web-7db8b88b94-d5fvc   1/1     Running     0          12m    10.244.1.58   node01   <none>           <none>
my-web-7db8b88b94-m9gbh   1/1     Running     0          12m    10.244.1.57   node01   <none>           <none>
my-web-7db8b88b94-q5dqc   1/1     Running     0          12m    10.244.1.59   node01   <none>           <none>
my-web-7db8b88b94-tsbmm   1/1     Running     0          12m    10.244.2.56   node02   <none>           <none>
my-web-7db8b88b94-wlgwb   1/1     Running     0          12m    10.244.2.58   node02   <none>           <none>
my-web-849cc47979-2g59w   0/1     Running     0          3m9s   10.244.1.63   node01   <none>           <none>
my-web-849cc47979-2lkb6   0/1     Running     0          3m9s   10.244.1.64   node01   <none>           <none>
my-web-849cc47979-762vb   0/1     Running     0          3m9s   10.244.1.62   node01   <none>           <none>
my-web-849cc47979-dv7x8   0/1     Running     0          3m9s   10.244.2.61   node02   <none>           <none>
my-web-849cc47979-j6nwz   0/1     Running     0          3m9s   10.244.2.60   node02   <none>           <none>
my-web-849cc47979-v5h7h   0/1     Running     0          3m9s   10.244.2.62   node02   <none>           <none>

咱們能夠看到當前pod的總數量爲13個,(包括maxSurge增長額外的數量)由於探測失敗,則設置爲將3個pod(包括額外的pod)爲不可用的狀態,但還剩下7個pod可用( 由於maxUnavailable設置爲3個),但注意:這7個pod的版本並無更新成功,仍是上一個的版本。

//查看pod的更新後的版本信息:
[root@sqm-master yaml]# kubectl  get deployments. -o wide
NAME     READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                        SELECTOR
my-web   7/10    6            7           58m   my-web       172.16.1.30:5000/nginx:v3.0   name=my-web

參數解釋:
READY :表示用戶的指望值
UP-TO-DATE:表示已更新的
AVAILABLE:表示可用的

咱們能夠發現已更新的鏡像版本數量爲6個(包括額外的3個pod),可是爲不可用的狀態,可是確保可用的的pod數量爲7個,可是版本並無更新。

總結:
描述在滾動更新過程當中,探測機制有什麼做用?

若是在公司中須要對某個應用中的pod進行更新操做,若是沒有探測機制,不管該pod是否是當你已經作好更新工做準備要進行更新的,它都會將該應用中全部的pod進行更新,這樣會形成嚴重的後果,雖然更新後你發現pod的狀態是正常的,爲了達到controller manager的指望值,READY的值依然是1/1, 可是pod已是從新生成的pod了,表示pod內的數據將會所有丟失。
若是加上探測機制的話,會探測容器內你指定的文件或其餘應用是否存在,若是達到你指定的條件,則探測成功,則會對你的pod進行更新,若是探測失敗則會設置pod(容器)爲不可用,雖然探測失敗的容器不可用了,但至少該模塊中還有其餘以前版本的pod可用,確保該公司該服務的正常運行。可見探測機制是多麼的重要啊。

———————— 本文至此結束,感謝閱讀 ————————

相關文章
相關標籤/搜索