nsenter命令簡介
nsenter命令是一個可以在指定進程的命令空間下運行指定程序的命令。它位於util-linux包中。
用途
一個最典型的用途就是進入容器的網絡命令空間。相當多的容器為了輕量級,是不包含較為基礎的命令的,比如說 ip address,ping,telnet,ss,tcpdump 等等命令,這就給調試容器網絡帶來相當大的困擾:只能通過 docker inspect ContainerID 命令獲取到容器IP,以及無法測試和其他網絡的連通性。這時就可以使用nsenter命令僅進入該容器的網絡命名空間,使用宿主機的命令調試容器網絡。此外,nsenter也可以進入 mnt, uts, ipc, pid, user 命令空間,以及指定根目錄和工作目錄。
原理
namespace
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
Linux的每個進程都具有命名空間,可以在/proc/PID/ns目錄中看到命名空間的文件描述符。
使用
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]:設置工作目錄 如果沒有給出program,則默認執行$SHELL。
示例:
這里我隨便運行了一個容器並查看容器pid
[root@Wshile ~]# docker inspect -f {{.State.Pid}} 091f114de06e
5645
然后,使用nsenter命令進入該容器的網絡命令空間:
[root@Wshile ~]# nsenter -n -t5645 [root@Wshile ~]# 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中,在得到容器pid之前還需獲取容器的ID,可以使用如下命令獲取:
[root@Wshile test]# kubectl get pod test -oyaml|grep containerID - containerID: docker://cf0873782d587dbca6aa32f49605229da3748600a9926e85b36916141597ec85