Kubernetes Pod鈎子


1、Pod容器鈎子最終目的

之前在生產環境中使用dubbo框架,由於服務更新的過程中,容器直接被停止了,部分請求仍會被分發到終止的容器,導致有用戶會訪問服務出現500錯誤,這部分錯誤請求數據占用的比較少,因為Pod是滾動一對一更新。由於這個問題出現了,考慮使用優雅的終止方式,將錯誤請求將至到最低,直至滾動更新完全不會影響到用戶。

簡單分析一下優雅的停止Pod

微服務中,網關會把流量分配給每個Pod節點,如:我們線上更新Pod的時候

1、如果我們直接把Pod給殺死,那這部分流量就無法得到正確的處理,會影響到部分用戶訪問,一般來說網關或者注冊中心會將我們的服務保持一個心跳,過了心跳超時后就會自動摘除我們的服務,但是有一個問題就是超時時間可能是10s、30s、甚至是60s,雖然不會大規模的影響我們業務系統,但是一定會對用戶產生輕微的抖動。

2、如果我們在停止服務前執行一條命令,通知網關或注冊中心這台Pod,即服務進行下線,那么注冊中心就會標記這個Pod/服務已經下線,不進行流量轉發,用戶也就不會有任何的影響,這就是優雅停止,將滾動更新的影響最小化。

2、何為Pod容器鈎子

Kubernetes最小調度單位為Pod,它為Pod中的容器提供了生命周期鈎子,鈎子能夠使得容器感知其生命周期內的所有事件,並且當相應的生命周期的鈎子被調用時運行執行的代碼,而Pod 鈎子是由Kubelet發起的。

容器鈎子兩類觸發點:

  • PostStart:容器創建后
  • PreStop:容器終止前

PostStart
這個鈎子在容器創建后立即執行。
但是,並不能保證鈎子將在容器ENTRYPOINT之前運行。
沒有參數傳遞給處理程序。

容器ENTRYPOINT和鈎子執行是異步操作。
如果鈎子花費太長時間以至於容器不能運行或者掛起, 容器將不能達到running狀態

PreStop
這個鈎子在容器終止之前立即被調用。
它是阻塞的,意味着它是同步的, 所以它必須在刪除容器的調用發出之前完成

如果鈎子在執行期間掛起, Pod階段將停留在running狀態並且永不會達到failed狀態。

如果PostStart或者PreStop鈎子失敗, 容器將會被kill。
用戶應該使他們的鈎子處理程序盡可能的輕量。

3、基於PostStart演示

如果PostStart或者PreStop鈎子失敗,它會殺死容器。所以我們應該讓鈎子函數盡可能的輕量。當然有些情況下,長時間運行命令是合理的,比如在停止容器之前預先保留狀態。

1.我們echo一段話追加到/tmp/message,在Pod啟動前操作

cat >>hook_test.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
  name: hook-demo1
spec:
  containers:
  - name: hook-demo1
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo 1 > /tmp/message"]
EOF

2.應用hook_test.yaml

$ kubectl apply -f  hook_test.yaml

3.可以通過下面查看結果

$ kubectl get pods | grep hook-demo1
hook-demo1                 1/1     Running   0          49s

$ kubectl exec -it hook-demo1 /bin/bash
root@hook-demo1:/# cat /tmp/message
1

4、基於PreStop演示

下面示例中,定義一個Nginx Pod,設置了PreStop鈎子函數,即在容器退出之前,優雅的關閉Nginx。

cat >>hook_test.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
  name: hook-demo2
spec:
  containers:
  - name: hook-demo2
    image: nginx
    lifecycle:
      preStop:
        exec:
          command: ["/usr/sbin/nginx","-s","quit"]
EOF

5、優雅停止Java應用

我們都知道java應用的啟動和停止都需要時間,為了更加優雅的停止,可以通過pidof獲取到java進程ID,循環通過kill命令往PID發送SIGTERM信號。

    lifecycle:
      preStop:
        exec:
          command: ["/bin/bash","-c","PID=`pidof java` && kill -SIGTERM $PID && while ps -p $PID > /dev/null;do sleep 1; done;"]


免責聲明!

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



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