我们知道docker容器使用namespace实现资源隔离。
我们知道,有很多image内部是没有bash的,所以我们docker exec是无法进入容器的,此时如果还想看一下容器内的情况,其实只需要想办法加入到容器对应的namespace就可以了。
我们使用nsenter工具即可实现,该工具启动后会将自己加入到指定的namespace中,然后exec执行我们指定的程序(通常就是bash)。
找到容器的进程ID
首先确定你要进入哪个容器,找到它的容器ID。
然后docker inspect找到这个容器的1号进程ID:
执行:docker inspect 容器ID
“State”: {
“Status”: “running”,
“Running”: true,
“Paused”: false,
“Restarting”: false,
“OOMKilled”: false,
“Dead”: false,
“Pid”: 9991,
“ExitCode”: 0,
“Error”: “”,
“StartedAt”: “2020-04-17T06:56:24.208483135Z”,
“FinishedAt”: “0001-01-01T00:00:00Z”
},
那么9991就是这个容器的进程ID,我们要加入的就是这个进程所在的namespace。
加入namespace
这就需要使用nsenter(全称namespace enter)工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
(base) root@debian:~/k8s# 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 |
nsenter -t 指定加入哪个进程的namespace,而namespace其实有很多种。
因为容器内没有bash程序,因此通常我们不会使用-a加入所有namespace(因为它包含了mount namespace),而是使用啥就传啥。
比如,我们加入network namespace,那么就这样:
nsenter -t 9991 -n bash
实际是运行了宿主机的bash程序,并加入了9991进程的network namespace,此时可以统计一下容器内有哪些网络端口:
1 2 3 4 5 6 7 8 9 10 11 |
(base) root@debian:/home/work# nsenter -t 9991 -n bash (base) root@debian:/home/work# netstat -tanlp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 172.17.0.7:43262 10.96.0.1:443 ESTABLISHED 9991/dashboard tcp6 0 0 :::9090 :::* LISTEN 9991/dashboard tcp6 0 0 172.17.0.7:9090 172.17.0.1:8090 TIME_WAIT - tcp6 0 0 172.17.0.7:9090 172.17.0.1:8030 TIME_WAIT - tcp6 0 0 172.17.0.7:9090 172.17.0.1:7970 TIME_WAIT - tcp6 0 0 172.17.0.7:9090 172.17.0.1:7910 TIME_WAIT - tcp6 0 0 172.17.0.7:9090 172.17.0.1:8150 TIME_WAIT - |
可见,现在只能看到容器内的端口了。
参考
如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~
