正確使用‘trap指令’實現Docker優雅退出


一般應用(比如mariadb)都會有一個退出命令,用戶使用類似systemctl stop ****.service方法,停止其服務時,systemd會調用其配置文件注冊的退出命令,該命令執行清理資源、退出集群、輸出必要日志等操作后才殺死自己的進程;在系統shutdown的時候也會有類似的流程,最大程度的保證應用正常退出,下面我們稱之為“進程優雅退出”。

 

將應用Docker化后,一個突出的問題是,如何讓進程優雅的退出,而不是強行殺死進程。Docker stop和Docker kill分別實現了優雅退出和強行退出兩個操作:

Docker stop:向容器內1號進程,發送SIGTERM信號,在10S之后(可通過參數指定)再發送SIGKILL信號。

Docker kill:直接發送SIGKILL信號。

顯然Docker已經考慮到應用優雅退出的問題,但在實際使用中,會遇到下面2個困難:

1.  只有1號進程才收到SIGTERM信號,但Docker中有很多1號進程為monitor或者為初始化腳本的進程,並不是工作進程,且1號進程不能處理SIGTERM信號,以mariadb為例,容器內的進程關系如下:

1 /bin/sh /usr/bin/mysqld_safe --wsrep-cluster-address=gcomm:// 2 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql/ ...

其中2號進程為1號進程的子進程,雖然2號進程可以處理SIGTERM信號但其收不到該信號,而1號進程雖然能收到SIGTERM但並不能處理此信號。

2. 即使1號進程能處理SIGTERM信號,但若其有子進程為外部命令(非build in命令),且子進程為前台阻塞狀態,那么1號進程在直到子進程退出前仍然不能收到SIGTERM信號。如下bash是不會處理SIGTERM信號的:

#!/bin/bash trap 'exit 0' SIGTERM sleep 10000

關於這一點需要了解進程處理信號的限制:只有當進程阻塞在內建命令時才可以響應SIG信號,否則會一直等待子進程退出后再處理,如上面的bash,要等到10000秒之后才能處理SIGTERM。關於內建命令和外部命令,描述如下:

內部命令實際上是shell程序的一部分,shell不需要創建子進程,比如:exit,history,cd,echo,wait,trap等,linux系統加載運行時shell就被加載並駐留在系統內存中,一般不會fork子進程。 外部命令是linux系統中的實用程序部分,需要時才將其調用內存。一般會fork出子進程。 用type命令可以分辨內部命令與外部命令。

 

綜上所述,對於多進程Docker,我建議在容器中使用自定義bash腳本作為容器入口,腳本中使用后台方式執行具體應用的命令,然后使用內建wait阻塞,並通過trap指令監聽SIGTERM,執行應用退出操作,下面以容器化mariadb為例,描述其腳本的大概實現:

#!/bin/bash
trap 'mysqladmin -uroot -p123456 shutdown' SIGTERM mysqld_safe --wsrep-cluster-address=gcomm://10.158.113.207,10.158.113.80,10.158.113.79 & wait $!

以上述腳本為入口的maraidb容器內進程關系如下:

mysql        1  0.0 0.0 11628 1352 ? Ss+ 07:59 0:00 /bin/bash /usr/bin/test.sh mysql 9 0.0 0.0 11764 1636 ? S+ 07:59 0:00 /bin/sh /usr/bin/mysqld_safe --wsrep-cluster-address=gcomm://10.158.113.207,10.158.113.80,10 mysql 188 1.0 3.7 1087368 300168 ? Sl+ 07:59 0:16 \_ /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/p

當執行docker stop ***的時候,該容器會自動調用mysqladmin shutdown優雅退出。

 

以上為個人原創,歡迎轉發,並保留出處。

個人能力有限,錯誤之處請留言指出。


免責聲明!

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



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