如果您在 Kubernetes 上运行软件,则需要调试在某个时候部署的软件的某些方面。 对于 习 虚拟机 (VMS) 来说,一种自然而然的简单调试方法是连接到正在运行的 Pod 并对其进行解释:
kubectl exec -it podname -c containername --bash这通常有效,而且有效。 但是,至少有两种类型的 Kubernetes"最佳实践"限制了 exec 的有用性:
不要以 root 身份运行。 容器以尽可能少的权限运行,甚至可能使用随机用户标识符 (UID) 运行。
尽量减少镜像。 映像尽可能小,您甚至可以将二进制文件写入无发行版映像。
应用这些最佳做法时,请使用:kubectl exec
连接到容器不可行,或者进入不适合调试的环境。
kubectl exec 指令不允许指定用户标志或功能来启动进程,而是从目标容器的 main 指令中复制这些设置。在解决运行容器的问题时,Kubernetes 提供了使用的原生化调试策略
kubectl debug
。debug 指令在正在运行的 pod 中启动一个新容器。 这个新容器可以作为不同的用户和你选择的任何映像运行。 由于调试容器与目标容器在同一个 Pod 中运行(因此在同一节点上),因此两者之间不需要绝对隔离。 调试容器可以与在同一 Pod 中运行的其他容器共享系统资源。
考虑签入 podpostpod
器皿postcont
中运行的 PostgreSQL 数据库的 CPU 使用率。 这个 pod 不以 root 身份运行,并且 postgres 镜像没有安装 top 或 htop 等工具,即kubectl exec
指令几乎没有效果。 您可以按照以下说明进行操作:
kubectl debug -it \ container=debug-container \ image=alpine \ target=postcont \ postpod您将以 root 身份登录(这是 Alpine 镜像的默认设置),并可以轻松安装您喜欢的交互式进程查看器 htop()。
apt add htop
)。您使用postcont
容器共享同一个进程命名空间,运行在其上的所有进程都可以查看甚至终止!退出进程时,临时容器也会终止。
如果要使用以上postcont
共享相同的进程命名空间,即使postcont
是的postpod
指定运行的唯一容器--target
是非可选的。可以按 Ctrl+P、Ctrl+D 断开与临时容器 bash 会话(会话)的连接,而无需退出(终止)该会话。 再使用
kubectl attach
重新连接。
kubectl debug
除了这里概述的之外,还有更多的功能,例如使用修改后的引导指令复制 Pod,或者通过访问节点的文件系统来引导 Pod"节点" pod。
kubectl debug
该指令是通过创建临时容器来实现的。 这些容器应在现有 Pod 中临时运行,以支持故障排除等操作。 “普通”容器和临时容器之间的差异很小。 看看 Kubernetes 在成立之初所做的基础设施选择,是理解我们为什么使用临时容器的最佳方式:
Pod 应该是一次性的、可更换的,并且 Pod 规格是不可变的。当 Kubernetes 主要用于部署无状态工作负载时,这更有意义——其中 Pod 本身被认为是临时的。 在这个 kubernetes 中,它可以被限制。 Pod 规范保持不变,但 Kubernetes 将临时容器建模为 Pod 的子资源。 与“普通”容器不同,临时容器不是 Pod 规范的一部分
内置指令kubectl debug
非常有用。 它允许你向正在运行的 Pod 添加一个临时容器,并可以选择与正在运行的 Pod 共享进程命名空间。 不过,如果您想使用kubectl debug
检查或修改正在运行的容器文件系统的一部分,而您就不走运了,因为调试 Pod 的文件系统与要连接到的容器的文件系统是分开的。 幸运的是,我们可以做得更好。 原理很简单:
阅读正在运行的目标容器的规范。
将临时容器填充到 Pod 中。 将其配置为与目标容器共享相同的进程命名空间,并包含相同的卷装载。
由于没有用于创建临时容器的 kubectl 命令,因此我们需要向 k8s api 构建一个补丁请求来创建它。 kubectl proxy
该指令允许访问 K8S API。 这个过程不是很人性化,所以把它封装到脚本或 kubectl 插件中是有意义的。 您可以在此处找到此类脚本实现的示例:
需要注意的是,这种方法和脚本可以很容易地扩展到从目标容器复制环境变量的规范。 如果将此脚本另存为
kubectl-superdebug
把它放在你的路上,你可以把它带到任何地方kubectl superdebug
运行形式如下:
还可以尝试扩展此脚本,以将目标容器的其他方面复制到调试容器中,例如环境变量引用。
至此,你已经大致了解了 Kubernetes 如何以本机方式调试正在运行的容器,它应该可以满足大多数人的需求。
Kubernetes 不提供以 root 身份连接到正在运行的容器的方法(除非主进程以 root 身份运行),也不提供从另一个容器访问容器根文件系统的方法。 但这并不意味着这些事情不能做。 毕竟,Kubernetes 只是一个位于容器化引擎之上的容器编排器。 如果出于某种原因,它确实有必要,您通常可以通过删除抽象层来做任何您想做的事情。
如果您使用的是 docker 引擎,并且可以直接从节点上运行的特权容器或通过节点上运行的特权容器访问您的引擎,那么您就可以开始了docker exec --user
并以您选择的用户身份执行流程。
kubectl ssh
跟kubectl exec-user
以及实现此方法的其他插件。 但可悲的是,containerd 和 cri-o 等现代引擎已不再可用--user
这会标记功能,这意味着这些插件无法在当前的 Kubernetes 安装上运行。
然而,即使是这些现代引擎,通常也只能与 Linux 命名空间交互。 通过输入适当的 Linux 命名空间集,您可以在任何所需的“容器”中运行指令。 kpexec 工具实现了这种方法。 它在与目标容器相同的节点上启动一个特权 Pod,然后确定它想要面向哪个 (linux) 命名空间,在这些 (linux) 命名空间中执行命令,最后将其输出流式传输到终端。 作为额外的奖励,它还在目标容器的文档系统之上覆盖了一组用于调试的工具。
与 kubectl exec 不同,kpexec 可以使用不同的 uid gid 运行指令,甚至可以使用与主容器进程不同的功能。 它与 containerd 和 cri-o 兼容。 只是 kpexec 采取的方法有些笨拙和脆弱,可能与集群的安全配置不兼容。 但是,如果 kubectl(超级)调试不能满足您的需求,则值得考虑。
需要注意的是,kpexec 使用 nsenter 直接在命名空间中执行指令。 它与无处不在的容器运行时 runc 兼容,但与 kata 容器等运行时不兼容。Appilot 是用于 DevOps 场景的开源 AI 助手,它可以充分利用 AI 大型语言模型的强大功能,允许用户直接输入自然语言,从而进一步简化应用程序部署和管理体验。用户可以根据自己的需求和使用情况将appilot集成到任何平台习中,然后通过输入自然语言实现调用后端平台的能力,轻松完成kubernetes调试工作。
#kubernetes#