Привет всем! Я Руслан Абдуллаев, DevOps-инженер Технократии. Хочу рассказать про наш проект из 2020. В тексте будет немного моей боли, признание ошибок архитектуры, переход к ansible и minio, и финальная форма покемона без единого даунтайма
«Все упало – нужно поднять!»
На старте со стороны архитектуры все было несложно: два сервера для дев и тест окружения, плюс прод, состоящий из двух серверов средней мощности: под приложение и базу.
Но вслед за простотой пришли проблемы. Мы стали замечать слабые стороны такой конфигурации. Основная беда — упор в ресурсы. Под нашим контролем было только вертикальное масштабирование. То есть на все вызовы мы могли отвечать банальным увеличением ресурсов прод-серверов. Но и это спасало лишь на время. В итоге — частые падения и понимание, что у всего этого есть потолок.
Будильник в те времена был не нужен: в 6 утра тебя все равно разбудит менеджер, с пеной у рта кричащий: «все упало – нужно поднять!».
Ситуация не устраивала всех, начиная от пользователей, которые не могли пользоваться платформой, заканчивая мной, который хотел спать. И тут хочется сказать, что в какой-то момент мы встали и со словами “хватит это терпеть” начали все резко менять, но нет. Изменения, скорее, были естественным продолжением проекта.
Мы поняли, что горизонтальное масштабирование должно решить большую часть проблем. Мы приступили. Нужно было разнести компоненты проекта по серверам и сделать дублирование для отказоустойчивости.
Закупились серверами, в течение пары месяцев перерабатывали все, что можно переработать, собрали новый прод и после зимних каникул переключили весь трафик со старого на новый.
Теперь детали
Пришлось погрузиться в тему кластеров баз данных: так как мы строили отказоустойчивую инфраструктуру, нельзя было обойтись всего одним сервером, это стало бы точкой отказа.
Было больно поднимать этот кластер из-за опасности испортить все данные и положить платформу на долгое время. Но и от этого можно спастись. Нужно всего лишь каждый день перед сном…. держать в голове, что реплицирование базы всегда занимает какое-то время. Если мы хотим читать данные с реплики сразу после того, как записали в мастер, то может задуматься о кешировании?
Еще на данном этапе мы не настраивали автопереключение мастера, но не факт, что это нужно. Главной задачей было не допустить, чтобы тяжеловесные запросы на чтение мешали другим операциям с данными. Также помним о возможном сплитбрейне при автопереключении. Вот такой народный рецепт.
С технической стороны кластер выглядит так:
3 сервера по 8 CPU 16 RAM и 1tb ssd. Реплицирование на основе транслирования журнала WAL.
![](https://habrastorage.org/getpro/habr/upload_files/3f7/ae2/d28/3f7ae2d28e53f9028165eb2b5d491b45.png)
В итоге у нас кластер из трех серверов, которые могут проглотить довольно большую нагрузку. Основной же удар примут четыре новых сервера, поэтому пришлось переработать хранение файлов. Уже нельзя использовать для этого тот же сервер, где работал бекенд – это приведет к рассинхрону: один файл запишется на первый сервер, а другой — на второй.
Мы с нашим бекенд разработчиком принялись искать возможные решения и остановились на minio, так как это s3 совместимое хранилище. При этом его можно развернуть на наших серверах и довольно тонко настроить. Например, обеспечить запись файлов только по внутренней сети, чтобы какие-то данные мог загрузить только бекенд, а наружу выкинуть только раздачу файлов.
Кстати, недавно столкнулся с обновлением minio, которое сломало нам дев среду. С обновлением произошло разделение админки с апи на разные порты. На первый взгляд ничего страшного, я добавил еще один домен и повесил на него админку, но почему-то часть нужного нам функционала сломалась. Например, шер файлов по ссылке. Пришлось откатываться до версии, которая была до этого.
Идем дальше. Я укрепил свои знания в деплое с помощью ansible. Это очень удобно. И почему я раньше так не делал? До ansible мы использовали обычный скрипт, который выкатывал нужные изменения на сервер из gitlab ci/cd. С приходом нескольких серверов, которые нужно обновлять, такой подход уже не работал. Зато ansible идеально подошел для этой задачи. Можно сказать, ему что делать, и он выполнит это параллельно на всех серверах.
Работаем с нагрузкой
Следующий пункт — балансировка нагрузки. Тут по классике, два сервера с nginx, выступающие входной точкой в платформу и размазывающие нагрузку по серверам.
Важно уточнить, что нагрузка, генерируемая во время нагрузочного тестирования, отличается от реальной пользовательской нагрузки. Как бы хорошо не были написаны тесты, они не смогут предугадать реакцию системы на настоящих пользователей.
Пример:
Перед переключением трафика на новый прод мы в течение нескольких дней активно нагружали его. Все просто летало. И вот мы запустили настоящих пользователей, но уже через несколько дней столкнулись с проблемой нехватки оперативной памяти на бекенд серверах. Все стало тормозить даже хуже, чем раньше.
Оказалось, мы неверно настроили количество gunicorn воркеров. С настоящими пользователями они начали отъедать много памяти. Тут стоит громко сказать: «не верьте официальной доке gunicorn!». Количество воркеров нужно ставить в зависимости от вашего приложения и проведенных тестов, а не на основе формулы которая дана в доке.
Но это не конец. Когда поняли проблему, решили снизить количество воркеров. Но у нас резко перестал собираться билд, мы не могли выкатить обновление. В течение следующих нескольких дней мы возились со сборкой и каждую ночь ребутали прод, чтобы он не лагал от нехватки памяти. В итоге пришлось сменить базовый докер-образ приложения и переписать его сборку. Это помогло выкатиться и решить проблему. После этого иногда все же приходилось ребутаться, но уже очень редко.
Пара слов о мониторинге
Мы настроили мониторинг всего железа, докер контейнеров и аптайма самой платформы на основе zabbix. Плюс никуда без алертов в телеграм в случае проблем. В конечном итоге это помогло предугадывать проблемы и решать их заранее, а не как обычно, когда все ломается в 6 утра. И вот мы уже более 6 месяцев без единого даунтайма.
Это мой первый текст, поэтому буду особенно рад вопросам в комментариях. Всем, кто добрался досюда спасибо! Как и обещал, в конце нечто особенное: пак девопсерских мемов.
![](https://habrastorage.org/getpro/habr/upload_files/70f/7c5/2c9/70f7c52c9bbdcb6be299b332127daadf.png)
![](https://habrastorage.org/getpro/habr/upload_files/6a8/ffb/4db/6a8ffb4db0b6df4692104f2fee58d475.png)
Кстати, подписывайтесь на наш телеграм-канал «Голос Технократии». Каждое утро мы публикуем новостной дайджест из мира ИТ, а по вечерам делимся интересными и полезными мастридами.