У нас было 2 балансировщика, 7 серверов для приложения, 5 самописных gem’ов, самописный конфиг ядра и целое множество языков программирования и технологий всех сортов и расцветок, база данных, а также списки todo в Basecamp, NodeJS, soсket.io и 2 дюжины ключей на одну сущность в Redis. Не то чтобы это был необходимый запас для стартапа, но если начал писать код, становится трудно остановиться. Единственное, что вызывало у меня опасение?—?это ZeroMQ. Ничто в мире не бывает более беспомощным, безответственным и порочным, чем самописная шина сообщений на основе ZeroMQ. Я знал, что рано или поздно мы перейдем и на эту дрянь.
А начиналось всё невинно: проект на Ruby on Rails, архитектура микро-сервисов, отдельный балансировщик с “горячим” бэкапом… Только потом я узнал, что: сервера работают на Gentoo; микросервисы используют хитрый алгоритм регистрации себя в приложении, что приводит к взрыву всего приложения если падает хотя бы один сервис; мониторинга нет; документации нет; населена роботами. Но достаточно лирики, давайте посмотрим как жил проект, когда в него пришёл я.
На сегодняшний день 90% написаного ниже неактуально — так это выглядело примерно два года назад. Повествование, однако, ведётся в настоящем времени?—?мне так удобнее.
Как я уже сказал, имеется Rails-приложение, и некоторое количество сервисов на бэкэнде. Обмен сообщениями между Rails-приложением и сервисами осуществляется через самописную шину сообщений. Рядом крутится Redis, в котором хранится срез текущего состояния сущностей, приложение на NodeJS + socket.io (обмен сообщениями между фронтэндом и бекендом). Упрощённо это выглядит примерно так:
Приложение оперирует некими сущностями, которые хранятся в базе “Rails db”. Сервисы оперируют теми же самыми сущностями, что и основное приложение, но имеют каждый свою отдельную базу. Синхронизация сущностей происходит через сообщения в ZeroMQ по сообытиям, которое генерирует основное приложение. Каждый сервис состоит из собственно самого сервиса, и набора event listener’ов (отдельные процессы по сути), которые принимают сообщения (каждый listener обрабатывает сообщения одного типа), и сообщают сервису что нужно сделать (какие поля в базе нужно поменять). Процесс самого сервиса тоже принимает определённый тип сообщений, по которым отдаёт в основное приложение данные из своей базы. И сервисы, и основное приложение активно работают с Redis (читают и пишут); синхронизации/локинга нет (т.е. возможны гонки, и они есть). Это что касается архитектуры приложения. Теперь пройдёмся кратко по серверам, и перейдём к самому интересному?—?особенностям экслпуатации.
Итак, сервера?—?обычные выделеные сервера (кто сказал “виртуалка”? обычные железяки). Средняя конфигурация?—?2х Core i7, 32–64 GB RAM, 2x 1T HDD / RAID1. По количеству?—?считаем. Два “балансера” (один основной, второй?—?“горячий” резерв, переключение?—?плавающий IP). Три сервера для сервисов. Один сервер для БД. Один сервер для брокера и Redis. Один сервер?—?тестовый (на нём крутятся все компоненты разом). Итого?—?8 штук. LAN между серверами нет, весь трафик гуляет по ДЦ (некоторые сервера разнесены по разным стойкам).
Что же с написаным выше не так, спросите вы? Да всё так, но дьявол, как обычно, кроется в деталях, а в нашем случае это?—?повседневная эксплуатация и поддержка. Дальше просто неструктурировано опишу некоторые моменты, которые я считаю проблемными.
Инструкция по добавлению нового сервера начинается со слов “устанавливаем Gentoo”. Да, весь стек крутится на Gentoo, со всеми вытекающими. Provisioning делается баш-скриптом. Для управления конфигурациями используется synctool (такой rsync на стероидах по сути). Деплой приложения?—?git pull руками на всех семи серверах. В коде основного приложения в десятке мест гвоздями прибиты имена хостов БД, Redis, брокера. Разделение в коде на production/development весьма условное (программисту настроить окружение для разработки занимает 2–3 дня). Сервисы настолько тесно интегрированы с основным приложением, что при падении одного?—?валится вся платформа. Сам сервис представляет из себя от трёх до пятнадцати процессов, каждый из которых просто пускается руками в screen (да, на одном из серверов постоянно запущено 15–20 сессий screen, и в репозитории с документацией лежит файлик “вот такие скрины должны быть на этом сервере после ребута”).
И самое главное?—?админка приложения. Рождённая в потаённых закоулках сознания сумрачного тевтонского гения гремучая смесь из bash, Ruby и Falcon. Вот вы знали, что есть такой язык программирования?—?Falcon? Теперь знаете (пройдите по ссылке, к слову, язык достоин внимания в качестве расширения кругозора). Сама “админка” представляет из себя просто набор SQL запросов, и кусков кода Ruby, которая позволяет оперировать разными параметрами сущностей. В ней нет ни-че-го, что оправдало бы использование чего-то ещё, кроме bash. Тот же falcon — за каким чёртом он там используется я так и не понял; реально всё, что делают falcon скрипты— по определённым условиям формируют примерно такое, и выполняют это через system():
echo "SELECT stuff FROM entities" | psql -U postgres db_name
Заключение
Всё, что описано выше создавалось одним человеком в течение двух лет. Его программерские скилы оценивать не возьмусь, но админ (или девопс, как хотите) из него, прямо скажем, херовый — чего стоит одна Гента на проде, вместо нормального бинарного дистрибутива. В какой-то момент даже бизнес понял что дальше нормально оно жить не будет, и меня попросили посмотреть, что можно сделать, чтоб со всей этой хернёй попробовать взлететь. В следующей части расскажу, что и как я делал, чтобы приуменьшить количество энтропии во Вселенной.
Комментарии (19)
olku
09.12.2016 13:36+1Интересно, продолжайте! На самом деле, это естественный ход вещей. Стартап за 2 года подрос, набрал клиентов, теперь задумался о качестве услуг и процессов, масштабировании и гибкости не в ущерб имеющимся клиентам. Можно лишь поздравить! Не все доживают.
SchmeL
09.12.2016 15:22Кто-то от Gentoo плюется, кто-то от Slackware, мы вот от CentOS с его dracut плевались, когда при создании снапшота lvm — он отказывался грузиться. Не важно в принципе какой дистрибутив используется, все зависит от того сколько процентов в команде могут с ним нормально управляться, если только один человек, то беда…
br0ziliy
09.12.2016 15:55+1Ну количество человеко-часов затраченое на поддержку Gentoo всё-ж поболее будет, чем на поддержку rpm- или deb-based дистрибутива. «Какой дистрибутив» в контексте «Debian или CentOS» и правда не имеет значения, но вот «source-based или binary» — очень даже. Я про это немного во второй части пишу.
Singaporian
12.12.2016 16:09Мы в нашем приложении автоматически при каждой сборке создаем около 120 пакетов. Релизимся примерно 2-3 раза в день. Плюс около 30-40 билдов тестеров и столько же дев. Пакеты не простые: каждый апгрейд умный и делает все как надо при помощи pre/post inst/rm скриптов, включая миграции SQL.
Сделаете тоже самое на Gentoo?
niko1aev
09.12.2016 17:02+2Вопрос скорее не к администраторам, а к разработчикам:
— В какой ситуации такая архитектура имеет смысла?
— Зачем срез состояний хранить в Redis?
— Зачем шина?
— Зачем вообще такое кол-во баз данных?
— Зачем хранить состояния в NoSQL базах?
tgz
09.12.2016 20:23Тема с 0MQ не раскрыта.
avigmati
12.12.2016 16:09+1Попытаюсь угадать: не удовлетворяет условиям масштабируемости (хороша для сообщений точка-точка), надежности (сообщения не персистентны).
tgz
12.12.2016 16:19Плохо угадываете. Если инструмент не подходит по своим характеристикам, его просто не будут использовать. Или как вы себе представляете, люди взяли 0mq, а через год поняли что персистентности нет?
jewubinin
12.12.2016 16:06Очень интересно. Пишите еще.
А как там по производительности?
Какую нагрузку держал такой зоопарк на таком железе в начале вашей разборки?
А были ли средства отказоустойчивость обеспечивающие? Падение одного сервера не рушило систему?
То ест весь этот зоопарк хоть как-то себя оправдывал или нет?br0ziliy
12.12.2016 16:08Плохо всё было по производительности. Упёрлись в пару говённо сделаных реализаций, и при 400-500 пользователей динамическая часть сайта тормозила страшно.
Отказоустойчивости не было, если падал один сервис — ложилось всё.
Продолжение: https://habrahabr.ru/post/317408/
Acuna
13.12.2016 10:33+1У меня объяснение это всему одно (особенно насчет админки): девопс просто принципиально не хотел пользовать PHP как несерьезный, и ему даже было невдомек, что он просто идеально подходит для таких задач. В конечном итоге сам себя в лужу и посадил.
v_sadist
Просто настоящей боли пост.
С нетерпением жду, как Вы все это разгребли (сам был в той же ситуации, но тоже вышел из нее с щитом)
br0ziliy
Продолжение: https://habrahabr.ru/post/317408/