В ходе работы с микросервисами мы неоднократно сталкивались с проблемами сервис дискавери при автоскелинге, схлопывании лишних нод. Были перепробованы почти все решения существовавшие или существующие на данный момент, но как водится — ничего не ложилось идеально на наши динамичные окружения (десятки остановок/запусков однотипных контейнеров в час). Наиболее близкое решение было NGINX+Consul+Consul templates, но оно было некрасивым, требовало перезапуска, не давало возможности использовать внешние хелсчеки иначе как через Consul. В общем, как всегда бывает — было принято решение написать свое решение. В процессе обсуждения всплыли десятки вещей, которые хорошо было бы реализовать, из них были выбраны самые критичные для нас и интересные для общественности. Iphash
Leastconn
Roundrobin
Weight Static — просто список серверов в конфиге.
Docker — запрос в докер Docker / Swarm API фильтрованные по label и внутренним портам контейнера.
Exec — инициирование запуска внешнего скрипта, чтение из stdout и его разбор по регулярке (пока прописана жестко).
JSON — запрашивает через http-запрос URL и разбирает его по паттернам (поддерживает многоуровневый JSON).
Plaintext — запрашивает через http-запрос URL и разбирает его по заданному в конфиге регулярному выражению.
SRV — запрашивает у заданного DNS SRV записи по имени сервиса. Так как изначально было совершенно понятно, что мы просто не потянем имплементировать хелсчеки в объеме того же haproxy, было принято решение отделаться малой кровью и сделать всего 2 типа хелсчеков. Ping — простой TCP ping;
Exec — запуск произвольного бинарника с передачей ему параметров и чтение из stdout вывода. У нас есть произвольные сервисы, регистрирующие себя, к примеру, в Consul. Будем использовать Consul dns для определения пула серверов.  В этом примере мы определили тип балансировки как "srv", так же определен DNS-сервер и его порт, на который будут идти запросы на сервис дискавери. Определена частота обновления списка серверов, а так же немаловажная переменная — политика для случая, когда DNS-сервер не ответил. Для максимальной консистентности окружения нужно ставить failpolicy="setempty". В таком случае при отсутствии ответа от DNS весь пул бекенд серверов будет обнулен, а входящие соединения будут сбрасываться. В противном случае нужно использовать failpolicy = "keeplast", тогда балансировщик будет использовать последние данные, пришедшие до сбоя соединения с DNS. По сути различий в API и способе настройки для Docker/Docker Swarm нет. Мы можем одинаково работать и с Docker хостом, и с Docker Swarm кластером. Рассмотрим работу с ними в одном примере.  Сейчас мы будем балансировать определенными сервисами, используя Docker Swarm, как более общий пример. Все нижеописанное работает и для отдельного Docker хоста. В данном примере мы определяем тип дискавери как "docker", определяем базовый docker url, лейблы и внутренний порт докер контейнера (со стороны сети самого контейнера) по которым балансировщик будет делать выборку, из которых формируется пул бекенд серверов. Для данного примера мы будем использовать более "продвинутый" тип хелсчеков, а именно exec-хелсчеки. Помимо параметров частоты запуска чеков есть еще время отработки скрипта. Время между запусками должно быть больше времени отработки скрипта, чтобы не было "набегов". Команда запуска данного хелсчека формируется как /path/to/script [ip] [port]. После отработки скрипта, он должен выводить в stdout строку, которая сравнивается с положительным и отрицательным предполагаемым результатом.  В последующих статьях я планирую привести несколько примеров более сложного использования других видов дискавери. Также будет описана специфика конфигурирования и установки под Windows. Devops