k8s中pod優雅關閉進程


前言:

在 Kubernetes 中,Pod 停止時 kubelet 會先給容器中的主進程發 SIGTERM 信號來通知進程進行 shutdown 以實現優雅停止,如果超時進程還未完全停止則會使用 SIGKILL 來強行終止。

容器終止流程:

1、Pod 被刪除,狀態置為 Terminating。
2、kube-proxy 更新轉發規則,將 Pod 從 service 的 endpoint 列表中摘除掉,新的流量不再轉發到該 Pod。
3、如果 Pod 配置了 preStop Hook ,將會執行。
4、kubelet 對 Pod 中各個 container 發送 SIGTERM 信號以通知容器進程開始優雅停止。
5、等待容器進程完全停止,如果在 terminationGracePeriodSeconds 內 (默認 30s) 還未完全停止,就發送 SIGKILL 信號強制殺死進程。
6、所有容器進程終止,清理 Pod 資源。

優雅退出,業務側需要做的任務是處理SIGTERM信號:

要實現優雅終止,務必在業務代碼里面處理下 SIGTERM 信號

 

注意事項:

要實現優雅退出,還需要注意的是如果業務容器的進程,是使用shell腳本啟動的,需要進行特殊處理,業務容器才能接收到SIGTERM信號。建議盡量不使用shell腳本啟動,如果確實需要,則需要特殊處理。

 

shell啟動為什么接收不到SIGTERM信號呢?

1、容器主進程是 shell,業務進程是在 shell 中啟動的,成為了 shell 進程的子進程。
2、shell 進程默認不會處理 SIGTERM 信號,自己不會退出,也不會將信號傳遞給子進程,導致業務進程不會觸發停止邏輯。
3、當等到 K8S 優雅停止超時時間 (terminationGracePeriodSeconds,默認 30s),發送 SIGKILL 強制殺死 shell 及其子進程。

 

解決方案:

1、如果shell啟動的是單進程,可以在shell 中啟動二進制的命令前面加一個exec,這個命令可以讓二進制啟動的進程代替shell成為主進程,從而業務進程可以接收到SIGTERM

#! /bin/bash

exec /bin/myapp # 腳本中執行二進制

 

2、shell啟動的是多個進程,則不能用exec來解決了,因為exec只能讓一個進程成為主進程。可以使用trap或init系統實現多進程啟動傳遞SIGTERM信號。

trap:

#! /bin/bash

/bin/myapp & pid1="$!" # 啟動第一個業務進程並記錄 pid
echo "app started with pid $pid1"

/bin/myclient & pid2="$!" # 啟動第二個業務進程並記錄 pid
echo "myclient started with pid $pid2"

handle_sigterm() {
  echo "[INFO] Received SIGTERM"
  kill -SIGTERM $pid1 $pid2 # 傳遞 SIGTERM 給業務進程
  wait $pid1 $pid2 # 等待所有業務進程完全終止
}
trap handle_sigterm SIGTERM # 捕獲 SIGTERM 信號並回調 handle_sigterm 函數

wait # 等待回調執行完,主進程再退出

 

init:

dumb-init 和 tini 都可以作為 init 進程,作為主進程 (PID 1) 在容器中啟動,然后它再運行 shell 來執行我們指定的腳本 (shell 作為子進程),shell 中啟動的業務進程也成為它的子進程,當它收到信號時會將其傳遞給所有的子進程,從而也能完美解決 SHELL 無法傳遞信號問題,並且還有回收僵屍進程的能力

制作包含init系統的業務鏡像:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y dumb-init
ADD start.sh /
ADD myapp /bin/myapp
ADD myclient /bin/myclient
ENTRYPOINT ["dumb-init", "--"]
CMD ["/start.sh"]

start.sh:

#! /bin/bash
/bin/app1 &
/bin/app2 &
wait

 

 

業務代碼不方便處理或沒有辦法處理SIGTERM信號時,進程優雅退出的方法:

1、preStop-webhook

        lifecycle:
          preStop:
            exec:
              command:
              - sleep
              - 5s

 

2、調整優雅終止時間,terminationGracePeriodSeconds 默認是30s。自己視情況而定

 


免責聲明!

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



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