Как умирают надёжные сервисы
Есть категория сбоев, которые особенно неприятны не потому, что всё упало сразу, а потому что сначала кажется, будто ничего страшного не произошло.
Все любят строить отказоустойчивые системы, и наша команда не исключение. У нас был именно такой сервис, надёжный как "швейцарские часы": хорошо распределённый по инфраструктуре, по нескольким дата-центрам, с резервом в облаке. По всем признакам система выглядела вполне надёжной.
Но экскаватор внёс свои коррективы и просто перерубил оптику, отрезав один из ЦОДов от остального мира. Казалось бы, чего переживать: компоненты распределены, запас прочности есть, значит переживём.
Только реальность, как обычно, интереснее, чем схемы на бумаге.
В сервисе были указаны локальные DNS-серверы, и находились они как раз в том самом отрубленном ЦОДе. Формально сервис продолжал жить, но тихо начал деградировать.
Красивого мгновенного падения не произошло. По мере истечения DNS-кэша часть запросов начала подвисать, отдельные функции стали работать нестабильно, таймауты поползли вверх. Получилась классическая история про отказоустойчивость, которая не пережила отказ одной из зависимостей.
Именно такие аварии хорошо отрезвляют. Они учат смотреть чуть шире: не только на свой сервис, но и на те сервисы, без которых он на самом деле жить не может.
Postmortem составили, причины выяснили, выводы сделали. Дальше уже обычная инженерная работа — не просто обсудить проблему, а закрыть дыру в архитектуре. Так появилась задача добавить собственный кэширующий DNS, который позволил бы сервису продержаться без удалённых резолверов.
Я взял эту задачу на себя. Перебрал несколько вариантов и в итоге поднял в Kubernetes связку из двух pod’ов Unbound для отказоустойчивости и Redis для хранения кэша. Redis сохраняет данные в файл в хранилище Ceph, чтобы кэш не исчезал после перезапуска и система не начинала каждый раз с чистого листа.
Получился ещё один слой устойчивости.
Самое полезное в таких историях не конкретный стек, а понимание простой вещи: отказоустойчивость проверяется не только количеством узлов, но и надёжностью зависимостей.
Как говорил великий классик:
«Опыт, сын ошибок трудных».




