В предыдущей части я описал общую архитектуру приложения, и некоторые особенности инфраструктуры. Сегодня я бы хотел остановиться на некоторых пунктах подробнее, и рассказать, какие проблемы были созданы буквально на ровном месте. Параллельно расскажу, почему были приняты некоторые, прямо скажем, сомнительные решения (из разговоров с предшественником). Платформа не мониторилась от слова совсем. При этом пользователи постоянно жаловались на тормоза некоторых частей сайта. Предшественник решал проблему горизонтальным масштабированием — раз в 2–3 месяца просто докупался ещё один сервер и добавлялся в конфиг Nginx на балансировщике. Забегая вперёд, скажу что после того, как я начал снимать статистику использования мощностей — оказалось что 90% инфраструктуры тупо простаивает. Деньги на аренду серверов тратились впустую. Причина такого подхода — “Ну, если чото работать не будет — клиенты скажут, зачем ещё один демон крутит”. За годы работы в индустрии для меня лично все дистрибутивы слились в один. Если раньше при планировании инфраструктуры я завязывался на какой-то один дистрибутив просто потому что у меня с ним больше опыта (или потому что захотелось попробовать новенькое), то теперь я чаще руководствуюсь соображениями стоимости поддержки того или иного решения в конкретной ситуации.
В проекте, который я описываю сейчас мой предшественник где-то прочитал, что Gentoo отлично масштабируется на десятки серверов, и один раз собрав пакет-его можно просто rsync’ом разливать на остальные машины. Теория красивая (и я даже видел такое работающее решение-для админских рабочих станций), на практике же- синхронизировать дерево портежей хотя бы раз в неделю никто не догадался, что с течением времени сделало практически нереальным установку пакетов. Про обновления безопасности речи вообще не было. За пару недель я привёл всё в божеский вид, и задумался о переезде на бинарный дистрибутив. Тратить каждый месяц по несколько дней на обновления и пересборку обратных зависимостей я не хотел (привет, брокер ZeroMQ реализованый на Ruby через libffi). Причина использования Gentoo- “Ну смотри как быстро можно при помощи моих скриптов раскатать новый сервер и добавить его в инфраструктуру”. Раз уж заговорил про брокер — расскажу, какие с ним были проблемы. Мониторинг состояния. Его не было (точнее, в коде брокера были заглушки для функций ping_service(), get_service_state(), get_stats() и подобным). Единственная реализованая функция — ping_broker() — работала только из одного сервиса, и её можно было вызвать из Rails консоли: ServiceName.ping_broker(). Всё. Сервисы не знали, когда брокер лежит. Сервисы не умели перерегистрироваться в случае перезапуска брокера. Брокер был stateless, соответственно “забывал” про все сервисы после рестарта, нужно было руками ходить по серверам, подключаться к screen’ам и рестартовать все сервисы и их обработчики событий. Ну и как вишенка на торте — брокер отвечал за назначение портов для сервиса. То есть, в настройках брокера задавался пул min_port:max_port, сервис при запуске спрашивал у брокера, на какой порт ему биндиться, и пытался начать слушать на этом порту. Если брокер работает на одном сервере, а сервис запускается на другом — порт, который выдал брокер уже может быть занять и сервис попросту не стартанёт с ошибкой “Address already in use”. Мониторить сервисы с такой схемой работы не представлялось возможным. Цель использования этого брокера — распределить нагрузку на сервер и иметь возможность крутить каждый сервис на своём сервере — достигнута так и не была. Кому интересно — ссылка на проект: http://walterdejong.github.io/synctool/. В принципе — оно имело право на жизнь. Но во-первых — гора bash-скриптов + rsync — это не управление конфигурациями, во-вторых я тогда как раз познакомился с Ansible, который оказался сильно гибче. Тут особо даже сказать нечего, просто за пару дней перенёс всю логику из synctool в Ansible и забыл как страшный сон. Причины использования synctool — “Ну я посмотрел на Puppet, мне показалось сложно, а в synctool можно всё скриптами решить”. Про Absible/Chef человек просто не знал. В первой части я упомянул falcon, но забыл дать ссылку на него, исправляюсь: http://www.falconpl.org/. Помесь процедурного и функционального скриптового ЯП с поддержкой многопоточности и собственной виртуальной машиной. В принципе — мощная и интересная штука с низким порогом входа, но зачем было это использовать только для того, чтоб выполнять ssh dba@db01 “echo ‘SELECT stuff FROM table’ | psql -U postgres app_db” — осталось за гранью моего понимания. Вопрос “Нахера это тут?” в отношении falcon так и не был мной задан. Последний пункт на сегодня. В Rails есть чудный механизм, который покрывает 99% случаев, когда нужно по-разному настроить приложение для продакшена и для разработки. Этот механизм использован не был, и в коде гвоздями были прибиты имена хостов для сервисов, адрес Redis, адрес и порт базы данных, и доменное имя приложения. Как-то мне пришлось мигрировать Redis и базу данных на другие сервера — платформа лежала больше суток, пока я выгрепывал все такие места. Причины — модель разработки, и не очень высокая квалификация программиста. Проект писался практически “на коленке” сначала, новые фичи добавлялись и добавлялись, рефакторинг никто не делал, и в какой-то момент это превратилось в то, что на картинке:

В последней части я расскажу о том, как платформа выглядит сейчас, какие технологии используются и почему, как использование подходящих под задачу инструментов помогает экономить деньги, и почему сисадмин не должен кодить, а программист — админить. Системный администратор автоматизированых систем