K8s 容器调试高级技巧

小夏 科技 更新 2024-01-29

如果您在 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 sshkubectl 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#

相似文章

    K8S 集群部署工具 Kubeadm 详解

    朋友们,您好。Kubeadm 是快速创建 Kubernetes 集群的最佳实践工具,我们只需要使用 kubeadm init 和 kubeadm join 命令即可完成 ks 集群的部署。kubeadm init 用于部署控制平面节点。kubeadm join 用于部署 Worker 节点并将它们加...

    Trivy 为 K8s 添加了 KBOM 漏洞扫描

    标准做法是扫描应用程序和 以查找漏洞。但为什么要止步于此呢?Aqua 希望为 Kubernetes 带来相同级别的安全性。Trivy 将 KBOM 漏洞扫描添加到 Ks 中,作者 Itay Shakury 是 Aqua Security 的开源副总裁,负责领导开源云原生安全解决方案的工程设计。Ita...

    8K分体终端M800S超高清多屏触控,提升会议效率

    K分体终端MS kp 帧超高清体验,多界面多视角合成,触控平板控制。在当今先进的会议技术下,K分体终端MS凭借其出色的KP帧超高清体验 多界面多屏合成能力和触控平板控制模式,为用户带来前所未有的会议协作体验。.Kp帧超高清 体验 MS支持kp帧超高清信号输出,具备实时编解码能力,无论在何种网络环境下...