nsenter 是一个可以用来进入到目标程序所在 Namespace 中运行命令的工具,一般常用于在宿主机上调试容器中运行的程序。
nsenter 安装
nsenter 位于 util-linux 包中,一般常用的 Linux 发行版都已经默认安装。如果你的系统没有安装,可以使用以下命令进行安装:
nsenter 用途
一个比较典型的用途就是进入容器的网络命名空间。通常容器为了轻量级,大多都是不包含较为基础网络管理调试工具,比如:ip、ping、telnet、ss、tcpdump 等命令,给调试容器内网络带来相当大的困扰。
nsenter 命令可以很方便的进入指定容器的网络命名空间,使用宿主机的命令调试容器网络。
除此以外,nsenter 还可以进入 mnt、uts、ipc、pid、user 等命名空间,以及指定根目录和工作目录。
nsenter 用法
首先看下 nsenter 命令的语法:
$ yum install util-linux
如果没有给出 program,则默认执行 $SHELL。最常用的参数组合是:
$ nsenter [options] [program [arguments]]
options:
-a, --all enter all namespaces of the target process by the default /proc/[pid]/ns/* namespace paths.
-m, --mount[=]:进入 mount 命令空间。如果指定了 file,则进入 file 的命名空间
-u, --uts[=]:进入 UTS 命名空间。如果指定了 file,则进入 file 的命名空间
-i, --ipc[=]:进入 System V IPC 命名空间。如果指定了 file,则进入 file 的命名空间
-n, --net[=]:进入 net 命名空间。如果指定了 file,则进入 file 的命名空间
-p, --pid[=:进入 pid 命名空间。如果指定了 file,则进入 file 的命名空间
-U, --user[=:进入 user 命名空间。如果指定了 file,则进入 file 的命名空间
-t, --target # 指定被进入命名空间的目标进程的 pid
-G, --setgid gid:设置运行程序的 GID
-S, --setuid uid:设置运行程序的 UID
-r, --root[=directory]:设置根目录
-w, --wd[=directory]:设置工作目录
nsenter 使用实例
进入 docker 容器的 namespace 中运行指定程序
使用 nsenter 进入 docker 容器的 namespace 是非常简单的,通常你只需要以下两步:
$ nsenter -a -t
$ nsenter -m -u -i -n -p -t
下面我们来看几个实例:
进入指定程序所在的所有命名空间
$ PID=$(docker inspect --format {{.State.Pid}}
$ nsenter -m -u -i -n -p -t $PID
进入指定程序所在的网络命名空间
运行一个 Nginx 容器,查看该容器的 Pid:
$ 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
然后,使用 nsenter 命令进入该容器的网络命令空间:
$ docker inspect -f {{.State.Pid}} nginx
进入 Kubernetes 容器的 namespace 中运行指定程序
如果是在 Kubernetes 中,在得到容器 Pid 之前,你还需先获取容器的 ID,可以使用如下命令获取:
$ nsenter -n -t5645
$ ip addr
1: lo:
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:
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
或者更为精确地获取 containerID:
$ kubectl get pod nginx -n web -o yaml|grep containerID
参考文档