Singularity容器实例自动自停止实现:子进程kill 1无效问题解决
kill 1无法终止sinit的问题 问题描述
需要实现可自动停止的Singularity容器实例:通过singularity instance start启动,定期检查容器内是否有存活进程,无进程时延迟停止容器。预期通过终止PID命名空间内的PID 1(sinit进程)实现全容器进程终止,但在%startscript的子进程(如子shell或Python监控进程)中执行kill 1无效,直接在%startscript主进程执行则有效,手动通过singularity exec执行kill 1也有效。
问题原因
Singularity的sinit进程作为容器PID命名空间的init进程,默认会忽略来自容器内子进程的SIGTERM信号(kill 1默认发送此信号),但会响应来自%startscript主进程或外部singularity exec的SIGTERM,以及所有来源的SIGKILL信号。
解决方案
提供两种可行方案,根据你的监控场景选择:
方案1:发送强制终止信号(SIGKILL)
在子进程中使用kill -9 1替代kill 1,直接发送SIGKILL信号(此信号无法被进程忽略)。修改后的test2.def示例:
# (test2.def) Bootstrap: Library From: alpine:latest %startscript ( sleep 5 kill -9 1 )
构建并启动后,5秒后实例会被强制终止。
方案2:让kill 1在%startscript主进程执行
如果需要保留SIGTERM的优雅终止逻辑,可将监控进程后台运行,让%startscript主进程等待监控进程退出后再执行kill 1。适用于Python监控脚本的场景:
# (带Python监控的示例.def) Bootstrap: Library From: ubuntu:latest %files monitor.py /opt/monitor.py %startscript # 启动Python监控进程后台运行 python3 /opt/monitor.py & MONITOR_PID=$! # 等待监控进程完成(监控逻辑结束后自行退出) wait $MONITOR_PID # 主进程执行kill 1,优雅终止容器 kill 1
其中monitor.py实现定期检查容器内进程的逻辑,当无存活进程时退出,触发主进程的kill 1操作。
验证方法
构建容器后执行:
sudo singularity build auto-stop.sif your-def-file.def singularity instance start auto-stop.sif auto-stop
等待监控逻辑触发后,通过singularity instance list确认实例已停止。
内容的提问来源于stack exchange,提问作者akraf

