背景
nsenter 是一个可以用来进入到目标程序所在 Namespace 中运行命令的工具,一般常用于在宿主机上调试容器中运行的程序。
基本用法
进入到网络 ns
用途:在主机上抓容器网卡的包
NAME=<pod_name>; PID=`docker ps | grep $NAME | grep pause | awk '{print $1}' | xargs docker inspect -f {{.State.Pid}}`; nsenter -n --target $PID
安装
nsenter 位于 util-linux 包中,一般常用的 Linux 发行版都已经默认安装。如果你的系统没有安装,可以使用以下命令进行安装:
yum install util-linux
用法
一个比较典型的用途就是进入容器的网络命名空间。通常容器为了轻量级,大多都是不包含较为基础网络管理调试工具,比如:ip、ping、telnet、ss、tcpdump 等命令,给调试容器内网络带来相当大的困扰。
nsenter 命令可以很方便的进入指定容器的网络命名空间,使用宿主机的命令调试容器网络。除此以外,nsenter 还可以进入 mnt、uts、ipc、pid、user 等命名空间,以及指定根目录和工作目录。
语法
nsenter [options] [program [arguments]]options:-t, --target pid:指定被进入命名空间的目标进程的pid-m, --mount[=file]:进入mount命令空间。如果指定了file,则进入file的命令空间-u, --uts[=file]:进入uts命令空间。如果指定了file,则进入file的命令空间-i, --ipc[=file]:进入ipc命令空间。如果指定了file,则进入file的命令空间-n, --net[=file]:进入net命令空间。如果指定了file,则进入file的命令空间-p, --pid[=file]:进入pid命令空间。如果指定了file,则进入file的命令空间-U, --user[=file]:进入user命令空间。如果指定了file,则进入file的命令空间-G, --setgid gid:设置运行程序的gid-S, --setuid uid:设置运行程序的uid-r, --root[=directory]:设置根目录-w, --wd[=directory]:设置工作目录
示例:
运行一个nginx容器,查看该容器的pid:
docker inspect -f {{.State.Pid}} nginx54325# 进入net命令空间nsenter -n -t 54325ip addr# 进入容器nsenter -m -u -i -n -p -tnsenter --target 54325 --mount --uts --ipc --net --pidroot@164f44ff58d1:/bin##在Kubernetes中,在得到容器pid之前还需获取容器的ID,可以使用如下命令获取:kubectl get pod test -oyaml|grep containerID - containerID: docker://cf0873782d587dbca6aa32f49605229da3748600a9926e85b36916141597ec85#或者更为精确地获取containerID:kubectl get pod test -o template --template='{{range .status.containerStatuses}}{{.containerID}}{{end}}'docker://cf0873782d587dbca6aa32f49605229da3748600a9926e85b36916141597ec85
原理
namespace是Linux中一些进程的属性的作用域,使用命名空间,可以隔离不同的进程。
Linux在不断的添加命名空间,目前有:
mount:挂载命名空间,使进程有一个独立的挂载文件系统,始于Linux 2.4.19
ipc:ipc命名空间,使进程有一个独立的ipc,包括消息队列,共享内存和信号量,始于Linux 2.6.19
uts:uts命名空间,使进程有一个独立的hostname和domainname,始于Linux 2.6.19
net:network命令空间,使进程有一个独立的网络栈,始于Linux 2.6.24
pid:pid命名空间,使进程有一个独立的pid空间,始于Linux 2.6.24
user:user命名空间,是进程有一个独立的user空间,始于Linux 2.6.23,结束于Linux 3.8
cgroup:cgroup命名空间,使进程有一个独立的cgroup控制组,始于Linux 4.6
与 kubectl exec/attach (docker exec)对比
kubectl exec/attach 原理不同,因此可以从本节点访问其他节点容器;而 nsenter 只能访问当前主机的命名空间;
很多时候容器中没有安装相关的程序,而通过 nsenter 我们可以使用主机上安装的程序,但是指定命名空间,为我们调试程序带来了方便。