Вопрос или проблема
Мне нужно предоставить сервис wireguard в Kubernetes через AWS Network Load Balancer.
Load Balancer не будет направлять трафик на мой pod с wireguard, пока не пройдут проверки работоспособности. Поскольку AWS Load Balancers не поддерживают проверки работоспособности UDP, а wireguard работает на UDP, я прикрепил простой TCP-сервис к pod’у с wireguard, но он недоступен и, следовательно, проверки работоспособности не проходят.
Вот соответствующий фрагмент спецификации деплоймента в yaml.
spec:
containers:
- name: "wireguard"
image: "linuxserver/wireguard:latest"
ports:
- containerPort: 51820
protocol: UDP
securityContext:
privileged: true
capabilities:
add:
- NET_ADMIN
- name: healthcheck
image: istio/tcp-echo-server:latest
imagePullPolicy: IfNotPresent
args: [ "9000", "hello" ]
ports:
- containerPort: 9000
Если я исключу контейнер wireguard или закомментирую часть NET_ADMIN, чтобы убедиться, что конфигурация сети не изменилась, я смогу успешно достичь pod с проверкой работоспособности, запустив, например, следующее:
kubectl run -i --rm --restart=Never dummy --image=busybox -- sh -c "echo world | nc wireguard-service.wg-test 9000"
hello world
В логах контейнера wireguard я вижу, что выполняются следующие команды. Я подозреваю, что в конфигурации маршрутизации узла что-то изменяется, так что порт 9000 становится недоступным.
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.11.0.1/16 dev wg0
[#] ip link set mtu 1450 up dev wg0
[#] wg set wg0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] iptables-restore -n
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
[#] sysctl -w -q net.ipv4.ip_forward=1
Я пробовал добавлять iptables -A INPUT -p tcp --dport 9000 -j ACCEPT
и iptables -A FORWARD -p tcp --dport 9000 -j ACCEPT
, но безуспешно.
Что я упускаю?
Ответ или решение
Чтобы решить проблему, связанную с невозможностью прохождения healthcheck для Wireguard контейнера через вспомогательный (sidecar) контейнер в Kubernetes, необходимо рассмотреть несколько аспектов и шагов настройки. Давайте разберем теорию, пример и применение для решения этой проблемы.
Теория
Wireguard — это современный, высокопроизводительный и безопасный VPN-протокол, который работает через UDP. Однако, AWS Network Load Balancer (NLB) не поддерживает проверку состояния (healthcheck) на уровне UDP. Для обеспечения корректной работы NLB с Wireguard необходимо использовать подходы, которые предусматривают промежуточные healthcheck over TCP.
Основные проблемы возникают из-за того, что Wireguard вносит изменения в конфигурацию сети, которые могут блокировать доступ к другому контейнеру, ответственному за TCP healthcheck. Эти изменения включают добавление сетевых интерфейсов, маршрутизацию и конфигурации iptables, которые могут помешать маршрутизации трафика, предназначенного для TCP порта healthcheck контейнера.
Пример
В примерном YAML манифесте деплоймента, предоставленном в вопросе, вы уже добавили TCP healthcheck контейнер в виде sidecar. Однако конфигурация Wireguard контейнера изменяет сетевую топологию под таким образом, что делает порт 9000 недоступным.
Текущая конфигурация Wireguard контейнера может содержать следующие команды, которые вызывают проблему:
ip link add wg0 type wireguard
wg setconf wg0 /dev/fd/63
ip -4 address add 10.11.0.1/16 dev wg0
ip link set mtu 1450 up dev wg0
wg set wg0 fwmark 51820
ip -4 route add 0.0.0.0/0 dev wg0 table 51820
ip -4 rule add not fwmark 51820 table 51820
ip -4 rule add table main suppress_prefixlength 0
sysctl -q net.ipv4.conf.all.src_valid_mark=1
iptables-restore -n
iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sysctl -w -q net.ipv4.ip_forward=1
Основная проблема заключается в изменении таблиц маршрутизации и правил iptables, которые могут блокировать доступ к порту 9000.
Применение
-
Разделение сетевых пространств: Рассмотрите возможность использования Network Namespaces или сетевого изолятора, чтобы убедиться, что изменения, которые Wireguard приносит в сетевые настройки, изолированы и не влияют на другие контейнеры.
-
Настройка iptables:
- Проверьте и измените правила iptables, чтобы обеспечить маршрутизацию трафика к TCP порту.
- Попробуйте добавить следующие правила:
iptables -A PREROUTING -t mangle -p tcp --dport 9000 -j MARK --set-mark 51820 iptables -A OUTPUT -t mangle -p tcp --sport 9000 -j MARK --set-mark 51820 iptables -A INPUT -p tcp --dport 9000 -j ACCEPT
-
Проверка маршрутизации: Убедитесь, что правило
ip -4 rule add table main suppress_prefixlength 0
действительно необходимо. Оно может блокировать весь внешнюю маршрутизацию для других портов. -
Использование Host Network: Вместо использования под-сетей Kubernetes, настройте Wireguard контейнер на использование Host Network. Это может снизить количество изменений, необходимых в конфигурации сетевого стека.
-
Отладка сетевых проблем: Используйте инструменты, такие как
tcpdump
илиiptables-save
для подробного анализа движения пакетов и идентификации блокирующих правил. -
Обновление конфигурации Load Balancer: Проверьте возможность использования другого механизма healthcheck, например HTTP код возврата от пинг-сервера, который будет проксироовать запросы на порт 9000.
-
Логирование и мониторинг: Настройте логирование, чтобы детально отслеживать изменения и прохождение пакетов через iptables, позволяющее определить точные места, где происходит блокировка.
Соблюдение этих рекомендаций может помочь вам в корректной настройке контейнеров в Kubernetes и обеспечении доступности вашего Wireguard сервиса через AWS NLB. Если проблема сохраняется, может потребоваться более детальный анализ сетевых конфигураций и взаимодействий контейнеров.