docker-撰写健康检查重试频率!=间隔
docker-compose healthcheck retry frequency != interval
我最近在 docker-compose
配置中设置了 healthcheck
s。
它做得很好,我喜欢它。这是一个典型的例子:
services:
app:
healthcheck:
test: curl -sS http://127.0.0.1:4000 || exit 1
interval: 5s
timeout: 3s
retries: 3
start_period: 30s
我的容器启动很慢,因此我设置了 30 秒 start_period
。
但这并不符合我的期望:我不需要每 5 秒检查一次,但我需要尽快知道容器何时准备好以便我的编排,并且由于我的start_period
是近似值,如果第一次检查还没有准备好,我要等interval
再试。
我想要的是:
- 当容器不健康时,每 5 秒重试一次
- 一旦健康,每 1 分钟检查一次
有没有办法用 docker-compose
实现这个开箱即用的方法?
我可以编写自定义脚本来实现此目的,但如果可能的话,我宁愿使用本机解决方案。
不幸的是,开箱即用是不可能的。
所有持续时间设置都是最终的。它们不能根据容器状态更改。
但是,根据 documentation,探测似乎不会等待 start_period
完成才检查您的测试。它唯一做的就是 start_period
期间发生的任何失败都不会被视为错误。
下面是让我这么想的句子:
start_period
provides initialization time for containers that need time to bootstrap. Probe failure during that period will not be counted towards the maximum number of retries. However, if a health check succeeds during the start period, the container is considered started and all consecutive failures will be counted towards the maximum number of retries.
我鼓励您测试一下是否真的如此,因为我从来没有真正关注过健康检查是否在开始期间进行过测试。
如果是这种情况,如果您不确定持续时间,您可以增加 start_period
并增加 interval
以找到一个好的折衷方案。
我写了一个脚本来执行此操作,但我更愿意找到一个本地解决方案:
#!/bin/sh
HEALTHCHECK_FILE="/root/.healthchecked"
COMMAND=${*?"Usage: healthcheck_retry <COMMAND>"}
if [ -r "$HEALTHCHECK_FILE" ]; then
LAST_HEALTHCHECK=$(date -r "$HEALTHCHECK_FILE" +%s)
# FIVE_MINUTES_AGO=$(date -d 'now - 5 minutes' +%s)
FIVE_MINUTES_AGO=$(echo "$(( $(date +%s)-5*60 ))")
echo "Healthcheck file present";
# if (( $LAST_HEALTHCHECK > $FIVE_MINUTES_AGO )); then
if [ $LAST_HEALTHCHECK -gt $FIVE_MINUTES_AGO ]; then
echo "Healthcheck too recent";
exit 0;
fi
fi
if $COMMAND ; then
echo "\"$COMMAND\" succeed: updating file";
touch $HEALTHCHECK_FILE;
exit 0;
else
echo "\"$COMMAND\" failed: exiting";
exit 1;
fi
我用的是:test: /healthcheck_retry.sh curl -fsS localhost:4000/healthcheck
问题是我需要确保脚本在 每个 容器中可用,所以我必须为此创建一个额外的卷:
image: postgres:11.6-alpine
volumes:
- ./scripts/utils/healthcheck_retry.sh:/healthcheck_retry.sh
我最近在 docker-compose
配置中设置了 healthcheck
s。
它做得很好,我喜欢它。这是一个典型的例子:
services:
app:
healthcheck:
test: curl -sS http://127.0.0.1:4000 || exit 1
interval: 5s
timeout: 3s
retries: 3
start_period: 30s
我的容器启动很慢,因此我设置了 30 秒 start_period
。
但这并不符合我的期望:我不需要每 5 秒检查一次,但我需要尽快知道容器何时准备好以便我的编排,并且由于我的start_period
是近似值,如果第一次检查还没有准备好,我要等interval
再试。
我想要的是:
- 当容器不健康时,每 5 秒重试一次
- 一旦健康,每 1 分钟检查一次
有没有办法用 docker-compose
实现这个开箱即用的方法?
我可以编写自定义脚本来实现此目的,但如果可能的话,我宁愿使用本机解决方案。
不幸的是,开箱即用是不可能的。
所有持续时间设置都是最终的。它们不能根据容器状态更改。
但是,根据 documentation,探测似乎不会等待 start_period
完成才检查您的测试。它唯一做的就是 start_period
期间发生的任何失败都不会被视为错误。
下面是让我这么想的句子:
start_period
provides initialization time for containers that need time to bootstrap. Probe failure during that period will not be counted towards the maximum number of retries. However, if a health check succeeds during the start period, the container is considered started and all consecutive failures will be counted towards the maximum number of retries.
我鼓励您测试一下是否真的如此,因为我从来没有真正关注过健康检查是否在开始期间进行过测试。
如果是这种情况,如果您不确定持续时间,您可以增加 start_period
并增加 interval
以找到一个好的折衷方案。
我写了一个脚本来执行此操作,但我更愿意找到一个本地解决方案:
#!/bin/sh
HEALTHCHECK_FILE="/root/.healthchecked"
COMMAND=${*?"Usage: healthcheck_retry <COMMAND>"}
if [ -r "$HEALTHCHECK_FILE" ]; then
LAST_HEALTHCHECK=$(date -r "$HEALTHCHECK_FILE" +%s)
# FIVE_MINUTES_AGO=$(date -d 'now - 5 minutes' +%s)
FIVE_MINUTES_AGO=$(echo "$(( $(date +%s)-5*60 ))")
echo "Healthcheck file present";
# if (( $LAST_HEALTHCHECK > $FIVE_MINUTES_AGO )); then
if [ $LAST_HEALTHCHECK -gt $FIVE_MINUTES_AGO ]; then
echo "Healthcheck too recent";
exit 0;
fi
fi
if $COMMAND ; then
echo "\"$COMMAND\" succeed: updating file";
touch $HEALTHCHECK_FILE;
exit 0;
else
echo "\"$COMMAND\" failed: exiting";
exit 1;
fi
我用的是:test: /healthcheck_retry.sh curl -fsS localhost:4000/healthcheck
问题是我需要确保脚本在 每个 容器中可用,所以我必须为此创建一个额外的卷:
image: postgres:11.6-alpine
volumes:
- ./scripts/utils/healthcheck_retry.sh:/healthcheck_retry.sh