调试错误时,我发现一个进程(来自容器)在状态tcp: out of memory
上有很多连接,即当我猫时CLOSE_WAIT
08
/proc/XXX/net/tcp
但 netstat 或 ss 都没有显示这些泄漏的连接。
133:0E03540A:9D9C 804CC2AD:01BB 08 00000000:00059D7A 00:00000000 00000000 0 0 316215 1 ffff8f677201df00 20 4 0 10 -1
134: 40A:8316 80A7E940:01BB 08 00000000:00000000 00:00000000 00000000 0 0 255647 1 ffff8f67c9592600 20 4 1 10 -1
135:0E03540A:8874 808C7D4A:01BB 08 00000000:00037EED 00:00000000 00000000 0 0 331603 1 ffff8f68e37a7200 20 4 1 10 -1 13
6: 0E03540A:E226 804CC2AD:01BB 08 00000000:0005E30B 00:00000000 00000000 0 0 215782 1 ffff8f67bd1edf00 20 4 0 10 -1
137:0E03540A:DAEC 804CC2AD:01BB 08 00000000:0005B41A 00:00000000 00000000 0 0 216048 1 ffff8f67daf9af8 0 20 4 0 10 -1 138:0E03540A
:9AEA 8005FB8E:01BB 08 00000000:000D6360 00:00000000 00000000 0 0 243082 1 ffff8f67db637200 20 4 30 10 -1
140: 0E03540A:BAE4 800FB16C:01BB 08 00000000:000D8432 00:00000000 00000000 0 0 245062 1 ffff8f67640f8980 20 4 1 10 -1
141:0E03540A:9754 804CC2AD:01BB 08 00000000: 00003186 00:00000000 00000000 0 0 298890 1 ffff8f676e1a5f00 20 4 1 10 -1
142: 0E03540A:C6FC 800FB16C:01BB 08 00000000:000658C9 0 0:00000000 00000000 0 0 299343 1 ffff8f68dcef5580 20 4 0 10 -1
143: 0E03540A:CB24 804CC2AD: 01BB 08 00000000:0005BBB4 00:00000000 00000000 0 0 316285 1 ffff8f6772019300 20 4 1 10 -1
144:0E03540A:8204 80A7E940:01BB 08 00 000000:0005DD3A 00:00000000 00000000 0 0 217390 1 ffff8f67dbc20000 20 4 0 10 -1
145: 0E03540A :8BC8 80016642:01BB 08 00000000:00059847 00:00000000 00000000 0 0 275095 1 ffff8f67b6d7a600 20 4 1 10 -1
146:0E03540A:C612 800 5FB8E:01BB 08 00000000:0003EC48 00:00000000 00000000 0 0 252281 1 ffff8f67cf014280 20 4 1 10 - 1
为什么 netstat 没有显示这些连接以及如何在不深入了解每个进程详细信息的情况下获取它们?
答案1
如果您从主机查看此内容,则您位于初始网络命名空间而不是容器的网络命名空间中:看不到这些连接或状态,因为它们不是由初始网络命名空间的网络堆栈处理的。当跟踪 中进程目录中的条目时/proc
,该条目是从进程的角度看到的...有时,因此有时会显示相关的命名空间信息,但工具并不意味着使用此信息。
因此,您必须首先切换到所研究进程的网络名称空间。
就这么简单(使用根用户):
nsenter -t XXX --net -- ss -tn
或者查找进程(如初始 pid 命名空间中所示,而不是容器的):
nsenter -t XXX --net -- ss -tnp state CLOSE-WAIT
通常,人们会按 Pod(或其他技术中的容器)而不是按进程进行搜索。各种容器技术允许从容器名称检索 PID 进程(例如: LXC'slxc-info -Hp -n containername
或 Docker's docker inspect --format '{{.State.Pid}}' containername
),但我不知道如果后端不是 Docker,Kubernetes 是否以及如何提供此信息。
另外,对于某些工具来说,这比这要困难一些,因为例如/sys
应该重新安装以/sys/class/net
反映新的网络命名空间的接口视图:现在将有两个命名空间需要更改:目标进程的命名空间和临时安装命名空间(以免损坏初始,也不使用可能没有所需命令的目标)。无论如何,该ss
命令纯粹在套接字上运行,不需要这个。
例如,过时的brctl show
命令需要它才能正常工作:
nsenter -t XXX --net -- unshare --mount -- sh -c 'mount -t sysfs sysfs /sys; brctl show'