nsenter 是一个可以用来进入到目标程序所在 Namespace 中运行命令的工具,一般常用于在宿主机上调试容器中运行的程序。
nsenter 安装
nsenter 位于 util-linux 包中,一般常用的 Linux 发行版都已经默认安装。如果你的系统没有安装,可以使用以下命令进行安装:
1 $ yum install util-linux
nsenter 用途
一个比较典型的用途就是进入容器的网络命名空间。通常容器为了轻量级,大多都是不包含较为基础网络管理调试工具,比如:ip、ping、telnet、ss、tcpdump 等命令,给调试容器内网络带来相当大的困扰。
nsenter 命令可以很方便的进入指定容器的网络命名空间,使用宿主机的命令调试容器网络。
除此以外,nsenter 还可以进入 mnt、uts、ipc、pid、user 等命名空间,以及指定根目录和工作目录。
nsenter 用法
首先看下 nsenter 命令的语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ nsenter [options] [program [arguments]] options: -a, --all enter all namespaces of the target process by the default /proc/[pid]/ns/* namespace paths. -m, --mount[=<file>]:进入 mount 命令空间。如果指定了 file,则进入 file 的命名空间 -u, --uts[=<file>]:进入 UTS 命名空间。如果指定了 file,则进入 file 的命名空间 -i, --ipc[=<file>]:进入 System V IPC 命名空间。如果指定了 file,则进入 file 的命名空间 -n, --net[=<file>]:进入 net 命名空间。如果指定了 file,则进入 file 的命名空间 -p, --pid[=<file>:进入 pid 命名空间。如果指定了 file,则进入 file 的命名空间 -U, --user[=<file>:进入 user 命名空间。如果指定了 file,则进入 file 的命名空间 -t, --target <pid> # 指定被进入命名空间的目标进程的 pid -G, --setgid gid:设置运行程序的 GID -S, --setuid uid:设置运行程序的 UID -r, --root[=directory]:设置根目录 -w, --wd[=directory]:设置工作目录
如果没有给出 program,则默认执行 $SHELL
。最常用的参数组合是:
1 2 3 # 有的版本不一定有 -a 这个参数 $ nsenter -a -t <pid> <command> $ nsenter -m -u -i -n -p -t <pid> <command>
nsenter 使用实例
进入 docker 容器的 namespace 中运行指定程序
使用 nsenter 进入 docker 容器的 namespace 是非常简单的,通常你只需要以下两步:
1 2 3 4 # 获取相应的 Dokcer 容器的 PID $ PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>) # 使用相应参数进入程序所在的不同 NameSpace $ nsenter -m -u -i -n -p -t $PID <command>
下面我们来看几个实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ docker run --rm --name test -d busybox sleep 10000 8115009baccc53a2a5f6dfff642e0d8ab1dfb95dde473d14fb9a06ce4e89364c $ docker ps |grep busybox 8115009baccc busybox "sleep 10000" 9 seconds ago Up 8 seconds test $ PID=$(docker inspect --format {{.State.Pid}} 8115009baccc) $ nsenter -m -u -i -n -p -t $PID ps aux PID USER TIME COMMAND 1 root 0:00 sleep 10000 7 root 0:00 ps aux $ nsenter -m -u -i -n -p -t $PID hostname 8115009baccc
运行一个 Nginx 容器,查看该容器的 Pid:
1 2 $ docker inspect -f {{.State.Pid}} nginx 5645
然后,使用 nsenter 命令进入该容器的网络命令空间:
1 2 3 4 5 6 7 8 9 10 $ nsenter -n -t5645 $ ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
进入 Kubernetes 容器的 namespace 中运行指定程序
如果是在 Kubernetes 中,在得到容器 Pid 之前,你还需先获取容器的 ID,可以使用如下命令获取:
1 2 $ kubectl get pod nginx -n web -o yaml|grep containerID - containerID: docker://cf0873782d587dbca6aa32f49605229da3748600a9926e85b36916141597ec85
或者更为精确地获取 containerID:
1 2 $ kubectl get pod nginx -n web -o template --template='{{range .status.containerStatuses}}{{.containerID}}{{end}}' docker://cf0873782d587dbca6aa32f49605229da3748600a9926e85b36916141597ec85
其它的步骤就和前面进入 Docker 容器的命名空间类似了。
参考文档
https://www.googgle.com
https://staight.github.io/2019/09/23/nsenter命令简介/
https://mozillazg.com/2020/04/nsenter-usage.html