容器中使用tcpdump抓包
参数
复制
容器内没有tcdump、route、ifconfig等网络命令,给我们网络调试、排查问题带来了很大的困难。我们知道,容器有自已的网络命名空间,所以我们只需要进入到容器的网络命名空间,再利用主机上的命令进行调试就可以了。
1.运行一个nginx容器
1 | # 通过宿主机的8000端口映射到容器的80端口$ docker run -d -p 8000:80 nginx:1.26.2 nginx |
2.找到容器中PID为1的进程在宿主机上对应的PID
1 | $ docker inspect -f {{.State.Pid}} nginx |
我们可以在宿主机上通过ps命令,确认4439进程就是对应我们容器中运行的nginx进程:
3.使用nsenter命令进入容器网络命名空间,并抓包
1 | # 进入到进程号为4439的网络命名空间$ nsenter -t 4439 -n |
然后,我们可以使用ifconfig命令查看该网络命名空间下的网络设备信息(这跟我们进入容器执行ifconfig命令看到的是一致的):
我们也可以通过以下命令确认容器的ip就是172.17.0.3:
1 | $ docker inspect -f {{.NetworkSettings.IPAddress}} nginx |
最后我们就可以运行tcpdump命令进行抓包了,在容器的网络命名空间中捕获80端口的流量,然后访问宿主机的8000端口,即可抓取到相应的网络报文了:
以上就和我们进入容器运行tcpdump命令抓取报文效果一样。
如果是在kubernetes中,我们该如何找到Pod中对应容器的网络命令空间呢?
1.启动一个 nginx Pod
1 | $ kubectl run nginx --image=nginx:1.26.2 |
确认容器running:
![图片](
2.获取Pod中的容器ID
1 | $ 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
1 | $ crictl inspect --template '{{.info.pid}}' -o go-template f79e81d5d641387306e2a583f7501ddd7c6b72d578969b65c1a0e021c00a7ed312191 |
4.使用nsenter命令进入容器网络命名空间
1 | # 进入到进程号为12191的网络命名空间$ nsenter -t 12191 -n |
接下去就可以使用tcdump、route、ifconfig等网络调试命令进行问题排查诊断了。