在调查容器中的一些 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
为每个Kubernetes
pod 创建的容器——它是创建网络命名空间的容器。
尝试通过运行以下命令查看 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
iproute
更通用的方法是使用
nsenter(1)
.一种方法是使用类似以下的东西,当需要运行临时的东西时,不一定支持
unshare(2)
/setns(2)
内置。如果您想使用
ss
以下方法查看特定的容器命名空间:找出容器进程的PID
ps aux
或者ps -ef
应该给你答案创建以下符号链接
如果您有最新版本的lsns,则可以使用选项-n -o NSFS将命名空间 inode 转换为网络子系统使用的 ID。
例如,假设您有 net NS 4026536974。您可以运行:
或多合一: