前言

本篇是Kubernetes第五篇,大家一定要把環境搭建起來,看是解決不了問題的,必須實戰。

Kubernetes系列文章:
  1. Kubernetes介紹
  2. Kubernetes環境搭建
  3. Kubernetes-kubectl介紹
  4. Kubernetes-Pod介紹(-)

Pod生命週期

Pod物件自從其建立開始至其終止退出的時間範圍稱為其生命週期。在這段時間中,Pod會處於多種不同的狀態,並執行一些操作;其中,建立主容器(main container)為必需的操作,其他可選的操作還包括執行初始化容器(init container)、容器啟動後鉤子(post start hook)、容器的存活性探測(liveness probe)、就緒性探測(readiness probe)以及容器終止前鉤子(pre stop hook)等,這些操作是否執行則取決於Pod的定義。如下圖所示:


image.png
Pod phase

Pod phase代表其所處生命週期的階段。Pod phase 並不是用來代表其容器的狀態,也不是一個嚴格的狀態機。定義在Pod的PodStatus物件的phase欄位中,phase 的可能情況有:


image.png

image.png
Pod conditions

Pod有一個PodStatus物件,PodStatus包含一個 PodCondition 陣列, 用來描述Pod是否達到某些指定的條件。 PodCondition包含以下欄位:


image.png
Pod 生命週期中的重要行為

除了建立應用容器之外,使用者還可以為 Pod 物件定義其生命週期中的多種行為,如初始化容器、存活性探測及就緒性探測等。

init container

初始化容器(init container)即應用程式的主容器啟動之前要執行的容器,常用於為主容器執行一些預置操作,它們具有兩種典型特徵:

  1. 初始化容器必須執行完成直至結束,若某初始化容器執行失敗,那麼 Kubernetes 需要重啟它直到成功完成;
  2. 每個初始化容器都必須按定義的順序序列執行;
初始化容器可以做什麼

有不少場景都需要在應用容器啟動之前進行初始化操作,例如,基於環境變數或配置模板為應用程式生成配置檔案、從配置中心獲取配置等。初始化容器的典型應用場景大概有以下幾種:

  1. 用於執行特定的檢測程式,出於安全等原因,這些程式不方便包含再主容器映象中;
  2. 為容器映象的構建和部署人員提供了分離、獨立工作的途徑,使得他們不必協同起來製作單個映象檔案;
  3. 初始化容器和主容器處於不同的檔案系統檢視中,因此可以分別安全地使用敏感資料,例如 Secrets 資源;
  4. 初始化容器要先於應用容器序列啟動並執行完成,因此可用於延後應用容器的啟動直至其依賴的條件得到滿足;

注意點: 初始化容器不支援就緒型探測器(Readiness Probe),因為它們必須在 Pod 就緒之前執行完成,而就緒型探測器是在之後才開始的。

實戰
  1. 刪除Pod,這裡先清理之前實現的Demo,這一步可忽略;
kubectl delete -f nginx-deployment.yaml
  1. 新建nginx-init-container.yaml檔案,在啟動Nginx之前,通過初始化容器busybox為Nginx建立一個index.html,init container與Nginx容器共享Volume,以保證Nginx訪問的是init container設定的index.html頁面;
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  #通過wget下載index.html
  initContainers:
    - name: install
      image: busybox
      command:
      - wget
      - "-O"
      - "/workdir/index.html"
      - http://www.baidu.com
      volumeMounts:
      - name: workdir
        mountPath: /workdir
  containers:
  - name: nginx
    image: nginx
    resources:
      limits:
        memory: "128Mi"
        cpu: "128m"
    ports:
    - containerPort: 80
    volumeMounts:
    - name: workdir
      mountPath: /usr/share/nginx/html
  volumes:
  - name: workdir
    emptyDir: {}
  1. 建立Pod資源;
kubectl apply -f nginx-init-container.yaml
  1. 檢視Pod執行事件;
kubectl describe pod nginx

image.png
  1. 進入容器目錄驗證index.html是否為init container生成;
kubectl exec -it nginx /bin/bash

image.png
生命週期鉤子函式

生命週期鉤子函式(lifecycle hook)是一些框架中常用的手段,它實現了程式執行週期中的關鍵時刻的可見性,並賦予使用者為此採取某種行動的能力。類似地,容器生命週期鉤子使它能夠感知自身生命週期管理中的事件,並在相應的時刻到來時執行由使用者指定的處理程式程式碼。Kubernetes 為容器提供了兩種生命週期鉤子:

  1. postStart:在容器建立完成之後立即執行的鉤子處理器(handler),不過 Kubernetes 無法確保它一定會於Docker中的 ENTRYPOINT 之前執行;
  2. preStop:於容器終止操作之前立即執行的鉤子處理器,它以同步的方式呼叫,因此在其完成之前會阻塞刪除容器的操作的呼叫;
鉤子函式實現方式

容器可以通過實現和註冊該回調的處理程式來訪問該回調。 針對容器,有兩種型別的回撥處理程式可供實現:

  1. Exec: 在鉤子時間觸發時直接在當前容器中執行由使用者定義的命令。 命令所消耗的資源計入容器的資源消耗;
  2. HTTP: 在當前容器中向某URL發起HTTP請求;
實戰
  1. 刪除Pod;
kubectl delete -f nginx-init-container.yaml
  1. 編輯nginx-init-container.yaml,增加postStart和preStop鉤子函式;
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  initContainers:
    - name: install
      image: busybox
      command:
      - wget
      - "-O"
      - "/workdir/index.html"
      - http://www.baidu.com
      volumeMounts:
      - name: workdir
        mountPath: /workdir
  containers:
  - name: nginx
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo postStart handler > /usr/share/message"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "nginx -s quit; while killall -0 nginx; do sleep 1; done"]
    resources:
      limits:
        memory: "128Mi"
        cpu: "128m"
    ports:
      - containerPort: 80
    volumeMounts:
      - name: workdir
        mountPath: /usr/share/nginx/html
  volumes:
  - name: workdir
    emptyDir: {}
  1. 建立Pod資源;
kubectl apply -f nginx-init-container.yaml
  1. 進入容器目錄驗證/usr/share/message目錄是否輸出postStart handler;
kubectl exec -it nginx -- /bin/bash

image.png
健康檢查

Kubernetes對Pod的健康狀態通過三類探針來檢查,其中最主要的探針是LivenessProbe和ReadinessProbe,kubelet會定期執行這兩類探針來診斷容器的檢查狀況,介紹如下:

  1. LivenessProbe: 用於判斷容器是否處於Running狀態,如果LivenessProbe探針檢測到容器處於不健康狀態,則kubelet回殺掉該容器的程序,並根據容器的重啟策略做相應的處理,如果一個容器不包含LivenessProbe探針,那麼kubelet會認為該容器的LivenessProbe探針一直返回值為true;
  2. ReadinessProbe: 用於判斷容器的服務是否處於Ready狀態,達到Ready狀態的Pod才可以接收請求。對於被Service管理的Pod,如果Ready狀態變為false, 則 Service是不會負載到該Pod上的。ReadinessProbe是定期觸發的,存在Pod整個生命週期中;
  3. StartupProbe: 用於容器啟動的健康檢查,用於一些啟動緩慢的業務,避免業務長時間啟動而被前面的探針kill掉;
探針的探測方式

容器探測(container probe)是Pod物件生命週期中的一項重要的日常任務,它是由kubelet對容器週期性執行的健康狀態診斷,診斷操作由於容器的處理器(handler)進行定義。Kubernetes 支援三種處理器用於 Pod 探測:

  1. ExecAction: 在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功;
  2. TCPSocketAction: 對指定埠上的容器的 IP 地址進行 TCP 檢查。如果埠開啟,則診斷被認為是成功的;
  3. HTTPGetAction: 對指定的埠和路徑上的容器的 IP 地址執行 HTTP Get 請求。如果響應的狀態碼大於等於200 且小於 400,則診斷被認為是成功的;
探針探測結果

每類探針都有三種結果:

  1. Success:容器通過檢查;
  2. Failure:容器未通過檢查;
  3. Unknown:未能執行檢查,因此不採取任何措施;
實戰
  1. 刪除Pod;
kubectl delete -f nginx-init-container.yaml
  1. 新建lifecycle-pod.yaml,繼續使用nginx容器,增加postStart和preStop鉤子函式,定義LivenessProbe和ReadinessProbe探針,驗證主容器的各項事件的執行流程;
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo postStart handler >> /usr/share/message"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo preStop handler >> /usr/share/message"]
    resources:
      limits:
        memory: "128Mi"
        cpu: "128m"
    ports:
      - containerPort: 80
    livenessProbe:
      exec:
        command: ["/bin/sh", "-c", "echo livenessProbe >> /usr/share/message"]
      initialDelaySeconds: 5
      periodSeconds: 5
    readinessProbe:
      exec:
        command: ["/bin/sh", "-c", "echo readinessProbe >> /usr/share/message"]
      initialDelaySeconds: 5
      periodSeconds: 5
  1. 建立Pod資源;
kubectl apply -f lifecycle-pod.yaml
  1. 進入容器目錄驗證/usr/share/message的輸出,到這裡我們就驗證了整個生命週期對的事件;
kubectl exec -it nginx -- /bin/bash

image.png
Pod重啟策略

容器程序發生崩潰或容器申請超出限制的資源等原因都可能會導致 Pod 物件的終止,此時是否應該重建該 Pod 物件則取決於其重啟策略restartPolicy屬性的定義。


img

Pod重啟策略與控制的方式息息相關,可以管理Pod的控制器有Replication Controller,Job,DaemonSet,及kubelet(靜態Pod), 對於不同的控制器有注意以下問題:

  1. Replication Controller和DaemonSet:必須設定為Always,需要保證該容器持續執行;
  2. Job:設定為OnFailure或Never,確保容器執行完後不再重啟;
  3. kubelet:在Pod失效的時候重啟它,不論RestartPolicy設定為什麼值,並且不會對Pod進行健康檢查;

此外還有一個需要注意的點就是重啟的容器的時間,kubelet重啟失效容器的時間間隔以指數方式增長,最長延遲時間為300秒。

結束

歡迎大家點點關注,點點贊!