Контейнер Docker в сети bridge не может получить доступ к nodeport’ам, обслуживаемым локальным узлом K8s.

Вопрос или проблема

Полное раскрытие, я пытался задать этот вопрос здесь, и он был закрыт как не по теме, но я надеюсь, что здесь он будет по теме.

Я углубился в эту проблему и до сих пор ничего не выяснил, поэтому надеюсь, что есть какие-то гуру 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.

Пример

Рассмотрим различные аспекты, которые следует принимать во внимание:

  1. Сетевая изоляция: Bridge-сеть Docker по своей архитектуре предоставляет уникальные подсети для каждого контейнера, что делает непосредственную маршрутизацию в другие сети (включая те, которые управляются Cilium для Kubernetes) нелегкой задачей. То есть, трафик, что идет от контейнера Docker, должен быть корректно маршрутизирован к нужной сети на host-уровне.

  2. Cilium и IP маршрутизация: Cilium предоставляет безопасное управление сетью и применяется IP маршрутизация и BPF программы для управления трафиком. Без корректного знания маршрутов, используемых Cilium, битые пакеты от контейнеров Docker могут игнорироваться или отклоняться.

  3. Конфликты портов и фильтрация: Если порт 32000 открыт для NodePort на хосте, то локальные правила firewall, установленные системой, например через iptables, могут мешать передаче данных от Docker к Kubernetes-сетям.

Применение

Для разрешения этой ситуации следует изучить несколько возможных стратегий и предложений:

  1. Проверка маршрутов: Убедитесь, что маршруты от сети Docker до сети NodePort известны и правильно настроены. Используйте такие команды как ip route для проверки текущих маршрутов и cilium bpf для контроля BPF программ Cilium, которые могут влиять на маршрутизацию.

  2. Настройка портов и iptables: Несмотря на то, что firewall отключен, проверьте все правила и цепочки через iptables; они могут все еще приниматься в учет другими компонентами. Наиболее уязвимой частью может быть POSTROUTING или INPUT, где пакеты могут быть изменены или отклонены.

  3. Просмотр и логирование через Cilium: Убедитесь, что все Cilium политики и правила сетевой безопасности корректно настроены и позволяют нужный трафик. Используйте cilium monitor или hubble для видимости того, как проходят пакеты, чтобы понять, где может блокироваться соединение.

  4. Пересмотр сетевой архитектуры или использование host-сети для контейнеров Docker: Временно перенастройте Docker-контейнеры на работу через host-сеть, чтобы обойти NAT и bridge изоляцию, и проверьте, доступен ли NodePort. Это может подтвердить, что проблема связана именно с bridge изоляцией и маршрутизацией.

  5. Документация и поддержка: Обратитесь к документации Cilium, т.к. без kube-proxy, маршрутизация и правила обработки пакетов могут отличаться. Также, не стесняйтесь обращаться к поддержке Cilium или сообществам разработчиков RKE2.

Заключение

Данная ситуация — типичное сочетание сложностей, связанных с разворачиванием и управлением разнородными сетевыми инфраструктурами. Понимание сетевых маршрутов и взаимодействие с такими компонентами как Cilium позволит вам настроить необходимые соединения и обеспечит успешную работу ваших контейнеров и сервисов в общей экосистеме.

Оцените материал
Добавить комментарий

Капча загружается...