Публикация служб Docker Swarm по определенным IP-адресам

На Centos 7.4 я настраиваю рой, в котором я хочу запустить несколько маршрутизаторов, все доступные на порте 80/443 .
Цель состоит в том, чтобы разместить несколько сред (тестовых / промежуточных ...) в одном рое, все симметрично.

Я использую Docker 17.12.0-ce и Traefik v1.4.6 в качестве маршрутизатора.

Основная идея состоит в том, чтобы иметь виртуальный IP-адрес для каждой среды и публиковать порты Traefik только на этом адресе. Это невозможно с Docker Swarm, поэтому мне приходится прибегать к тому, чтобы экземпляры Traefik прослушивали порты 81/82 и т. Д. И каким-то образом переносили трафик с VIP: 80 на: 81 /: 82.

Виртуальные IP-адреса для всех сред через менеджеры роя обрабатываются Keepalived.

Соответствующая конфигурация службы докеров для Traefik:

"Ports": [
          {
           "Protocol": "tcp",
           "TargetPort": 80,
           "PublishedPort": 81,
           "PublishMode": "ingress"
          },

# netstat -anp|grep 81
tcp6       7      0 :::81                   :::*                    LISTEN      4578/dockerd        

firewalld настроен на разрешение трафика на порты 80, 81, 82 и т. Д.

Доступ к серверным службам, предоставляемым Traefik, непосредственно через порт 81 на VIP работает. Другой трафик не прошел, и время ожидания запроса на стороне клиента в конечном итоге истекло.
ipvsadm зарегистрировал соединение как активное.

Если я настрою HAProxy для прослушивания VIP: 80 и проксирования запросов через HTTP на 127.0.0.1:81, все будет работать, но я бы хотел избежать этого, поскольку он требует, чтобы все данные проходили через HAProxy, тратя впустую ресурсы даром и требуют локальной настройки.

У меня нет идей, и я не знаю, как дальше устранять неполадки.

ИЗМЕНИТЬ для уточнения. Мой вопрос:
Можно ли перенаправить трафик с VIP: 80 на: 81 /: 82 и т. Д. Без использования HAProxy или другого процесса, который просто перекачивал бы данные на настоящий маршрутизатор (Traefik)?

1
задан 23 January 2018 в 19:30
2 ответа

Во-первых, вы можете использовать несколько IP-адресов на хост, если у вас есть возможность добавлять IP-адреса в реальной сети. Этот действительно работает в Swarm под Linux. См. macvlan docs и поиск в Google для "macvlan swarm".

2-й, вы используете оверлей и входную сеть роя, верно?

3-й, большинство людей просто помещают Traefik (или мой fav ] http://proxy.dockerflow.com ) для прослушивания 80/443 и перенаправления на соответствующую службу / стек в Swarm на основе заголовка хоста. Как спросил Флорин, почему вы не пробуете это?

2
ответ дан 3 December 2019 в 20:17

Нам нужно было опубликовать отдельные сервисы docker swarm на одних и тех же портах, но на разных конкретных IP-адресах. Вот как мы это сделали.

Docker добавляет правила в цепочку DOCKER-INGRESS таблицы nat для каждого опубликованного порта. Добавляемые правила не зависят от IP, поэтому обычно любой опубликованный порт будет доступен для всех IP-адресов хоста. Вот пример правила, которое Docker добавит для службы, опубликованной на порту 80:

iptables -t nat -A DOCKER-INGRESS -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.2 :80

(Вы можете просмотреть их, запустив iptables-save -t nat | grep DOCKER-INGRESS).

Наше решение состоит в том, чтобы публиковать наши сервисы на разных портах и ​​использовать скрипт, который перехватывает команды iptables dockerd, чтобы переписать их, чтобы они соответствовали правильной паре IP-адреса и общедоступного порта.

Например:

  • сервис №1 опубликован на порту 1080, но должен прослушиваться на 1.2.3.4:80
  • сервис №2 опубликован на порту 1180, но должен прослушиваться на 1.2.3.5:80

Затем мы соответствующим образом настраиваем наш скрипт:

# cat /usr/local/sbin/iptables
#!/bin/bash

REGEX_INGRESS="^(.*DOCKER-INGRESS -p tcp) (--dport [0-9]+) (-j DNAT --to-destination .*)"
IPTABLES=/usr/sbin/iptables

SRV_1_IP=1.2.3.4
SRV_2_IP=1.2.3.5

ipt() {
  echo "EXECUTING: $@" >>/tmp/iptables.log
  $IPTABLES "$@"
}

if [[ "$*" =~ $REGEX_INGRESS ]]; then
  START=${BASH_REMATCH[1]}
  PORT=${BASH_REMATCH[2]}
  END=${BASH_REMATCH[3]}
  
  echo "REQUESTED: $@" >>/tmp/iptables.log

  case "$PORT" in
     '--dport 1080') ipt $START --dport 80 -d $SRV_1_IP $END; exit $?; ;;
     '--dport 2080') ipt $START --dport 80 -d $SRV_2_IP $END; exit $?; ;;
                  *) ipt "$@"; exit $?; ;;
  esac
fi

echo "PASSING-THROUGH: $@" >>/tmp/iptables.log

$IPTABLES "$@"

NB Сценарий должен быть установлен в PATH dockerd перед командой iptables вашего дистрибутива. В Debian Buster iptables устанавливается в /usr/sbin/iptables, а PATH dockerd имеет /usr/local/sbin перед /usr/sbin, поэтому имеет смысл установить скрипт в /usr/local/sbin/iptables. (Вы можете проверить PATH dockerd, запустив cat /proc/$(pgrep dockerd)/environ | tr '\0' '\012' | grep ^PATH).

Теперь при запуске этих docker-сервисов правила iptables будут переписаны следующим образом:

iptables -t nat -A DOCKER-INGRESS -d 1.2.3.4/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.2:1080
iptables -t nat -A DOCKER-INGRESS -d 1.2.3.5/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.2:2080

В результате запросы на http://1.2.3.4/ идут к сервису №1, а запросы на http://1.2.3.5/ идут к сервису №2.

Сценарий можно настроить и расширить в соответствии с вашими потребностями. Он должен быть установлен на всех узлах, на которые вы будете направлять запросы, и настроен на общедоступные IP-адреса этого узла.

4
ответ дан 27 December 2020 в 18:43

Теги

Похожие вопросы