客串文章,最初发表在Lightrun的博客上,作者是Lightrun的开发者关系总监Tom Granot

KoolKits(Kubernetes工具包)是Kubernetes的高度自治的、特定语言的、包含电池的调试容器镜像。在实践中,如果你在一个不熟悉的shell中进行艰难的调试时被卡住了,他们就是你在生产pod上安装的东西。

如果你不喜欢书面文字,我们为该项目制作了一个2分钟的快速解释。

简要介绍一下背景,请注意这些容器镜像是为了与新的kubectl 调试功能一起使用的,该功能可以启动Ephemeral 容器进行交互式故障排除。KoolKit 将被kubectl debug 拉出,作为你的 pod 中的一个容器被旋转起来,并且能够访问与你的原始容器相同的进程命名空间。

由于生产容器通常都是光秃秃的,使用 KoolKit 可以让你用强大的工具来排除故障,而不是依赖由于最初构建生产镜像的人的慷慨(或粗心)而留下的东西。

每个 KoolKit 中的工具都是精心挑选的,你可以在下面阅读更多关于整个项目背后的动机。

如果你只是想看一下好东西,请随时在GitHub上查看整个项目。

调试Kubernetes很困难

要了解Kubernetes吊舱内发生的事情并非易事。

多实例(即网络地狱)--为了有效地调试基于Kubernetes的应用程序,你需要能够访问运行在多个pods/节点中的同一应用程序的多个副本,以及运行在不同pods/节点上的多个应用程序。为了获得运行特定代码的特定应用程序的shell并对其进行调试,你需要在人群中识别它,即使如此--也仅限于特定的pod,因为shell是1-1。

没有工具/信息的图像-- 云原生世界的最佳做法是运送 "薄图像"--包含尽可能少的臃肿的容器基础,以确保拉动时间的快速。这意味着,许多这些容器缺乏基本的工具--有些 容器基本上不包含任何东西,甚至没有一个shell--这使得在shell层面上的调试几乎不可能。

置断点会导致级联故障--注意,一般来说,分布式应用倾向于创建相互依赖的服务--一个网络服务会依赖一些引导服务,另一个服务调用网络服务,从而依赖它,等等。如果一个服务失败了,所有依赖它的其他服务也会失败。当在一个其他服务依赖的服务内放置一个断点时,我们就会有发生级联故障的风险--一个服务杀死一个依赖它的服务,就会杀死另一个依赖它的服务,以此类推。

调试可以改变状态 - 使用调试器,你可以改变应用程序中的各种值并修改状态。这可能会对生产应用产生灾难性的后果,这些应用应该被排除在任何内部干扰之外--所有的状态修改应该通过外部的输入和应用于它们的逻辑发生,而不是由开发者干扰应用。

隐私考虑--市场上的大多数工具并不能防止开发者暴露在私人敏感数据中。相反,开发人员可以在允许他们查看信用卡信息、个人健康数据等的位置添加断点。

该领域的工具也有很多需要改进的地方--为开发目的将本地环境连接到远程集群的工具通常只允许你在任何特定时间点在一个服务上工作--你可以连接到远程服务,但你一次只能开发一个服务。此外,服务网状结构故障排除器依赖于,嗯--服务网状结构,而现在并非所有集群都有。

KoolKits 背后的动因

我们很早就意识到,通过使用正确的工具来打包,对于故障排除的开发者来说是一个巨大的力量源泉--我们想找到一种方法来回馈社区--这就是我们想出的 KoolKits 的想法。

让我们深入探讨一下,解释一下为什么 KoolKits 会非常有用。

正如我们之前提到的,有一个众所周知的 Kubernetes 最佳实践,即应该建立小型容器镜像。这是有道理的,有几个不同的原因。

  1. 构建镜像将消耗更少的资源(又称CI时间)。
  2. 拉取镜像将花费更少的时间(反正谁愿意为这么多的ingress付费?)
  3. 更少的东西意味着暴露在安全漏洞下的表面积更小,在这个世界上,即使是无操作记录也不安全了

还有很多工具存在,可以帮助你在不做太多繁重工作的情况下达到目的。

  1. Alpine Linux的基础镜像是超级小的
  2. 无DistroLess Docker镜像更进一步,除了运行时之外,删除了所有东西。
  3. Docker多阶段构建有助于创建薄的最终生产镜像

当你试图调试这些容器内发生的事情时,问题就开始了。通过使用一个小的生产镜像,你放弃了大量的工具,而这些工具在解决你的应用程序中的问题时是非常宝贵的

通过使用 KoolKit,你可以让自己获得小型生产镜像的好处,而不会在高质量的工具上打折扣--每个 KoolKit 都包含为它所代表的特定运行时精心挑选的工具,此外还有一套更通用的基于 Linux 系统的工具。

P.S. KoolKits 的灵感来自kubespynetshoot

考虑因素

在构建这些图像的过程中,我们做了不少决定--下面列出了我们考虑的一些事情。

图像的大小

KoolKits Docker 镜像往往运行得,呃,相当

KoolKits 的目的是下载一次,保存在集群的 Docker 注册表中,然后在需要时立即作为容器启动。由于它们并不打算持续拉动,而且由于它们打算装满好东西,这是一个我们愿意忍受的副作用。

使用Ubuntu基础镜像

很难创建一个真正苗条的镜像的部分原因是我们决定使用一个完整的 Ubuntu 20.04 系统作为每个 KoolKit 的基础。这主要是因为我们希望在你的集群中复制与你在本地调试相同的环境。

例如,这意味着不需要用Alpine来替代你习惯使用的正常Ubuntu软件包。实际上,这意味着我们有办法在每个 KoolKit 中包括那些没有 Alpine 版本的工具。

使用语言版本管理器

每个 KoolKit 都使用(尽可能)一个语言版本管理器,而不是依赖特定语言的发行版。这样做是为了让你能够轻松地安装较早的运行时版本,也是为了让你能够在需要时在运行时版本之间随意交换(例如,获得只存在于特定运行时版本的工具的特定版本)。

 
 

可用的KoolKits

Repo 中的每个文件夹都包含 KoolKit 背后的 Docker 文件以及对调试镜像的简短解释。所有的KoolKits都是基于ubuntu:20.04的基础镜像,因为真正的人需要真正的外壳。

可用的 KoolKits 列表。

  1. koolkit-jvm- 采用OpenJDK 17.0.2及相关工具(包括便于版本管理的jabba和Maven 3.8.4)
  2. koolkit-node- Node 16.13.1 及相关工具 (包括便于版本管理的nvm)
  3. koolkit-python- Python 3.10.2 及相关工具(包括便于版本管理的pyenv)

请注意,你实际上不需要自己构建它们--所有的 KoolKits 都公开托管在Docker Hub上,可以免费使用。

KoolKits 即将推出

贡献

我们非常乐意为任何图像添加我们遗漏的工具--只要打开一个拉动请求一个问题来建议一个。

KoolKits 是由 Lightrun 创建的 - 一个开发者观察平台。使用Lightrun,开发者可以将新的、只读的日志、指标和痕迹实时添加到本地或生产中运行的实时应用程序中--无需重新部署或停止该应用程序。Lightrun在Kubernetes上开箱即用,并允许多模块、多集群调试,而不需要端口转发或服务网向导。 今天就在你的IDE中免费获得Lightrun。