当删除 pod 或部署新版本的 pod 时,kubernetes 理论上应该向正在SIGTERM运行的进程发送.gracePeriodSecondsSIGKILL
我遇到了这个问题,这第一个SIGTERM似乎永远不会被发送。我的集群中的默认设置从未更改(kill 在 30 秒后按预期发送),因此我的假设是我的 Dockerfile 可能存在错误、权限或类似问题(见下文)。
我已经排除了优雅关闭逻辑中存在的错误,SIGTERM通过kubectl exec-ing 进入 pod 并kill -15在按预期工作的进程上使用来捕获可执行文件中的 。
Dockerfile 如下所示:
FROM debian:bullseye-slim AS app
ARG USERNAME=app
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN apt update && apt install -y libssl-dev zstd ca-certificates pkg-config
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME
WORKDIR /home/$USERNAME
ARG RELEASE_DIR
ARG SERVICE
USER $USERNAME
COPY $RELEASE_DIR .
EXPOSE 8080
ENV CMD=./${SERVICE}
CMD ${CMD}
Run Code Online (Sandbox Code Playgroud)
这里有明显的错误吗?或者 kubernetes 是否需要一些额外的配置才能真正按预期发送终止信号?
为了使终止正常工作,您需要确保您的应用程序是主容器进程。使用shell 形式 CMD,容器运行的命令是/bin/sh -c '${CMD}',并且根据该环境变量中的内容和/bin/sh实际内容,该 shell 包装器可能会继续作为主容器进程运行并拦截终止信号。
相同的机制适用于普通 Docker 和 Kubernetes,如果您docker stop在本地使用容器,您应该会看到类似的问题。这可能更容易调试和迭代。
解决此问题的最简单方法是使用看起来像 JSON 数组的exec 形式。CMD由于这不会运行 shell,因此它也无法进行变量扩展,并且您必须清楚地说明您希望命令实际是什么
CMD ["./service"]
Run Code Online (Sandbox Code Playgroud)
这在运行时仍然很容易覆盖,实际上您根本不需要它CMD:
# instead of `docker run -e CMD='...'`
docker run --rm my-image \
ls -l /home/app
Run Code Online (Sandbox Code Playgroud)
# or in a Kubernetes pod spec
command:
- /home/app/another_app
args:
- --option
Run Code Online (Sandbox Code Playgroud)
您可以类似地删除 Dockerfile 中的几乎所有ARG声明(例如,容器用户的名称或数字 uid 不重要,并且编译的应用程序文件名和主机构建路径通常是固定的),这将简化设置。
| 归档时间: |
|
| 查看次数: |
3897 次 |
| 最近记录: |