Почему нельзя использовать DNS для балансировки всех backend машин
Что проверяют
Видите ли вы разницу между «раздать клиентам список адресов» и «балансировать нагрузку». Для Go-сервисов это ещё и вопрос про долгоживущие соединения: gRPC и HTTP/2 ведут себя с DNS совсем не так, как браузер.
Как отвечать
DNS умеет одно: отдать набор адресных записей. Всё остальное, чего ждут от балансировщика, он не делает.
Нет обратной связи о состоянии. Резолвер не знает, что процесс упал или деградировал, и продолжает отдавать его адрес. Запись убрать можно, но клиенты узнают об этом не раньше, чем истечёт TTL, а TTL повсеместно не соблюдается: кэшируют промежуточные резолверы, ОС, рантайм и сам клиент. Вывод машины из ротации превращается в ожидание вслепую.
Нет распределения. Порядок записей в ответе это не алгоритм: клиент обычно берёт первый рабочий адрес, и вместо равномерной нагрузки получается перекос. Нет ни весов, ни учёта числа соединений, ни знания о долгих запросах.
Нет масштаба. Ответ по UDP ограничен по размеру, поэтому в него влезает лишь десяток-другой адресов, остальное обрезается или уходит в TCP.
В Go добавляется своё: адрес резолвится один раз, при установке соединения. Пул http.Transport и канал gRPC живут часами и остаются приклеенными к старому адресу. Новая реплика в DNS есть, а трафика на ней нет, пока соединения не переустановят.
Рабочая схема: DNS распределяет грубо, по регионам и точкам входа, а внутри работает балансировщик или клиентская балансировка поверх service discovery с активными проверками здоровья.
Где спотыкаются
Говорят, что DNS не умеет географию. Умеет: геозависимые ответы и подсказка о подсети клиента работают давно. Слабое место не в географии, а в кэшах и отсутствии проверок состояния.
Второе: верят в TTL как в таймер. Короткий TTL нагружает резолверы, но клиента ни к чему не обязывает: часть кэшей держит запись дольше, а отдельные рантаймы запоминают адрес на всё время жизни процесса.
Третье: забывают про долгие соединения и предлагают чистый DNS для gRPC. Без периодического переустановления соединений или резолвера внутри клиента новые реплики так и останутся пустыми.