我想实现一个shutdown-script
在我的 VM 将在 Google Compute Engine 上被抢占时调用的方法。该 VM 用于运行执行长时间运行的批处理的 dockers 容器,因此我向它们发送一个信号以使它们正常退出。
当我手动执行它时,该关闭脚本运行良好,但在真正的抢占用例或我自己杀死 VM 时它会中断。
我收到了这个错误:
... logs from my containers ...
A 2019-08-13T16:54:07.943153098Z time="2019-08-13T16:54:07Z" level=error msg="error waiting for container: unexpected EOF"
(just after this error, I can see what I put in the 1st line of my shutting-down script, see code below)
A 2019-08-13T16:54:08.093815210Z 2019-08-13 16:54:08: Shutting down! TEST SIGTERM SHUTTING DOWN (this is the 1st line of my shuttig-down script)
A 2019-08-13T16:54:08.093845375Z docker ps -a
(no reult)
A 2019-08-13T16:54:08.155512145Z ps -ef
... a lot of things, but nothing related to docker ...
2019-08-13 16:54:08: task_subscriber not running, shutting down immediately.
我使用来自 GCE 的抢占式 VM,带有 image Container-Optimized OS 73-11647.267.0 stable
。我将我的码头工人作为服务运行systemctl
,但我不认为这是相关的 - [编辑]实际上我可以通过这个解决我的问题。
现在,我很确定当 Google 向我的 VM 发送 ACPI 信号时会发生很多事情,甚至在从 VM 元数据中获取并调用关闭脚本之前。
我的猜测是所有服务都同时停止,最终停止docker.service
。
当我的容器运行时,我可以level=error msg="error waiting for container: unexpected EOF"
通过一个简单的sudo systemctl stop docker.service
这是我的shuting-down
脚本的一部分:
#!/bin/bash
# This script must be added in the VM metadata as "shutdown-script" so that
# it is executed when the instance is being preempted.
CONTAINER_NAME="task_subscriber" # For example, "task_subscriber"
logTime() {
local datetime="$(date +"%Y-%m-%d %T")"
echo -e "$datetime: $1" # Console
echo -e "$datetime: $1" >>/var/log/containers/$CONTAINER_NAME.log
}
logTime "Shutting down! TEST SIGTERM SHUTTING DOWN"
echo "docker ps -a" >>/var/log/containers/$CONTAINER_NAME.log
docker ps -a >>/var/log/containers/$CONTAINER_NAME.log
echo "ps -ef" >>/var/log/containers/$CONTAINER_NAME.log
ps -ef >>/var/log/containers/$CONTAINER_NAME.log
if [[ ! "$(docker ps -q -f name=${CONTAINER_NAME})" ]]; then
logTime "${CONTAINER_NAME} not running, shutting down immediately."
sleep 10 # Give time to send logs
exit 0
fi
logTime "Sending SIGTERM to ${CONTAINER_NAME}"
#docker kill --signal=SIGTERM ${CONTAINER_NAME}
systemctl stop taskexecutor.service
# Portable waitpid equivalent
while [[ "$(docker ps -q -f name=${CONTAINER_NAME})" ]]; do
sleep 1
logTime "Waiting for ${CONTAINER_NAME} termination"
done
logTime "${CONTAINER_NAME} is done, shutting down."
logTime "TEST SIGTERM SHUTTING DOWN BYE BYE"
sleep 10 # Give time to send logs
如果我只是systemctl stop taskexecutor.service
手动调用(而不是通过真正关闭服务器),SIGTERM 信号将发送到我的 docker 并且我的应用程序会正确处理它并存在。
任何想法?
-- 我是如何解决我的问题的 --
我可以通过在我的服务配置中添加对 docker 的依赖来解决它:
[Unit]
Wants=gcr-online.target docker.service
After=gcr-online.target docker.service
我不知道除了shutdown-script
Google 执行存储在元数据中之外的魔法是如何工作的。但我认为他们应该修复一些问题,Container-Optimized OS
以便在 docker 停止之前发生魔法。否则,我们不能依靠它来优雅地关闭一个基本脚本(希望我在这里使用的是 systemd)......