如何在特定网络命名空间中使用 ss

如何在特定网络命名空间中使用 ss

在调查容器中的一些 TCP 网络问题时,我尝试使用它ss来窥视容器网络 TCP 堆栈。

我们在 AWS 中运行 Amazon Linux:

# uname -a
Linux 4.14.173-137.229.amzn2.x86_64 #1 SMP Wed Apr 1 18:06:08 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

ss有以下 CLI 开关:

       -N NSNAME, --net=NSNAME
              Switch to the specified network namespace name.

lsns给出以下输出:

# lsns | grep net
4026531993 net       225     1 root      /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026532284 net         2 26244 root      /pause

这是pause为每个 pod 创建的容器Kubernetes——它是创建网络命名空间的容器。

尝试通过运行以下命令来窥视 pod 网络命名空间ss

# ss -tp -N 4026532284
Cannot open network namespace "4026532284": No such file or directory

有趣的是 ip netns list没有返回任何网络命名空间:

# ip netns list
#

有没有什么方法可以从根网络命名空间(即 netns 1)查看 K8s pod 网络命名空间?

# ss --version
ss utility, iproute2-ss180129

# lsns --version
lsns from util-linux 2.30.2

# rpm -qi iproute
Name        : iproute
Version     : 4.15.0
Release     : 1.amzn2.0.4
Architecture: x86_64
Install Date: Sat 07 Mar 2020 03:42:24 AM UTC
Group       : Applications/System
Size        : 1321292
License     : GPLv2+ and Public Domain
Signature   : RSA/SHA256, Fri 21 Feb 2020 09:00:29 PM UTC, Key ID 11cf1f95c87f5b1a
Source RPM  : iproute-4.15.0-1.amzn2.0.4.src.rpm
Build Date  : Fri 21 Feb 2020 07:56:50 PM UTC
Build Host  : build.amazon.com
Relocations : (not relocatable)
Packager    : Amazon Linux
Vendor      : Amazon Linux
URL         : http://kernel.org/pub/linux/utils/net/iproute2/
Summary     : Advanced IP routing and network device configuration tools

更新时间:2020 年 12 月 1 日星期二 11:35:39 UTC

经过一番挣扎之后,我最终决定strace这么做。

事实证明ss它是一个很棒的工具,但是当与容器一起使用时,它就有点不尽如人意了,但我觉得其中涉及的“罪魁祸首”不止一个。

ss不去查找创建网络命名空间的进程的实际 PID,而是直接去检查/var/run/netns

openat(AT_FDCWD, "/var/run/netns/4026532284", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
write(2, "Cannot open network namespace \"4"..., 70Cannot open network namespace "4026532284": No such file or directory
) = 70

现在,我怀疑这是由于iproute包的创建方式network namespaces,即考虑到包ss附带的内容,对网络命名空间的iproute假设ip是:“嘿,所有网络 ns 都应该在目录中找到/var/run/netns,因为,为什么不呢,而且这将使iproute开发人员的生活更轻松,或者其他什么。

ss事实证明,这是iproute对现代容器工具和互操作性缺乏“共识”的错误假设iproute,但它在某种程度上解释了

ip netns list

因此,创建网络命名空间的方式ip(以便可以通过 检查ss)显然与 kubernetes 等创建它们的方式不匹配,从而使得iproute软件包实用程序在总体上几乎毫无用处。

答案1

更通用的方法是使用nsenter(1)

nsenter -t ${PID_FOO} -muni ss -tpi

当需要运行临时的东西时,可以使用以下方法,而这些东西不一定支持unshare(2)/setns(2)内置。

docker run -it --rm --security-opt=seccomp:unconfined \
                    --security-opt=apparmor:unconfined \
                    --privileged --pid=host --userns=host \
debian:jessie@sha256:51cd80bb935b76fbbf49640750736abc63ab7084d5331e198326b20063e7f13c \
nsenter -t ${PID_FOO} -m -u -n -i -F ss -tpi

答案2

如果你想使用ss它来查看特定的容器命名空间,你可以这样做:

  1. 找出容器进程的PID ps aux或者ps -ef应该给你答案

  2. 创建以下符号链接

ln -s /proc/PID/ns/net /var/run/netns/mycontainer
  1. 利润
ss -tpi -N mycontainer

答案3

如果你有最新版本的lsns,您可以使用选项-n -o NSFS将命名空间 inode 转换为网络子系统使用的 ID。

例如,假设您的网络 NS 为 4026536974。您可以运行:

sh-4.4# lsns --version
lsns from util-linux 2.32.1
sh-4.4# lsns -n -o NSFS 4026536974 | sort -u                                                                                                                                                                                                 
/run/netns/d0912eba-0fae-425c-94ba-cf270aa23c93
sh-4.4# basename /run/netns/d0912eba-0fae-425c-94ba-cf270aa23c93                                                                                                                                                                             
d0912eba-0fae-425c-94ba-cf270aa23c93
sh-4.4# ss -nltp -N d0912eba-0fae-425c-94ba-cf270aa23c93 | head -2                                                                                                                                                                           
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port                                                                                    
LISTEN    0         128                0.0.0.0:5000             0.0.0.0:*        users:(("nginx",pid=874035,fd=5),("nginx",pid=874028,fd=5))                    
sh-4.4# 

或者全部合为一体:

sh-4.4# lsns -n -o NSFS 4026536974 | sort -u | xargs -rn1 basename | xargs -rn1 ss -nltp -N | head -2                                                                                                                                        
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port                                                                                    
LISTEN    0         128                0.0.0.0:5000             0.0.0.0:*        users:(("nginx",pid=874035,fd=5),("nginx",pid=874028,fd=5))                    
sh-4.4# 

相关内容