[Перевод] 11 лет хостинга SaaS: история и мой опыт
Источник
Нашему ресурсу Tanda скоро исполняется 11 лет. По этому поводу один из моих читателей высказал идею, что было бы классно поразмышлять на тему опыта, который я получил за долгие годы управления этим приложением.
В итоге я просидел над этой статьёй целую вечность, потому что процессы развёртывания, хостинга и управления инфраструктурой в целом на протяжении десяти лет являлись, пожалуй, наиболее трудной и беспокойной частью моей работы. В основном причина в том, что я постоянно окунался в омут с головой и зачастую не понимал, что делал. К сожалению, когда у вас есть активное приложение, которое используют многие люди, вы не всегда находите время на подобающее изучение матчасти.
Изложенная в этой статье история разбита на несколько этапов, через которые мы прошли. Я написал её, чтобы те, кто окажется на аналогичном пути, могли миновать некоторые из его острых углов.
▍ Этап 1: Heroku
Мы начали с Heroku, потому что в 2012 году, если вы проходили какое-либо обучение по Ruby on Rails, которое включало развёртывание приложения, то в итоге заводили аккаунт на Heroku.
В простоте использования конкурентов у Heroku не было. Но это не было достаточным аргументом для тех, кто ещё никогда не сталкивался с развёртыванием приложения. Я знал, что авторы интернет-руководств считали этот способ самым простым для развёртывания приложения, но тогда ещё не понимал, насколько этот инструмент лучше всего того, что было до него. 1
Зато я понимал его слабые стороны:
- отсутствие гибкости;
- затраты.
Отсутствие гибкости: Heroku отлично работал, пока вы использовали его в точности так, как было задумано. И мы были довольно близки к этому: веб-приложение с базой данных, несколькими фоновыми воркерами и кэшем. Но при этом было одно небольшое отличие — нашему приложению периодически требовалось обрабатывать длинные запросы (загрузку файлов) от медленных клиентов (телефоны или планшеты, работающие в условиях слабого сигнала). Мы не первыми предложили возможность загрузки файлов, но правильный способ настройки Unicorn для обработки этого процесса настолько отличался от базовых установок, что это доставило мне немало хлопот. 2
Поскольку я ничего не знал о развёртывании приложений, то решил, что это вина Heroku.
Сегодня я уже лучше понимаю и ценю сложность того, что они пытались делать, но сомневаюсь, что был единственным, кто слишком буквально воспринял их громкое заявление о предоставлении всего необходимого для развёртывания приложения.
Затраты: Heroku стоит намного дороже альтернативных решений вроде запуска собственного VPS. Естественно, он и делает намного больше. Но поскольку это был мой первый самостоятельный деплой, то я не оценил этих дополнительных возможностей и при сравнении с альтернативами акцентировал своё внимание на долларовых знаках.
Думаю, что сегодня также рассуждают новички, кто только начинает осваивать Rails, в отличие от тех, кто познакомился с этим инструментом после использования Java или чего-то подобного из старых непростых времён. Эти люди по-разному оценят все достоинства современного решения в сравнении с тем, что было доступно раньше. К счастью, сегодня можно легко выработать тот же уровень понимания, попытавшись собрать фулстэк-приложение на JS, а затем вернувшись к Rails.
Как бы то ни было, именно стоимость в итоге привела нас к отказу от Heroku. Наш последний счёт от этого сервиса составил…$104.95.
▍ Этап 2: Digital Ocean
Где-то через год с момента запуска Tanda к нам устроился интерн из моего университета, который был очень заинтересован в работе с инфраструктурой и оптимизации затрат. По сути, это он убедил меня, что платить за Heroku — это всё равно, что выбрасывать деньги на ветер. Он был славным парнем, и я реально ценю оказанную им в то время помощь, но 10 лет спустя могу честно сказать, что это был ужасный совет (я сам виноват, что послушал его).
Переезд с Heroku означал замену всех компонентов, за которые отвечала эта платформа. И мы делали это не полностью автоматическим способом, поскольку были настолько мелкими, что смысл в этом отсутствовал. Так что мы просто щёлкали по серверам в интерфейсе Digital Ocean, после чего настроили скрипты Capistrano для их развёртывания. За выходные мы отключили сайт на очень короткий промежуток времени, скачали с Heroku базу данных, загрузили её на дроплет Digital Ocean (а-ля сервер) и изменили записи DNS. Миграция была закончена!
Наш первый счёт от Digital Ocean составил $28,93, а второй (за первый полный месяц) — $39,23. Я решил, что поступил мудро и сэкономил по $2 доллара в день. Какое-то время всё работало нормально. В результате оказалось, что $40/месяц покрывали намного больше серверов, чем требовалось для работы нашего небольшого приложения.
Проблемы же начали возникать, когда приложение начало расти активнее. Наша база клиентов удваивалась каждые 9 месяцев, и довольно скоро это привело к потребности в дополнительных серверах. Добавлять их нужно было вручную, а поскольку этот процесс оказался довольно кропотливым, то в нём было легко допустить ошибку. Я разобрался, как это делать, но всякий раз, когда я сталкиваюсь с добавлением нового «аппаратного обеспечения», мне внутренне становится не по себе.
Настоящие же проблемы стали проявляться, когда наш сервер базы данных начал перегружаться. Довольно регулярно, если мы не развёртывали сайт дольше одного дня, Postgres исчерпывала память, и операционная система её закрывала. Иногда проблема исправлялась сама, но чаще кому-то приходилось подключаться к приложению через SSH и перезапускать все серверы. Это была неприятная часть рабочего времени дня, но за тот период у меня также накопилось немало историй о перезапуске серверов с телефона из туалетов в барах.3
Однако худший инцидент с Digital Ocean произошёл, когда эта платформа одновременно отключила все наши дроплеты. Срок действия привязанной к аккаунту кредитной карты истёк. При этом возможность привязать резервную карту отсутствовала, а письма с уведомлениями отправлялись в общий ящик, который никто не отслеживал. В результате где-то месяц мы получали и игнорировали предупреждения о необходимости внести платёж, и реально обратили на это внимание, только когда вся система оказалась отключена и не отвечала на SSH. Это была полностью их вина, но в тот момент всё выглядело просто как кривая настройка.
Описание всей этой истории спустя 10 лет вызывает у меня стыд. Поразительно, что при таком недостатке знаний мы всё же смогли справиться. Если бы у меня была машина времени, то я бы вернулся назад и посоветовал себе потратить на Digital Ocean в 10 раз больше ($500/месяц в действительности не стали бы слишком критичной суммой) и спать спокойно.
Просидев на Digital Ocean где-то 3 года, мы решили, что эта платформа слишком проста для наших растущих потребностей. Мы начинали регистрировать крупных клиентов и решили, что нам нужен более корпоративный подход к хостингу приложения. Мы хотели перейти на управляемую базу данных, чтобы больше не заниматься управлением Postgres и серверами самим. Мы хотели сократить время даунтайма нашей платформы.4
Нам требовалась возможность автоматического масштабирования в ответ на колебания в спросе, а также возможность балансировать нагрузку различных маршрутов к разным группам ресурсов (…из нашего монорепозитория). Мы думали, что всё это нужно нам для того, чтобы быть полноценным сервисом.
По факту же, оглядываясь назад, я понимаю, что бо́льшая часть этой логики сработала наоборот. Автомасштабирование — это техника, а не продукт, монополизированный AWS. Вместо поиска дополнительных сложностей нам следовало найти платформу, достаточно простую, чтобы мы могли полноценно её освоить (хотя управляемая база данных была реально хорошей идеей).
Единственной разумной причиной съехать с Digital Ocean стало то, что у них не было австралийского дата-центра, а у нас были клиенты, для которых это было очень важно. Тогда его запуск вроде как был не за горами, но по факту случился только в конце 2022-го. Так что хорошо, что мы не стали его ждать.
Как бы то ни было, нам нужно было поднимать уровень. А если вы хотите поднять уровень своего хостинга, то к кому обратитесь?
▍ Этап 3: AWS
Нам нужно было становиться реальным бизнесом, а реальные бизнесмены размещали свои приложения на AWS. Так мы и поступили. В частности, мы портировали нашу инфраструктуру Digital Ocean на AWS EC2. Мы не использовали преимущества других возможностей платформы, а просто рассматривали её как любой другой VPS.
Через несколько месяцев я узнал, что за нами был закреплён аккаунт-менеджер AWS. Об этом я узнал от клиента, который также дал некоторые пояснения. Я был воодушевлён, так как считал, что менеджер поможет нам быстро вырасти и попасть в нирвану, где мы уже сможем спокойно жить без постоянного страха перед масштабированием.
На нашу первую встречу менеджер также пригласил своего архитектора программных решений. Я никогда ранее не встречался с такими специалистами, поэтому не понимал до конца, чем они занимаются. Единственное, что делал тот парень на встрече — это отвечал на любые наши вопросы фразой: «А как это будет работать в мире без серверов?» Я не совсем понимал, чем нам способен помочь сервис AWS Lambda (до сих пор не понимаю), но этот архитектор не мог привнести в беседу ничего полезного, кроме как напоминать о его существовании. 5
Меня так вдохновило наличие аккаунт-менеджера, что я какое-то время чувствовал себя тупым за то, что не понимал Lambda и не мог разобраться в принципах работы AWS. В итоге я осознал, что проблема была не во мне.
Ещё один забавный инцидент произошёл где-то через год и был связан с исчерпанием целых чисел. Наше приложение Rails было довольно старым, и почти в каждой таблице в качестве первичного ключа использовалось целое число. В более новых версиях Rails новые таблицы создавались в виде bigint, но тогда никто в нашей команде не осознавал, что это проблема, пока однажды в пятницу (такое не подстроишь — это была пятница 13-е) мы не смогли вставить новые строки в самую активно записываемую таблицу. К счастью, в тот вечер все ещё находились в офисе, общаясь за выпивкой, поэтому мы смогли быстро отреагировать на этот инцидент. Вот похожая история.
Этот инцидент подтолкнул нас приложить дополнительные усилия к мониторингу системы, чтобы быстрее реагировать на возможные неполадки (нет худа без добра). Кроме того, тот случай вселил в меня пожизненную паранойю относительно других скрытых подвохов PostgreSQL, которую я так и не смог полноценно усмирить.
В последнее время основные проекты на AWS преимущественно были связаны с достижением соответствия стандартам. Подтвердив соблюдение всех пунктов GDRP (General Data Protection Regulation, общий регламент по защите данных) и его аналогов в других странах, мы получили сертификат SOC-2. Помимо этого, всё немного упростила возможность указывать на логотип Amazon, но сам факт размещения на конкретном облаке ещё не открывал для нас все двери.
Просидев несколько лет на AWS, мы начали ощущать стабильность и набрались опыта в работе с инфраструктурой. Какое-то время мы не занимались построением стека, да и большой потребности в этом не видели — два больших достижения! Очередным серьёзным вызовом для нас стали специализированные знания, то есть их отсутствие. За всю историю Tanda в команде «DevOps» (очень широко говоря) работало менее 10 человек. Но люди приходят и уходят. На тот момент в ней было два специалиста, один из которых скоро собирался уходить, а перспектива присутствия в команде всего одного инженера по обеспечению надёжности сайта (SRE, Site Reliability Engineer) выглядела удручающе.
Не то, чтобы SRE работали полностью в одиночку. Какое-то время у нас практиковалась работа инженеров по графику, но мы не особо преуспевали в обучении людей работе с особо каверзными частями стека, лежащего в основе нашего приложения. В результате сменные сотрудники много времени тратили на подтверждение оповещений и их мониторинг, но лишь изредка им удавалось успешно вникать в суть и исправлять проблемы или значительно улучшать работу системы.
По сути, система удерживалась на плаву благодаря некоему общему стержню и индивидуальным усилиям сотрудников, что явно нельзя назвать успешной долгосрочной стратегией. Нам требовалась грамотная структура команды, чтобы мы перестали зависеть от возможности одного человека отладить любую проблему.
▍ Этап 4: команда инфраструктуры платформы
Для этого где-то год назад мы создали команду инфраструктуры платформы (PIT, Platform Infrastructure Team), которая подчинялась техническому директору. Эта команда включала по несколько человек на каждый часовой пояс, обеспечивая круглосуточное покрытие задач операционной деятельности, инфраструктуры и всей связанной с этим работы.
Для меня это стало значительным событием — я, наконец, перестал выходить на дежурства.
Кроме того, это был первый раз, когда я реально почувствовал, что теперь у нас есть команда, которая накапливает опыт. Спустя десять лет постоянного беспокойства то об одном, то о другом, мы всё ещё знали недостаточно, допускали нелепые ошибки и часто меняли платформы. Так что появление дорожной карты, ведущей к стабильности и профессионализму, стало огромным облегчением.
Первое, что сделала команда PIT — это завершила кучу недоделанных проектов инфраструктуры и по максимуму отсекла её неиспользуемую часть. Попутно с этим они должным образом задокументировали процесс дежурств и быстро избавились от лишней сложности. Это моментально повысило эффективность всех участников команды, а также дало им чувство владения системой.
Официальная кепка нашей команды инфраструктуры платформы на голове технического директора Леона
Но работа до сих пор продолжается, потому что накапливание опыта в сложных областях происходит небыстро. Зато сейчас я впервые за всё время уверен в команде и реально горжусь тем, чего нам удалось достичь за один год.
Кстати, мы до сих пор на AWS, но это не означает, что мы никогда не будем менять платформу. Всегда полезно исследовать новые горизонты, и мы немало времени провели, изучая возможность переезда с облака в управляемый дата-центр. Тем не менее приятно осознавать, что потребности в этом у нас нет.
▍ Если бы у меня была машина времени
Если бы я имел возможность вернуться в 2012 год и дать себе несколько рекомендаций, какими бы они были?
Я бы дал себе много мелких советов и три больших. В обоих случаях смысл сводится к трате чуть большего количества денег для избежания серьёзных головняков.
- Использовать управляемые сервисы как можно дольше. Мы поставили себе сильную подножку, съехав с Heroku после всего нескольких месяцев размещения. Нам следовало оставаться на этой платформе в течение нескольких лет — так много времени было потрачено на управление серверами, которое могло осуществляться за нас в тот критический период начала существования проекта.
- Организовать PIT раньше. Мне следовало организовать команду профессионалов, желающих работать в этой области, намного раньше. Не в период размещения на Heroku, но сразу, когда мы достигли реальных масштабов и перестали справляться с инфраструктурой.
- Больше думать о себе. По какой-то причине я всегда с трудом ставил в приоритет проекты, способные уменьшить число тревожных оповещений, упростить систему дежурства или позволить мне лучше высыпаться. Так было до того момента, когда мои нервы не выдержали, и я перераспределил значительную часть бюджета на организацию команды по обслуживанию инфраструктуры. Возможность качественно высыпаться очень положительно сказывается в коммерческом плане, и это нисколько не эгоистично — ставить её в приоритет перед другими вещами, которые можно поручить отдельной команде специалистов.
▍ Сноски
1. Думаю, что по мере того, как мы приближаемся ко всё менее сложной в экономическом плане эпохе, продукты вроде Twilio и Stripe сталкиваются с похожей проблемой.
2. Подробности о том, что пошло не так, можете прочесть в руководстве Heroku по развёртыванию Unicorn, в частности раздел Slow Clients. Этот раздел попался мне на глаза через некоторое время после звонка инженера Heroku, который сообщил о проблеме. Впоследствии я сменил Unicorn на Puma.
3. В итоге я столкнулся с изъяном подготовленных выражений (prepared statements) в Rails 4.2, который, по всей видимости, вызывал как раз ту проблему, что наблюдалась у нас. Вот яркий момент из прошлого. В ту ночь я прекрасно выспался!
4. Тогда мы думали, что сервис Digital Ocean реально нестабилен и постоянно отключает нас от сети на время обслуживания. Иногда это так и было, но в те дни причиной также могла быть наша некомпетентность.
5. Кстати, большинство из знакомых мне людей до сих пор используют серверы.