<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          K8s Pod優(yōu)雅關(guān)閉,沒你想象的那么簡(jiǎn)單!

          共 2376字,需瀏覽 5分鐘

           ·

          2021-09-27 19:21

          更新部署服務(wù)時(shí),Pod 會(huì)終止,新 Pod 上位。如果在這個(gè)部署過程中老 Pod 有一個(gè)很長的操作,我們想在這個(gè)操作成功完成后殺死這個(gè) pod(優(yōu)雅關(guān)閉),如果無法做到的話,被殺死的 pod 可能會(huì)丟失一定的流量,或者外界無法感知到該 Pod 被殺死。特別是,如果我們有一個(gè)接收大量流量的 API,錯(cuò)誤率在部署過程中會(huì)顯著增加。

          其實(shí)這也挺簡(jiǎn)單的,添加一個(gè)優(yōu)雅關(guān)閉就行了,之前寫過優(yōu)雅關(guān)閉的最佳實(shí)踐K8S Pod流量的優(yōu)雅無損切換實(shí)踐,后來在發(fā)現(xiàn)還是不夠優(yōu)雅........

          當(dāng) Kubernetes 殺死一個(gè) pod 時(shí),會(huì)發(fā)生以下 5 個(gè)步驟:

          1、 Pod 切換到終止?fàn)顟B(tài)并停止接收任何新流量,容器仍在 pod 內(nèi)運(yùn)行。

          2、 preStop 鉤子是一個(gè)特殊的命令或 HTTP 請(qǐng)求被執(zhí)行,并被發(fā)送到 pod 內(nèi)的容器。

          3、 SIGTERM 信號(hào)被發(fā)送到 pod,容器意識(shí)到它將很快關(guān)閉。

          4、 Kubernetes 等待寬限期 (terminationGracePeriodSeconds)。此等待與 preStop hook 和 SIGTERM 信號(hào)執(zhí)行并行(默認(rèn) 30 秒)。因此,Kubernetes 不會(huì)等待這些完成。如果這段時(shí)間結(jié)束,則直接進(jìn)入下一步。正確設(shè)置寬限期的值非常重要。

          5、向 pod 發(fā)送 SIGKILL 信號(hào),然后移除 pod。如果容器在寬限期后仍在運(yùn)行,則 Pod 被 SIGKILL 強(qiáng)行移除,終止完成。

          總結(jié)下大致分為兩步,第一步定義 preStop,一般情況下可以休眠 30s,用于處理殘余流量;第二步發(fā)送 SIGTERM 信號(hào),服務(wù)收到信號(hào)后進(jìn)行服務(wù)的收尾工作處理。比如:關(guān)閉連接、通知第三方注冊(cè)中心服務(wù)關(guān)閉.....

          有同學(xué)疑問,既然 pod 已經(jīng)終止了,同時(shí) K8s 的網(wǎng)絡(luò) endpoint 也摘除了,為什么還會(huì)進(jìn)來流量呢?

          因?yàn)檫@個(gè)網(wǎng)絡(luò)接口的摘除是異步的,這也是為什么會(huì)首先執(zhí)行 preStop,然后發(fā)送 SIGTERM 信號(hào)的原因所在。

          這樣做基本上能夠保證流量無損,但是這樣做的前提是服務(wù)能夠收到 SIGTERM 信號(hào)。

          理想情況下,一個(gè)容器只有一個(gè)進(jìn)程,但是在現(xiàn)實(shí)場(chǎng)景下很難做到,比如,我會(huì)用一個(gè) shell 腳本去管理和啟動(dòng) Java 進(jìn)程,除了 shell 腳本主進(jìn)程之外,還要運(yùn)行監(jiān)控、日志收集等子進(jìn)程,這樣一個(gè)容器里面就運(yùn)行了多個(gè)進(jìn)程。

          系統(tǒng)底層默認(rèn)會(huì)向主進(jìn)程發(fā)送 SIGTERM 信號(hào),而對(duì)剩余子進(jìn)程發(fā)送 SIGKILL 信號(hào)。系統(tǒng)這樣做的大概原因是因?yàn)榇蠹以谠O(shè)計(jì)主進(jìn)程腳本的時(shí)候都不會(huì)進(jìn)行信號(hào)的捕獲和傳遞,這會(huì)導(dǎo)致容器關(guān)閉時(shí),多個(gè)子進(jìn)程無法被正常終止,所以系統(tǒng)使用 SIGKILL 這個(gè)不可屏蔽信號(hào),而是為了能夠在沒有任何前提條件的情況下,能夠把容器中所有的進(jìn)程關(guān)掉。

          具體可以使用strace -p pid去跟蹤服務(wù)調(diào)用情況。

          也就是說如果主進(jìn)程自身不是服務(wù)本身,可能會(huì)導(dǎo)致是被強(qiáng)制Kill的,解決的方法也很簡(jiǎn)單,也就是在主進(jìn)程中對(duì)收到的信號(hào)做個(gè)轉(zhuǎn)發(fā),發(fā)送到容器中的其他子進(jìn)程,這樣容器中的所有進(jìn)程在停止時(shí),都會(huì)收到 SIGTERM,而不是 SIGKILL 信號(hào)了。

          具體如何實(shí)現(xiàn)呢?比如下面的trap信號(hào),就是一種實(shí)現(xiàn)方式,這里有一篇最佳實(shí)踐http://veithen.io/2014/11/16/sigterm-propagation.html。

          #startup.sh
          ...
          trap 'kill -TERM $child' TERM
          nohup java $JAVA_OPTS -jar ./xxx.jar --server.port=8080 &

          child=$!
          wait $child
          wait $child

          當(dāng)然很多成熟的框架都實(shí)現(xiàn)了優(yōu)雅關(guān)閉功能,比如spring的CustomHealthCheck類擴(kuò)展了AbstractHealthIndicator類,并允許我們通過覆蓋doHealthCheck()方法來構(gòu)建自定義健康檢查結(jié)構(gòu)。根據(jù)我們從HealthService收到的標(biāo)志,我們將系統(tǒng)的健康狀態(tài)設(shè)置為up或down。

          這樣的話,我們可以通過preStop調(diào)用該接口實(shí)現(xiàn)另外一種方式的優(yōu)雅關(guān)閉。


           lifecycle:
                  preStop:
                    httpGet:
                      path: /unhealthy
                      port: http

          最后服務(wù)端收到優(yōu)雅關(guān)閉信號(hào)后可以進(jìn)行一些善后處理工作。

          這就是K8s,自身很簡(jiǎn)單,但是它的低層牽涉了Linux內(nèi)核、進(jìn)程、網(wǎng)絡(luò)、存儲(chǔ)等方方面面的知識(shí),但并不會(huì)在Kubernetes的文檔中交代清楚??善褪撬鼈?,才是容器技術(shù)的精髓所在。


          Linux命令查詢工具

          有收獲,點(diǎn)個(gè)在看 

          瀏覽 138
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美女同网站 | 人人插人人操人人摸 | 一到本在线视频无码 | 中文字幕乱 | 深爱五月激情 |