• 深入理解Kubernetes Pod调试


    调试运行中的容器和Pod不像直接调试进程那么容易,本文介绍了通过临时容器共享命名空间的方式调试业务容器进程的方法。原文: Debugging Kubernetes Pods: Deep Dive

    Zan@Unsplash
    Zan@Unsplash

    调试pod最简单的方法是在有问题的pod中执行命令,并尝试排除故障。这种方法很简单,但有许多缺点。

    • 正在运行的应用pod可能没有排除现有问题所需的所有工具。
    • 如果想执行一些需要额外权限的操作,需要重新启动应用pod,以添加新的权限。
    • 在docker镜像中添加调试工具会引入安全风险,提升容器权限也是如此。

    因此,我们需要探索其他调试pod的方法。

    使用临时调试容器进行调试

    kubectl exec不够用时(比如容器已经崩溃,或者容器镜像没有包含调试实用程序,比如distroless镜像),或者正在运行的pod没有调试所需的特权时,[临时容器(ephemeral container)](https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/ "临时容器(ephemeral container "临时容器(ephemeral container)")")对于交互式故障排除非常有用。

    临时容器背后的主要思想是,K8S将具有选定自定义镜像的新容器添加到现有pod中,而不需要重新启动该pod。这个新的容器可以共享目标容器的资源,包括:

    • Linux网络命名空间
    • Linux进程命名空间
    • 访问共享卷
    • 访问K8S节点

    我将为每个用例提供一个示例。

    在开始演示前,需要有一个版本为1.23的k8s集群,建议使用```kind```[1],但也可以使用其他任何配置器。

    我们从创建演示集群开始。

    创建kind集群

    创建新集群很简单,只需运行命令kind create cluster

    示例: alt

    一旦创建了集群,需要验证是否启动并可访问。

    示例: alt

    所有操作都将从主kind节点执行,所以需要通过docker exec -it bash访问。

    示例: alt

    创建简单工作负载

    假设需要调试Nginx,我们创建一个单副本Nginx部署,通过运行以下命令来完成。

    kubectl create deployment nginx --image=nginx
    • 1
    alt
    诊断网络故障

    诊断网络故障需要共享网络命名空间。当将临时容器附加到运行中的pod时,这是默认的Linux命名空间。

    接下来我们创建第一个临时容器,使用nicolaka/netshoot作为新的临时容器的镜像,该镜像包含许多故障排除工具,如tcpdumpstrace

    kubectl debug -it pod-name --image= -- command
    • 1

    示例: alt

    我们确认一下两个容器共享相同的Linux命名空间。在主节点上打开一个新shell,并运行此命令:

    systemd-cgls -u kubelet-kubepods-besteffort.slice
    • 1

    示例: alt

    从上面的例子中,可以得到两个容器的主进程ID:

    • 2612 -> 临时容器的主进程ID
    • 2259 -> Nginx容器的主进程ID

    接下来,检查每个进程的Linux命名空间。

    alt

    从截图中可以发现,两个进程具有相同的Linux网络命名空间ID。

    现在我们从临时容器中抓取Nginx容器的网络数据包。

    从临时容器shell运行此命令:

    tcpdump -n port 80
    • 1

    示例: alt

    现在,试着从k8s主节点向这个pod发送一些请求。

    curl http://pod-ip-adderss
    • 1
    alt

    现在观察临时容器终端,会发现TCP报文会被打印出来:

    alt

    第一个演示完成,现在我们可以从临时容器捕获网络数据包了。

    接下来看第二个用例。

    利用临时容器跟踪/分析进程

    下一个用例是从临时容器跟踪应用容器中运行的进程。

    为此,我们需要:

    • 这两个容器必须共享相同的Linux进程命名空间。
    • 临时容器必须具有Linux capability SYS_PTRACE

    创建临时容器时,通过添加额外参数--target ,可以轻松共享Linux进程命名空间。

    kubectl debug -it  --image=nicolaka/netshoot --target  -- bash
    • 1

    示例: alt

    正如上面截图可以看到:

    1. 为了共享进程命名空间,需要添加额外的命令行参数 --target
    2. 从临时容器中,可以看到 nginx容器中所有正在运行的进程
    3. 因为临时容器没有 ptrace系统调用所需权限,因此无法跟踪 nginx进程。该系统调用被 strace命令用来暂停Linux进程,记录 nginx发送给内核的每个系统调用。

    如何解决这个问题?很不幸,我没有找到从kubectl命令向临时容器传递额外权限的方法。因此,我们将构造并发送HTTP请求到kube API服务器,而不使用kubectl命令。

    curl -v -XPATCH -H "Content-Type: application/json-patch+json" \
    'http://127.0.0.1:8001/api/v1/namespaces/default/pods/nginx-8f458dc5b-wkvq4/ephemeralcontainers' \
    --data-binary @- << EOF
    [{
    "op""add""path""/spec/ephemeralContainers/-",
    "value": {
    "command":[ "/bin/sh" ],
    "stdin"true"tty"true,
    "image""nicolaka/netshoot",
    "name""debug-strace",
    "securityContext": {"capabilities": {"add": ["SYS_PTRACE"]}},
    "targetContainerName""nginx" }}]
    EOF
    • 1

    现在可以在权限不被拒绝的情况下调用strace

    alt

    本例给临时容器添加了执行SYS_PTRACE的权限,但具体给什么权限取决于所用的调试器,或者简单点可以给临时容器特权访问,从而不需要担心需要允许哪个系统调用。

    另外,可以从临时容器访问nginx容器的文件系统。根文件系统位于/proc//root目录下。

    我们看看是否可以从临时容器访问nginx配置。

    示例: alt

    好了,接下来我们看一下临时容器的最后一个用例。

    通过节点上的shell进行调试

    有时候我们需要访问k8s节点,但却没有对节点的ssh或控制台访问权限。

    这时候可以通过临时容器访问节点。

    kubectl debug node/ -it --image=
    • 1

    在节点上创建调试会话时,请记住:

    • kubectl debug会根据节点名称自动生成新Pod的名称。
    • 容器运行在主机IPC、Network和PID命名空间中。
    • 节点根文件系统将挂载在 /host上。

    如果希望临时容器的根文件系统与节点相同,只需要将chroot /host

    示例: alt

    延伸阅读
    Debug Running Pods[2]
    Manage containers in namespaces by using nsenter[3] Debugging With Ephemeral Containers[4]

    你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。
    微信公众号:DeepNoMind

    参考资料

    [1]

    kind: https://kind.sigs.k8s.io

    [2]

    Debug Running Pods: https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod

    [3]

    Manage containers in namespaces by using nsenter: https://www.redhat.com/sysadmin/container-namespaces-nsenter

    [4]

    Debugging With Ephemeral Containers: https://static.sched.com/hosted_files/kccnceu2022/70/Ephemeral_Containers.pdf

    - END -

    本文由 mdnice 多平台发布

  • 相关阅读:
    Echarts案例网站(由于https://www.makeapie.com/关闭了,所以找了一些替代的)
    继承(1)
    超级超级灵性的解题思路,看了全部的题解,没有人想到这个思路,真·力扣唯一——用单调栈处理LeetCode 1562 查找大小为M的最新分组
    牛客练习赛106 E(二分图捏)
    扩展实现Unity协程的完整栈跟踪
    Maven基本操作详解
    Python Random模块详解
    Java19虚拟线程都来了,我正在写的线程代码会被淘汰掉吗?
    【Python零基础入门篇 · 15】:内置函数二【min()和max函数、zip()拉链函数、map()映射函数、reduce()】
    VSCode中使用github
  • 原文地址:https://blog.csdn.net/yuff100/article/details/132941033