
在調查容器中的一些 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
更新: UTC 2020 年 12 月 1 日星期二 11:35:39
經過一番掙扎,我終於決定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
檢視特定容器名稱空間,請執行下列操作:
找出容器進程的PID
ps aux
或ps -ef
應該給你答案建立以下符號連結
ln -s /proc/PID/ns/net /var/run/netns/mycontainer
- 利潤
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#