Назад | Перейти на главную страницу

Почему нам (не) следует балансировать нагрузку на нескольких хостах в кластере Docker Swarm?

У нас есть 3 хоста в кластере роя, и у нас есть веб-приложение, развернутое в этом кластере. Веб-приложение будет работать только на 1 хосте в любой момент времени. Если один хост выходит из строя, веб-приложение будет перемещено на другой хост.

Docker позаботится о маршрутизации вашего запроса в веб-приложение независимо от того, на каком хосте ваш запрос попал.

Чтобы гарантировать, что мы всегда доберемся до запущенного и работающего хоста, мы думаем об использовании Nginx в первую очередь. Мы бы создали виртуальный хост на Nginx, который будет передавать запросы рою Docker.

Для этого у нас есть два подхода.

A. Мы бы просто "циклически перебирали" запросы через хосты.

Это простой подход. Мы бы использовали Nginx для отключения сервисов, когда они выходили из строя. Однако, несмотря на то, что Nginx получил ошибку 500 от хоста 1, возможно, веб-приложение вернуло эту ошибку 500 с хоста 3. Nginx будет неправильно думать, что служба не работает на хосте 1, и отключит службу на этом хосте.

Б. Все запросы мы направляем лидеру роя.

Мы не используем Nginx для балансировки нагрузки между хостами. Мы просто отправляем все запросы лидеру Docker Swarm (с помощью различных скриптов мы настраиваем Nginx для этого). Таким образом, мы не выполняем «двойную» балансировку нагрузки (как Nginx, так и Docker Swarm) - но весь трафик проходит только через лидера Docker Swarm.

С одной стороны, решение A просто и понятно, но оно также может усложнить задачу двойной балансировки нагрузки. Второе решение может быть более запутанным в том смысле, что оно менее стандартно, но также может упростить понимание.

Какой подход мы должны - с чисто технической точки зрения - предпочесть?

Думаю, это комментарий к варианту 1.

Я тоже смотрю на это и из того, что я могу сказать в Docker Swarm> 1.12, все, что вам нужно сделать, - это создать обратный прокси для службы / веб-сайта. В своем доказательстве концепции я сделал следующее: 1) создал две оверлейные сети, одну для прокси-сети, которая будет обращена к внешней стороне, и одну для моей служебной сети, которая является внутренней только тогда. 2) развернул 3 реплики службы, прикрепив ее к служебный оверлей и оверлейный сетевой прокси-сервер (--network proxy --network my-service). Наконец, я установил обратный прокси-сервер nginx, привязанный к моему корпоративному псевдониму, который будет принимать входящие соединения на портах 80 и 443.

sudo docker service create --name proxy \ 
-p 80:80 \
-p 443:443 \
--network proxy \
--mount type=volume,source=reverse-proxy,target=/etc/nginx/conf.d,volume-driver=azurefile \
--mount type=volume,source=ssl,target=/etc/nginx/ssl,volume-driver=azurefile \
nginx

Крепления просто есть, поэтому мне не нужно копировать файлы на каждый хост. Это подключение указывает на учетную запись хранилища файлов Azure, что значительно упрощает обслуживание дополнительных контейнеров.

Обратный прокси выглядит так:

location /my-service/ {
    proxy_read_timeout 900;                
    proxy_pass http://my-service/;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

http: // мой-сервис - это внутренняя запись DNS для роя, которая всегда указывает на VIP, на котором размещается моя служба, будь то 1 узел или 1000 узлов. Насколько я могу судить, каждая развертываемая вами служба получает свой собственный диапазон подсети, а главные узлы отслеживают, где работают контейнеры, и обрабатывают маршрутизацию за вас.

В настоящее время у нас есть несколько A-записей, указывающих на разные IP-адреса хоста, и для этого используется циклический перебор, однако мы можем переместить их из управляемого DNS Windows Server в Azure Traffic Manager для большего контроля.