容器中没有tcpdump命令我们该怎么抓包?
十一月 05, 2024 [虚拟化与容器] #obsidian #容器 #网络容器中没有tcpdump命令我们该怎么抓包?
容器内没有tcdump、route、ifconfig等网络命令,给我们网络调试、排查问题带来了很大的困难。我们知道,容器有自已的网络命名空间,所以我们只需要进入到容器的网络命名空间,再利用主机上的命令进行调试就可以了。
1.运行一个nginx容器
# 通过宿主机的8000端口映射到容器的80端口
$ docker run -d -p 8000:80 nginx:1.26.2 nginx
2.找到容器中PID为1的进程在宿主机上对应的PID
$ docker inspect -f {{.State.Pid}} nginx
我们可以在宿主机上通过ps命令,确认4439进程就是对应我们容器中运行的nginx进程:

3.使用nsenter命令进入容器网络命名空间,并抓包
# 进入到进程号为4439的网络命名空间
$ nsenter -t 4439 -n
然后,我们可以使用ifconfig命令查看该网络命名空间下的网络设备信息(这跟我们进入容器执行**ifconfig**命令看到的是一致的):

我们也可以通过以下命令确认容器的ip就是172.17.0.3:
$ docker inspect -f {{.NetworkSettings.IPAddress}} nginx

最后我们就可以运行tcpdump命令进行抓包了,在容器的网络命名空间中捕获80端口的流量,然后访问宿主机的8000端口,即可抓取到相应的网络报文了:

以上就和我们进入容器运行tcpdump命令抓取报文效果一样。
如果是在kubernetes中,我们该如何找到Pod中对应容器的网络命令空间呢?
1.启动一个 nginx Pod
$ kubectl run nginx --image=nginx:1.26.2
确认容器running:

2.获取Pod中的容器ID
$ kubectl get pods nginx -o jsonpath='{.status.containerStatuses[0].containerID}'
containerd://f79e81d5d641387306e2a583f7501ddd7c6b72d578969b65c1a0e021c00a7ed3
案例中nginx Pod只有一个名称为nginx的container,如果Pod中有多个container,使用
containerStatuses[0]选取Pod中第一个container的containerID也没有关系,因为在k8s里,Pod中所有container是共享同一个网络命名空间的;
3.获取容器中PID为1的进程在宿主机上对应的进程PID
$ crictl inspect --template '{{.info.pid}}' -o go-template f79e81d5d641387306e2a583f7501ddd7c6b72d578969b65c1a0e021c00a7ed3
12191
4.使用nsenter命令进入容器网络命名空间
# 进入到进程号为12191的网络命名空间
$ nsenter -t 12191 -n
接下去就可以使用tcdump、route、ifconfig等网络调试命令进行问题排查诊断了。