Kubernetes快速调试平台

88 阅读4分钟

Kubernetes快速调试平台

在使用Kubernetes工作时,需要访问Kubernetes内部资源的情况并不罕见。虽然你可以桥接很多东西,但你也可能需要从Kubernetes环境/网络/......运行一个镜像来重现一个问题并更快地连接(桥接如果在你的电脑前进行,特别是通过VPN),会很慢。

要解决这个问题,最简单的是部署一个调试容器,它将在你调查问题的时候运行(例如,检查一些数据库内容)。

最近的Kubernetes版本创建了短暂性容器的概念(doc)。长话短说,这是一种在没有任何资源保证的情况下运行容器的方法(我把它看作是 "低优先级 "容器),没有端口绑定也没有探针。一个短暂的容器的主要优点是能够在一个特定的Pod ,以检查它的状态。

然而,在实践中,我们经常想弹出一个容器来连接到其他人或检查应用程序的状态(数据库、文件系统...)。而这时,短暂的容器并不是最好的选择....,因为它们需要你有权限来运行它们,并且需要一个非常新的Kubernetes版本,而这两个假设到今天为止并不总是真实的(希望在未来几年内会有所改变)。

所以今天,在Kubernetes集群中运行调试容器的最佳选择--假设你有部署权限--是运行一个普通的旧容器:

kubectl run \ (1)
  debug \ (2)
  --restart=Never \ (3)
  --image=alpine \ (4)
  -it \ (5)
  -- /bin/sh (6)
  1. kubectl (你确实可以用YAML来代替)运行一个容器。
  2. 命名这个容器debug
  3. 当它被关闭时不要重启(=当我停止它时)
  4. 使用alpine 图像
  5. 在交互式模式下运行它(实际上我们想连接到它)。
  6. 打开一个shell

所以在这之后我们会得到一个为我们启动shell的容器。

在这篇文章中,我使用了alpine 和它的包管理器apk ,但如果你觉得用ubuntuapt 更合适,只需替换图像和命令,效果是一样的。

我们就完成了 :).... 差不多了。

在一些(开发)不安全的环境中,它将工作得很好,你将连接到shell,apk update && apk add <debug tool> ,你将调试你需要的东西。然而,在安全的环境中,它将无法运行,因为root用户(容器的默认用户)被禁止修改容器(apk ,会告诉你系统被锁定):

ERROR: Unable to lock database: Permission denied
ERROR: Failed to open apk database:

有多种方案可以解决这个问题,从调整部署以给容器运行命令的权限(如果不是在纯开发环境中,不建议这样做)到创建一个预先打包的镜像。

这是我倾向于使用的最后一个选项,因为它有一些优势:

  • 在工具安装方面,你可以做你想做的事,因为你在构建机器上运行它(通常是你的)。
  • 你预先打包了一个实用的镜像,然后在需要的时候可以重复使用,避免了下次重新设置所有的工具。
  • (可选的)你可以在图像中注入一些别名,以使用kubernetes环境变量的快捷方式(我常用的是pg ,连接到环境中的postgres服务)。

要使用最后一个选项,第一步是创建一个docker镜像。要做到这一点,你可以在任何空文件夹中创建这个Dockerfile

FROM alpine (1)
RUN apk update && apk add postgresql-client curl (2)
ENTRYPOINT "/bin/sh" (3)
  1. 使用你喜欢的基础镜像。
  2. 安装你需要的工具(postgresql客户端和curl那里)。
  3. 默认启动一个shell(避免容器在部署时立即启动和停止)。

然后你需要构建这个镜像。要做到这一点,从你放置Dockerfile 的文件夹中运行这个命令:

docker build . \ (1)
  -t $MY_REGISTRY/debug (2)
  1. 从这个文件夹中的Dockerfile 创建镜像。
  2. 将镜像(名称)标记为$MY_REGISTRY/debug 。这里很重要的一点是,$MY_REGISTRY 是你将推送镜像的注册表,Kubernetes将从这里下载镜像。

现在你有了你需要的工具的调试镜像,只要把它远程推送到你的Kubernetes/images注册表。

docker push $MY_REGISTRY/debug

如果你的注册表是经过认证的(通常是),确保在之前运行docker login <registry host>

在这个阶段,我们推送了我们的镜像,Kubernetes能够运行它,所以我们只需要修改之前的命令,部署我们的镜像,而不是一个普通的alpine

kubectl delete pod debug (1)
kubectl run debug --restart=Never --image=$MY_REGISTRY/debug -it -- /bin/sh (2)
  • 我们删除之前的pod部署,它应该还在那里。
  • 我们将新创建的调试镜像部署在一个容器中。

在那里你可以使用你预先包装在镜像中的所有工具来调试你的应用程序。

最后,当你用完你的debug 容器后,你可以用kubectl delete pod debug 删除它。

有很多方法可以实现这种事情,但这种技术是相当有效的,对我来说,它比其他方法具有最大的优势。

我喜欢使用的最后一个技巧是不把调试容器命名为debug ,而是使用我的用户名(如果我们人数众多,则使用团队名称)。这样就可以不交叉使用图像,并在run 结束时杀死容器,另外这也可以区分工具,不覆盖图像而不创建大量的标签(使用一个日期)。一个非常接近的选择是将图像命名为debug ,用你的name ,并将容器命名为debug-$name ,但这在时间上比每个人/组有一个图像,并以与图像相同的方式命名容器更不容易处理。有一个单一的名字(而且只是一般地使用latest ),在团队轮换时就很容易清理图像和容器了。