Networking

如何在特定的網路命名空間中使用 ss

  • June 3, 2021

在調查容器中的一些 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為每個Kubernetespod 創建的容器——它是創建網路命名空間的容器。

嘗試通過執行以下命令查看 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).

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

引用自:https://serverfault.com/questions/1044516