K8S避坑指南 - Deployment更新POD內容器沒法收到SIGTERM信號

開源項目推薦

Pepper Metrics是我與同事開發的一個開源工具(github.com/zrbcool/pep…),其經過收集jedis/mybatis/httpservlet/dubbo/motan的運行性能統計,並暴露成prometheus等主流時序數據庫兼容數據,經過grafana展現趨勢。其插件化的架構也很是方便使用者擴展並集成其餘開源組件。
請你們給個star,同時歡迎你們成爲開發者提交PR一塊兒完善項目。html

簡述

容器化後,在應用發佈時,某個服務重啓,致使該服務調用方大量報錯,直到服務重啓完成。報錯的內容是RPC調用失敗,咱們的RPC這塊是有優雅關閉的,也就是說,在進程收到SIGTERM信號後,咱們經過JVM的ShutdownHook機制,註冊了RPC服務的反註冊鉤子,在進程收到SIGTERM時應用會主動從註冊中心摘除自身防止調用方大量報錯。可是爲何容器化後會致使這個問題呢?java

問題排查

應用正常啓動 git

查看容器內進程

# yum install psmisc
# pstree -p
bash(1)───java(22)─┬─{java}(23)
                   ├─{java}(24)
                   ├─{java}(25)
                   ├─{java}(26)
                   ├─{java}(27)
                   ├─{java}(28)
                   ├─{java}(29)
                   ├─{java}(30)
                    ...
# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 09:50 ?        00:00:00 /bin/bash run.sh start
root        22     1 15 09:50 ?        00:01:20 /app/3rd/jdk/default/bin/java -Xmx512m -Xms512m ...
root        49     0  0 09:51 pts/0    00:00:00 bash
root       263    49  0 09:59 pts/0    00:00:00 ps -ef
複製代碼

在容器內正常kill 22子進程,可見咱們應用的shutdown鉤子能夠正確處理善後工做 github

可是,在實際生產中,咱們的deploy滾動更新時,經過查看被刪除pod的日誌,發現pod被terminate的時候,應用進程並未正確處理SIGTERM信號,問題產生。

問題分析

根據對Kubernetes機制的調研,如圖: kubernetes.io/docs/concep… docker

由於咱們的容器是經過run.sh腳本啓動,這個在前面截圖能夠看到,java進程是1號run.sh進程的子進程,對應Kubernetes原理,可知22號java進程在POD刪除時不必定會收到SIGTERM,因此致使了咱們的shutdown hook不生效。

問題解決

既然已經定位問題,那麼解決問題的方法就有了思路,run.sh執行java進程後,將進程上下文讓給java進程,java進程接管,java進程變爲容器內的1號進程。 咱們參考了這篇文章受到啓發 yeasy.gitbooks.io/docker_prac… 在run.sh執行java前面增長exec命令便可 數據庫

而後,從新build鏡像,發佈,查看進程,發現咱們的java進程已是1號進程
而後重啓,再查看重啓前POD留下的日誌
問題解決!
相關文章
相關標籤/搜索