У меня есть две машины, работающие на Ubuntu 18.04 с установленной на них Docker версии 18.09.9. Я установил ройный кластер, в котором узел-менеджер объявляет свой общедоступный IP-адрес, а рабочий узел - свой частный IP-адрес:
// On manager
docker swarm init --advertise-addr INSTANCE_PUBLIC_IP
// On worker
docker swarm join --advertise-addr INSTANCE_PRIVATE_IP --token XXXXXX MANAGER_PUBLIC_IP:2377
Две машины работают в одной частной сети, и менеджер может подключаться к частному IP-адресу рабочего. Рой в основном работает, я могу развертывать службы, видеть входящую сеть на обоих узлах и т.д., но когда я развертываю службу, контейнер которой находится на рабочем узле, я не могу связаться с ней через узел диспетчера. Время ожидания соединения истекло. От рабочего узла соединение установлено успешно.
Однако если я заставлю рабочий узел рекламировать свой общедоступный IP-адрес, все будет работать хорошо. Узлы размещены в Digitalocean, вы знаете, откуда взялась эта проблема?
Относится к Истекло время ожидания соединений с сеткой маршрутизации Docker Swarm.
Я наконец-то понял ! Проблема заключалась не в закрытых портах или неправильной настройке, а во внутреннем устройстве Digitalocean с точки зрения сети.
Они устанавливают NAT между общедоступным и частным IP-адресами экземпляров. Оказывается, подключение p2p через NAT не очень хорошо сочетается. Как указано в этом комментарии (https://github.com/docker/swarmkit/issues/1429#issuecomment-361924332):
Ключ в том, чтобы иметь прямое соединение (без NAT на пути) от рабочего узла к управляющему узлу и наоборот.
На этой странице также упоминаются потенциальные проблемы и ограничения NAT: https://en.wikipedia.org/wiki/Network_address_translation#Issues_and_limitations
В нем говорится: «Если маршрутизатор NAT не приложит особых усилий для поддержки таких протоколов, входящие пакеты не смогут достичь места назначения».
Так что, даже если вы можете в конечном итоге полностью использовать рой через систему NAT, я бы не рекомендовал этого делать.
Обычно это результат того, что брандмауэр блокирует оверлейные сетевые порты vxlan между хостом. Вы хотите открыть следующее:
При использовании iptables на каждом узле кластера роя вам потребуется следующее:
iptables -A INPUT -p tcp -m tcp --dport 2377 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 7946 -j ACCEPT
iptables -A INPUT -p udp -m udp --dport 7946 -j ACCEPT
iptables -A INPUT -p tcp -m udp --dport 4789 -j ACCEPT
iptables -A INPUT -p 50 -j ACCEPT
Обратите внимание, что некоторые инструменты, в частности VMWare NSX, блокируют порты vxlan.