
Kubernetes 网络之 Pod 网络调试
基本介绍
在实际工作中,我们经常会遇到一些疑似网络方面的故障问题,从而需要对 Kubernetes 集群中的 Pod 进行网络调试。
但是由于最小化原则,Pod 的容器镜像中通常并不会安装 ping、curl、telnet、tcpdump 等调试工具,或者在 Pod 容器中可以临时安装工具、但是效率不高,都会给 Pod 网络调试带来困难。
针对上述实际场景,笔者将在本文介绍一种 Pod 网络调试方法,以灵活应对网络调试需求。
Pod 网络调试
1、调试工具
nsenter 是 Linux 操作系统的一种命令行工具,允许用户进入指定进程的某个命名空间,并在该命名空间下灵活使用主机的命令行工具、执行特权操作等。
命名空间则是 Linux 内核的一种功能,用于将进程的资源隔离在不同的环境中,从而提高安全性和可靠性。常见的命名空间包括:
Mount:文件系统命名空间
UTS:主机名和域名命名空间
IPC:进程间通信命名空间
PID:进程命名空间
Network:网络命名空间
User:用户命名空间
通常在 Linux 操作系统中,默认安装有 nsenter。手动安装命令如下:
yum install -y util-linux || apt install -y util-linux
2、调试原理
在文章【Docker】专题一:Docker 基本架构 中提到,容器的本质是进程,但可以运行于独立的命名空间,拥有自己的 root 文件系统、网络配置、进程空间,甚至用户 ID 空间。
由此可见,我们可以通过 nsenter 进入 Pod 中容器(进程)的网络命名空间,利用 Node 节点已有的命令行工具实现对 Pod 进行网络调试。
3、调试过程
| 本过程在使用 Containerd 作为运行时的 Kubernetes 集群中进行验证
作为对比,进入 Pod 内容器查看是否安装有 ping、curl、telnet、tcpdump 等调试工具,可以看到相关命令都不存在
kubectl exec -it <pod_name> bash
确定 Pod 所在 Node 节点
kubectl get po <pod_name> -owide
登录到 Pod 所在 Node 节点
在 Node 节点上操作,获取 Pod 内某个容器的 ID
crictl ps | grep <pod_name>
根据容器 ID 获取容器 PID
crictl inspect <container_id> | grep -i pid
进入容器网络命名空间,并验证
nsenter -t <pid> -n
使用 Node 节点已安装的 ping、curl、telnet、tcpdump 等工具进行网络调试接口
nsenter 常用参数
-t <pid>:指定要进入的目标进程的 ID-m:进入目标进程的文件系统命名空间-u:进入目标进程的用户命名空间-i:进入目标进程的 IPC 命名空间-n:进入目标进程的网络命名空间-p:进入目标进程的 PID 命名空间--root=/path/to/root:指定容器根文件系统路径(仅在进入挂载命名空间时有效)--wd=/path/to/workdir:指定工作目录
=======================================================================nsenter -h
Usage: nsenter [options] [<program> [<argument>...]]
Run a program with namespaces of other processes.
Options: -a, --all enter all namespaces -t, --target <pid> target process to get namespaces from -m, --mount[=<file>] enter mount namespace -u, --uts[=<file>] enter UTS namespace (hostname etc) -i, --ipc[=<file>] enter System V IPC namespace -n, --net[=<file>] enter network namespace -p, --pid[=<file>] enter pid namespace -C, --cgroup[=<file>] enter cgroup namespace -U, --user[=<file>] enter user namespace -S, --setuid <uid> set uid in entered namespace -G, --setgid <gid> set gid in entered namespace --preserve-credentials do not touch uids or gids -r, --root[=<dir>] set the root directory -w, --wd[=<dir>] set the working directory -F, --no-fork do not fork before exec'ing <program> -Z, --follow-context set SELinux context according to --target PID -h, --help display this help -V, --version display version
- 感谢你赐予我前进的力量