自我回答,因为我找到了适合我们的解决方案:
tl;dr:使用 .ebextensions 脚本在 01flip 之前运行您的脚本,您的脚本将确保 docker 内的任何内容正常关闭
首先,您的应用程序(或您在 docker 中运行的任何程序)必须能够捕获信号,例如 SIGINT,并在其上正常关闭。
这与 Docker 完全无关,您可以测试它在任何地方运行(例如在本地)有很多关于为网络上不同类型的应用程序(无论是 ruby、node.js 等)完成这种行为的信息。 .)
其次,基于 EB/Docker 的项目可以有一个 .ebextensions 文件夹,其中包含在部署时要执行的各种脚本。我们将 2 个自定义脚本放入其中,gracefulshutdown_01.config 和 gracefulshutdown_02.config 文件看起来像这样:
# gracefulshutdown_01.config
commands:
backup-original-flip-hook:
command: cp -f /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh /opt/elasticbeanstalk/hooks/appdeploy/01flip.sh.bak
test: '[ ! -f /opt/elasticbeanstalk/hooks/appdeploy/01flip.sh.bak ]'
cleanup-custom-hooks:
command: rm -f 05gracefulshutdown.sh
cwd: /opt/elasticbeanstalk/hooks/appdeploy/enact
ignoreErrors: true
和:
# gracefulshutdown_02.config
commands:
reorder-original-flip-hook:
command: mv /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh /opt/elasticbeanstalk/hooks/appdeploy/enact/10flip.sh
test: '[ -f /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh ]'
files:
"/opt/elasticbeanstalk/hooks/appdeploy/enact/05gracefulshutdown.sh":
mode: "000755"
owner: root
group: root
content: |
#!/bin/sh
# find currently running docker
EB_CONFIG_DOCKER_CURRENT_APP_FILE=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_file)
EB_CONFIG_DOCKER_CURRENT_APP=""
if [ -f $EB_CONFIG_DOCKER_CURRENT_APP_FILE ]; then
EB_CONFIG_DOCKER_CURRENT_APP=`cat $EB_CONFIG_DOCKER_CURRENT_APP_FILE | cut -c 1-12`
echo "Graceful shutdown on app container: $EB_CONFIG_DOCKER_CURRENT_APP"
else
echo "NO CURRENT APP TO GRACEFUL SHUTDOWN FOUND"
exit 0
fi
# give graceful kill command to all running .js files (not stats!!)
docker exec $EB_CONFIG_DOCKER_CURRENT_APP sh -c "ps x -o pid,command | grep -E 'workers' | grep -v -E 'forever|grep' " | awk '{print $1}' | xargs docker exec $EB_CONFIG_DOCKER_CURRENT_APP kill -s SIGINT
echo "sent kill signals"
# wait (max 5 mins) until processes are done and terminate themselves
TRIES=100
until [ $TRIES -eq 0 ]; do
PIDS=`docker exec $EB_CONFIG_DOCKER_CURRENT_APP sh -c "ps x -o pid,command | grep -E 'workers' | grep -v -E 'forever|grep' " | awk '{print $1}' | cat`
echo TRIES $TRIES PIDS $PIDS
if [ -z "$PIDS" ]; then
echo "finished graceful shutdown of docker $EB_CONFIG_DOCKER_CURRENT_APP"
exit 0
else
let TRIES-=1
sleep 3
fi
done
echo "failed to graceful shutdown, please investigate manually"
exit 1
gracefulshutdown_01.config是一个小工具,用于备份原始的 flip01 并删除(如果存在)我们的自定义脚本。
gracefulshutdown_02.config是魔法发生的地方。它创建了一个 05gracefulshutdown 制定脚本,并通过将其重命名为 10flip 来确保之后会发生翻转。
自定义脚本 05gracefulshutdown 基本上是这样做的:
- 查找当前正在运行的 docker
- 找到所有需要发送 SIGINT 的进程(对我们来说,它的进程名称中带有 'workers'
- 向上述进程发送信号
- 环形:
- 检查之前的进程是否被杀死
- 继续循环尝试多次
- 如果尝试结束,以状态“1”退出并且不要继续 10flip,需要手动干预。
这假设您在机器上只运行了 1 个 docker,并且您能够手动跳上以在它失败的情况下检查什么是错误的(因为我们从未发生过)。
我想它也可以在很多方面得到改进,所以玩得开心。