Вопрос или проблема
Полное раскрытие, я пытался задать этот вопрос здесь, и он был закрыт как не по теме, но я надеюсь, что здесь он будет по теме.
Я углубился в эту проблему и до сих пор ничего не выяснил, поэтому надеюсь, что есть какие-то гуру k8s/docker/сетевого взаимодействия, которые будут заинтересованы в углублении и помогут мне разобраться в этом.
Настройка
- Хост – Ubuntu 22.04.5 LTS
- Этот хост является одновузловым кластером K8s, а также хостом docker.
- Для K8s используется RKE2 v1.29.2+rke2r1. За сетевое взаимодействие отвечает Cilium, kube-proxy не используется.
- Для Docker – 24.0.7 (как сервер, так и клиент)
- Kasm (в данном случае создающий docker-контейнеры) 1.16.0
- IP хоста (и к чему привязан узел K8s)
192.168.H.H
Проблема: Docker-контейнеры (рабочие пространства kasm), работающие в мостовой сети, не могут получить доступ к сервисам NodePort на хосте, например, 192.168.H.H:32000
Пример tcpdump, захваченного на хосте при попытке подключения:
veth123 P ifindex 123 ma:ca:dd:re:ss:01 ethertype IPv4 172.22.0.14.60388 > 192.168.H.H.32000: Flags[S]
br123 In ifindex 456 ma:ca:dd:re:ss:01 ethertype IPv4 172.22.0.14.60388 > 192.168.H.H.32000: Flags[S]
br123 Out ifindex 456 ma:ca:dd:re:ss:02 ethertype IPv4 192.168.H.H.32000 > 172.22.0.14.60388: Flags[R.]
veth123 Out ifindex 123 ma:ca:dd:re:ss:02 ethertype IPv4 192.168.H.H.32000 > 172.22.0.14.60388: Flags[R.]
ma:ca:dd:re:ss:01
это внутренний mac контейнера (видимый в docker network inspect сетевого моста)ma:ca:dd:re:ss:02
это mac мостового устройства, связанного с сетевым мостом docker- видно, что есть активный отказ,
RST,ACK
возвращается от … чего-то…
Дополнительная информация:
- Docker-контейнеры, работающие в мостовой сети, могут получать доступ к другим вещам, размещенным на хосте (например, если я запускаю
kubectl port-forward
в pod за192.168.H.H:32000
, то я могу получить доступ к порту хоста, связанному с перенаправлением порта из docker-контейнера в мостовой сети. Или если я просто запускаюpython3 -m http.server
, я могу без проблем получить доступ к192.168.H.H:8000
). - Другие вещи на хосте (например, curl или браузер), или даже docker-контейнер, работающий в сети хоста, могут без проблем получить доступ к NodePort
192.168.H.H:32000
. - Брандмауэр отключен.
systemctl stop ufw
затемsystemctl disable ufw
- При запуске tcpdump внутри целевого контейнера (т.е. pod за NodePort
192.168.H.H:32000
) он не получает неудачные соединения, поэтому не он отправляет RST,ACK (конечно он получает успешные соединения, и их можно увидеть в выводе tcpdump).
Попытка отладки iptables
- Конечно, я знаю, что проблема похожа на проблему с iptables, поэтому я сделал следующее:
iptables -t raw -I PREROUTING 1 -p tcp --dport 32000 -j TRACE
iptables -t raw -I PREROUTING 1 -p tcp --sport 32000 -j TRACE
iptables -t raw -I OUTPUT 1 -p tcp --dport 32000 -j TRACE
iptables -t raw -I OUTPUT 1 -p tcp --sport 32000 -j TRACE
xtables-monitor --trace
- Заключение каждого трассировки пакета было «ACCEPT», и в выводе не было сообщений о отклонении или отказе (я особенно искал отклонение на основании происходящего RST,ACK).
Попытка отладки cilium
- Конечно, я знаю, что проблема также похожа на проблему с cilium, поэтому я попытался разобраться и с этой стороны.
- получил shell в pod cilium
- ни
cilium-dbg monitor
, ниhubble observe -f
и друзья, похоже, не показывали ничего, связанного с моими неудачными попытками, но, конечно, показывали вещи для успешных (тех, которые не поступают из моего docker-контейнера в мостовой сети).
Неидеально иметь смешанные решения для управления контейнерами, как у меня здесь, но я не уверен, что есть какой-либо способ обойти это в моей ситуации.
На данный момент я совершенно потерян. Буду быстро отвечать на уточняющие вопросы, если у кого-то они есть…
.
Ответ или решение
Теория
Проблема, с которой вы столкнулись, когда контейнер Docker в bridge-сети не может получить доступ к NodePort-службам локального узла Kubernetes, связана с очень тонкой взаимосвязью между сетевыми настройками Docker и Kubernetes на одном хосте. Ваша конфигурация использует RKE2 с Cilium без kube-proxy
, что налагает свои специфические сетевые особенности и ограничения. Docker bridge-сеть изолирует сетевой трафик контейнера от других сетей, включая Host и User-defined сети, но проблемой здесь является сложность настройки сетевой маршрутизации между Docker и NodePort на Kubernetes.
Пример
Рассмотрим различные аспекты, которые следует принимать во внимание:
-
Сетевая изоляция: Bridge-сеть Docker по своей архитектуре предоставляет уникальные подсети для каждого контейнера, что делает непосредственную маршрутизацию в другие сети (включая те, которые управляются Cilium для Kubernetes) нелегкой задачей. То есть, трафик, что идет от контейнера Docker, должен быть корректно маршрутизирован к нужной сети на host-уровне.
-
Cilium и IP маршрутизация: Cilium предоставляет безопасное управление сетью и применяется IP маршрутизация и BPF программы для управления трафиком. Без корректного знания маршрутов, используемых Cilium, битые пакеты от контейнеров Docker могут игнорироваться или отклоняться.
-
Конфликты портов и фильтрация: Если порт 32000 открыт для NodePort на хосте, то локальные правила firewall, установленные системой, например через iptables, могут мешать передаче данных от Docker к Kubernetes-сетям.
Применение
Для разрешения этой ситуации следует изучить несколько возможных стратегий и предложений:
-
Проверка маршрутов: Убедитесь, что маршруты от сети Docker до сети NodePort известны и правильно настроены. Используйте такие команды как
ip route
для проверки текущих маршрутов иcilium bpf
для контроля BPF программ Cilium, которые могут влиять на маршрутизацию. -
Настройка портов и iptables: Несмотря на то, что firewall отключен, проверьте все правила и цепочки через iptables; они могут все еще приниматься в учет другими компонентами. Наиболее уязвимой частью может быть POSTROUTING или INPUT, где пакеты могут быть изменены или отклонены.
-
Просмотр и логирование через Cilium: Убедитесь, что все Cilium политики и правила сетевой безопасности корректно настроены и позволяют нужный трафик. Используйте
cilium monitor
илиhubble
для видимости того, как проходят пакеты, чтобы понять, где может блокироваться соединение. -
Пересмотр сетевой архитектуры или использование host-сети для контейнеров Docker: Временно перенастройте Docker-контейнеры на работу через host-сеть, чтобы обойти NAT и bridge изоляцию, и проверьте, доступен ли NodePort. Это может подтвердить, что проблема связана именно с bridge изоляцией и маршрутизацией.
-
Документация и поддержка: Обратитесь к документации Cilium, т.к. без
kube-proxy
, маршрутизация и правила обработки пакетов могут отличаться. Также, не стесняйтесь обращаться к поддержке Cilium или сообществам разработчиков RKE2.
Заключение
Данная ситуация — типичное сочетание сложностей, связанных с разворачиванием и управлением разнородными сетевыми инфраструктурами. Понимание сетевых маршрутов и взаимодействие с такими компонентами как Cilium позволит вам настроить необходимые соединения и обеспечит успешную работу ваших контейнеров и сервисов в общей экосистеме.