我计划使用 distroless 基础镜像来运行容器应用程序。
由于我在 k8s sidecar 中使用 envoy,因此当我停止应用程序容器时,我会在安全停止 pod 之前使用 preStop 中的 sleep 命令。
lifecycle
preStop:
exec:
command:
- sleep
- "40
由于distroless镜像不允许使用shell等,所以我们使用多阶段构建,以便我们可以使用sleep命令。
这个简单的 golang 应用程序。
FROM alpine:3.13 as builder
ENV GOROOT /go
FROM gcr.io/distroless/static-debian10
WORKDIR /app
COPY ./dist/app ./
COPY --from=builder /bin/sleep /bin/sleep
CMD ["./app"]
当我启动此镜像中的 Pod 并将其切换到另一个 Pod 时, sleep 命令失败。
Exec lifecycle hook ([sleep 40]) for Container
难道这样就不行了吗? 如果我做错了,我希望得到指点。
谢谢。
最佳答案
只有当您的图像仅包含您尝试运行的应用程序而绝对没有其他内容时,“distoless”图像才真正有意义。这通常是一个很好的做法,但尝试引入额外的 sleep(1) 命令并不完全兼容。
我可以建议几种方法来解决这个问题:
弄清楚如何完全不需要 sleep (1)。 “我们需要等待 40 秒,因为 Envoy”看起来您正在解决一个错误;修复该错误,而不是尝试延迟容器关闭。
使用与主应用程序相同的语言重新实现延迟。例如,在 Python 中,它是一个 3 行脚本。那么运行它所需的一切都已经在图像中了。
获取静态编译的sleep(1) 二进制文件。获取此信息的最简单方法是从 BusyBox工具套件,在单个二进制文件中包含许多常见的 Unix 实用程序;但 Alpine Linux 基本上只是 BusyBox 加上一个包管理器,因此获得 BusyBox 的最简单方法是将您的镜像更改为
FROM
基于 Alpine 的镜像。获取 sleep(1) 二进制文件所需的所有动态库。您可以在可以运行的环境中运行 ldd sleep 来找出它们是什么。不过,您可能不想直接从主机复制它们,这就是普通 Linux 发行版预打包这些库的地方(并且已经带有
/bin/sleep
)。
在您的 Dockerfile 中,您可能会遇到损坏的符号链接(symbolic link) /bin/sleep -> busybox
。您还可以复制 busybox
二进制文件,但这本质上违背了拥有无发行镜像的意义。
关于docker - 如何运行 sleep 命令到 distroless,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66579990/