Короткий ответ
Нужно сверить путь, порт, протокол, ожидаемый код ответа и таймауты health check с реальным поведением приложения — чаще всего причина в том, что health check стучится не в тот порт/путь, ожидает слишком быстрый ответ, или проверяемый эндпоинт зависит от медленной внешней зависимости.
Как это работает подробнее
балансировщик периодически посылает запрос на заданный путь/порт и сравнивает код ответа и время с настроенными ожиданиями; если ответ не пришёл вовремя или код не совпал заданное число раз подряд, таргет исключается из ротации независимо от реального поведения под пользовательским трафиком.
Пример кода
example.txt
Health check config: HTTP GET /status, timeout 2s, interval 5s, unhealthy threshold 2
Логи приложения: /status иногда отвечает за 2.5-3s под нагрузкой из-за синхронного запроса к внешнему APIЧто использовать на практике
- Рекомендация. сравнивают конфигурацию health check с логами приложения в момент пометки unhealthy; отдельно проверяют, не блокирует ли security group именно IP-диапазон балансировщика; используют отдельный лёгкий health-эндпоинт, не зависящий от медленных внешних вызовов.
- Проверка. после замены
/statusна лёгкий эндпоинт без внешних вызовов (или увеличения таймаута до реалистичного значения) инстансы должны стабильно оставаться healthy под той же нагрузкой.
Подводные камни
- Риск. использовать для health check тяжёлый эндпоинт, проверяющий все внешние зависимости, из-за чего он иногда отвечает дольше таймаута под нагрузкой
- Риск. настраивать слишком маленький таймаут/интервал относительно реального времени ответа приложения
- Риск. не проверять, что security group пропускает трафик именно с IP-диапазона health checker'а.