Kubernetes 0-1 使用preStop優雅終止Pod


Kubernetes允許Pod終止之前,執行自定義邏輯。

字段定義

字段定義:pod.spec.containers.lifecycle.preStop

$ kubectl explain pod.spec.containers.lifecycle.preStop
KIND:     Pod
VERSION:  v1

RESOURCE: preStop <Object>

DESCRIPTION:
     PreStop is called immediately before a container is terminated due to an
     API request or management event such as liveness/startup probe failure,
     preemption, resource contention, etc. The handler is not called if the
     container crashes or exits. The reason for termination is passed to the
     handler. The Pod's termination grace period countdown begins before the
     PreStop hooked is executed. Regardless of the outcome of the handler, the
     container will eventually terminate within the Pod's termination grace
     period. Other management of the container blocks until the hook completes
     or until the termination grace period is reached. More info:
     https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks

     Handler defines a specific action that should be taken

FIELDS:
   exec <Object>
     One and only one of the following should be specified. Exec specifies the
     action to take.

   httpGet      <Object>
     HTTPGet specifies the http request to perform.

   tcpSocket    <Object>
     TCPSocket specifies an action involving a TCP port. TCP hooks not yet
     supported

有三種preStop方式:

  • exec
  • httpGet
  • tcpSocket

示例

使用最簡單的exec作示例,詳細查看一下exec下需要定義的字段:

$ kubectl explain pod.spec.containers.lifecycle.preStop.exec
KIND:     Pod
VERSION:  v1

RESOURCE: exec <Object>

DESCRIPTION:
...
FIELDS:
   command      <[]string>
     Command is the command line to execute inside the container, the working
     directory for the command is root ('/') in the container's filesystem. The
     command is simply exec'd, it is not run inside a shell, so traditional
     shell instructions ('|', etc) won't work. To use a shell, you need to
     explicitly call out to that shell. Exit status of 0 is treated as
     live/healthy and non-zero is unhealthy.

接下來按照字段釋義,直接定義一個Pod:

$ kubectl apply -f pod.yaml
# pod.yaml文件內容:
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
    - name: busybox
      image: busybox
      command: ["/bin/sh", "-c", "sleep 10m"]
      lifecycle:
        preStop:
          exec:
            command:
              [
                "/bin/sh",
                "-c",
                "echo this pod is stopping. > /stop.log && sleep 10s",
              ]

刪除pod:

$ kubectl delete pod busybox

在新終端窗口(因為刪除pod會占用終端窗口)獲取pod內文件內容,需要在pod完全刪除之前(10s內,也可以將該值設置稍長一點):

$ kubectl exec busybox -c busybox -- cat /stop.log
# 可以得到日志內容
this pod is stopping.

這說明,preStop確實生效了。

使用場景

  • 你的請求已經到達了當前Pod,硬終止會導致請求失敗,我們希望已經到達了當前Pod的請求處理完成再將其停止掉,盡可能避免請求失敗;
  • Pod已經本身已經注冊到了服務中心,我們希望在Pod停止之前,主動向服務注冊中心通知下線;

結束語

與preStop相對應,有一個postStart的概念,在容器創建成功后執行,可用於初始化資源,准備環境等;

如果preStop與postStart執行失敗,將會殺死容器。所以作為鈎子函數,應該盡量保證它們是輕量的;

Pod的終止過程:

刪除Pod => Pod被標記為Terminating狀態 => Service移除該Pod的endpoint => kubelet甄別Terminating狀態的pod,執行pod的preStop鈎子 => 如果執行preStop超時(grace period) ,kubelet發送SIGTERM並等待2秒 => ...

gzh


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM