docker - 如何运行 sleep 命令到 distroless

标签 docker kubernetes

我计划使用 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) 命令并不完全兼容。

我可以建议几种方法来解决这个问题:

  1. 弄清楚如何完全不需要 sleep (1)。 “我们需要等待 40 秒,因为 Envoy”看起来您正在解决一个错误;修复该错误,而不是尝试延迟容器关闭。

  2. 使用与主应用程序相同的语言重新实现延迟。例如,在 Python 中,它是一个 3 行脚本。那么运行它所需的一切都已经在图像中了。

  3. 获取静态编译的sleep(1) 二进制文件。获取此信息的最简单方法是从 BusyBox工具套件,在单个二进制文件中包含许多常见的 Unix 实用程序;但 Alpine Linux 基本上只是 BusyBox 加上一个包管理器,因此获得 BusyBox 的最简单方法是将您的镜像更改为 FROM 基于 Alpine 的镜像。

  4. 获取 sleep(1) 二进制文件所需的所有动态库。您可以在可以运行的环境中运行 ldd sleep 来找出它们是什么。不过,您可能不想直接从主机复制它们,这就是普通 Linux 发行版预打包这些库的地方(并且已经带有 /bin/sleep)。

在您的 Dockerfile 中,您可能会遇到损坏的符号链接(symbolic link) /bin/sleep -> busybox。您还可以复制 busybox 二进制文件,但这本质上违背了拥有无发行镜像的意义。

关于docker - 如何运行 sleep 命令到 distroless,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66579990/

相关文章:

postgresql - postgres 和 docker-compose : can't create a custom role and database

node.js - Mongoose 无法连接到docker中的mongodb

docker - 在 GCP 启动脚本期间查找用户名

postgresql - 无法启动用 docker-compose 编写的 kong 服务

go - 如何在运行独立go服务的kubernetes中配置Pod的就绪和活跃性探针?

docker - minikube 无法在 ubuntu 20.04 LTS 上启动。由于 GUEST_PROVISION 退出

docker - Docker会协助作为高级压缩器吗?

kubernetes - 在 GCP 中为负载均衡器获取 DNS

azure - Azure Kubernetes (AKS) 'Time-out' 会发生什么情况会断开集群中 Pod 进出的连接?

kubernetes - 在尝试部署 Prometheus 时出现错误 : found in Chart. yaml,但在图表/目录中丢失:kube-state-metrics