
Исследуя некоторые проблемы TCP-сети в контейнерах, я попытался ss
заглянуть в стек TCP-сети контейнера.
Мы используем Amazon Linux в AWS:
# 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, запустив ss
:
# ss -tp -N 4026532284
Cannot open network namespace "4026532284": No such file or directory
Интересно, что ip netns list
не возвращает никаких сетевых пространств имен:
# ip netns list
#
Есть ли способ заглянуть в сетевые пространства имен модуля K8s из корневого сетевого пространства имен, т. е. из netns 1?
# 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
Обновление: Вт Дек 1 11:35:39 UTC 2020
После некоторой борьбы я наконец решился на 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
Подход, который можно использовать, заключается в использовании чего-то вроде следующего, когда необходимо запустить adhoc-вещи, которые не обязательно поддерживаются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, вы можете использовать опции-н -о NSFSдля преобразования индексного дескриптора пространства имен в идентификатор, используемый сетевой подсистемой.
Например, предположим, что у вас есть net 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#