Kubernetes-Pod介紹(二)-生命周期

前言

本篇是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
image.png
Pod phase

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

image.png
image.png
image.png
image.png
Pod conditions

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

image.png
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"
      - //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
image.png
  1. 進入容器目錄驗證index.html是否為init container生成;
kubectl exec -it nginx /bin/bash
image.png
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"
      - //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
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
image.png
Pod重啟策略

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

img
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秒。

結束

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

Tags: