Хабрахабр

«Битрикс24»: «Быстро поднятое не считается упавшим»

На сегодняшний день у сервиса «Битрикс24» нет сотен гигабит трафика, нет огромного парка серверов (хотя и существующих, конечно, немало). Но для многих клиентов он является основным инструментом работы в компании, это настоящее business-critical приложение. Поэтому падать — ну, никак нельзя. А что если падение все-таки случилось, но «восстал» сервис так быстро, что никто ничего и не заметил? И как удаётся реализовать при этом failover без потери качества работы и количества клиентов? Александр Демидов, директор направления облачных сервисов «Битрикс24», рассказал для нашего блога о том, как за 7 лет существования продукта эволюционировала система резервирования.

Главная сложность, наверное, была в следующем: до запуска в паблик в виде SaaS этот продукт существовал просто в формате коробочного решения.
«В виде SaaS мы запустили „Битрикс24“ 7 лет назад. И мы к 2012 году решили, что хотим запустить это как SaaS, администрируя самостоятельно, обеспечивая отказоустойчивость и надёжность. Клиенты покупали его у нас, размещали у себя на серверах, заводили корпоративный портал — общее решение для общения сотрудников, хранения файлов, ведение задач, CRM, вот это всё. Опыт мы набирали в процессе, потому что до тех самых пор у нас его просто не было — мы были лишь производителями ПО, не сервис-провайдерами.

Он расстроился, конечно, но пошёл и купил на другом сайте. Запуская сервис, мы понимали, что самое главное — это обеспечить отказоустойчивость, надежность и постоянную доступность сервиса, потому что если у вас простой обычный сайт, магазин, например, и он упал у вас и лежит час — страдаете только вы сами, вы теряете заказы, вы теряете клиентов, но для самого вашего клиента — для него это не очень критично. Потому что вся работа может встать, если что-то внутри работать не будет. А если это приложение, на которое завязана вся работа внутри компании, коммуникации, решения, то самое ключевое — это завоевать доверие пользователей, то есть не подводить их и не падать.

Битрикс.24 как SaaS

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

Увы, запускать критически устойчивый веб-сервис на этом невозможно. Типичное веб-приложение на тот момент — это один сервер, на котором крутится какой-то код php, база mysql, файлы загружаются, документы, картинки кладутся в папочку upload – ну и всё это работает. Там распределенный кэш не поддерживается, репликация баз данных не поддерживается.

Разделить логику продукта и, собственно, хранение данных. Мы сформулировали требования: это умение размещаться в разных локейшнах, поддерживать репликацию, в идеале размещаться в разных географически распределённых дата-центрах. Из этих соображений сложились, собственно, требования к продукту, который мы как раз в течение года и дорабатывали. Динамически уметь масштабироваться по нагрузке, статику вообще вынести. Поддержку репликации mysql на уровне самого продукта: то есть разработчик, который пишет код — не задумывается, как его запросы будут распределяться, он использует наш api, а мы умеем правильно распределять запросы на запись и на чтение между мастерами и слейвами. За это время в платформе, которая получилась единой — для коробочных решений, для нашего собственного сервиса, — мы сделали поддержку тех вещей, которые нам были необходимы.

Поэтому это было удобно и для нас как для сервиса, и для разработчиков, которые работают с коробочным решением: если они используют просто наш api для работы, они не задумываются, где в итоге файл сохранится, локально на файловой системе или попадёт в объектное файловое хранилище. Мы сделали поддержку на уровне продукта различных облачных объектных хранилищ: google storage, amazon s3, — плюс, поддержка open stack swift.

В 2012 году мы запускались полностью в Amazon AWS, потому что у нас уже был опыт работы с этой платформой — наш собственный сайт там размещался. В итоге мы сразу решили, что будем резервироваться на уровне целого дата-центра. Нагрузка балансируется — на тот момент амазоновским elb, но чуть позже мы пришли к собственным балансировщикам, потому что нам нужна была более сложная логика. Нас привлекало то, что в каждом регионе в Amazon’e есть несколько зон доступности — по сути, (в их терминологии) несколько дата-центров, которые более-менее друг от друга независимы и позволяют нам резервироваться на уровне целого дата-центра: если он вдруг выходит из строя, базы реплицируются master-master, серверы веб-приложений зарезервированы, а статика вынесена в объектное хранилище s3.

Что хотели — то и получили…

Все базовые вещи, которые мы хотели обеспечить — отказоустойчивость самих серверов, веб-приложений, баз данных — все работало хорошо. Самый простой сценарий: если у нас выходит из строя какое-то из веб-приложений, то тут всё просто — они выключаются из балансировки.

Работал амазоновский автоскейлинг: когда нагрузка вырастала, добавлялись новые машины в автоскейлинг-группу, нагрузка распределялась на новые машины — всё было хорошо. Вышедшие из строя машины балансировщик (тогда это был амазоновский elb) сам помечал unhealthy, выключал распределение нагрузки на них. Схема за все эти годы немножко менялась, но продолжает работать: она простая, понятная, и никаких сложностей с этим нет. С нашими балансировщиками логика примерна та же самая: если что-то случается с сервером приложений, мы убираем с него запросы, выкидываем эти машины, стартуем новые и продолжаем работать.

Поэтому мы имеем возможность выключить из работы базу данных, перераспределив нагрузку на второй дата-центр. Мы работаем по всему миру, пики нагрузки у клиентов абсолютно разные, и, по-хорошему, мы должны иметь возможность проводить те или иные сервисные работы с любыми компонентами нашей системы в любое время – незаметно для клиентов.

— Трафик мы переключаем на работающий дата-центр — если это авария на дата-центре, то полностью, если это наши плановые работы с какой-то одной базой, то мы часть трафика, обслуживающего этих клиентов, переключаем на второй дата-центр, приостанавливается репликация. Как это все работает? Работы заканчиваем, репликация восстанавливается, и мы возвращаем всю нагрузку назад. Если нужны новые машины для веб-приложений, так как выросла нагрузка на втором дата-центре, они автоматом стартуют. А если это авария, то мы делаем всё банально: в системе мониторинга используем механизм event-handlers. Если нам надо зеркально провести какие-то работы во втором ДЦ, например, установить системные обновления или изменить настройки во второй базе данных, то, в общем, повторяем всё то же самое, просто в другую сторону. У нас для каждой базы прописано, какой сервер является для нее failover’ом, и куда нужно переключить трафик в случае её недоступности. Если у нас срабатывает несколько проверок и статус переходит в critical, то у нас запускается этот handler, обработчик, который может выполнить ту или иную логику. В принципе, подобные механизмы есть практически в любой системе мониторинга, что-то более сложное мы пока не используем, но возможно когда-то будем. Мы — так исторически сложилось — используем в том или ином виде nagios или какие-либо его форки. Сейчас мониторинг срабатывает на недоступность и имеет возможность что-то переключить.

Все ли мы зарезервировали?

У нас много клиентов из США, много клиентов из Европы, много клиентов, которые ближе к Востоку — Япония, Сингапур и так далее. Разумеется, огромная доля клиентов в России. То есть работа далеко не в одном регионе. Пользователям хочется быстрого отклика, есть требования по соблюдению различных локальных законов, и внутри каждого региона мы резервируемся на два дата-центра, плюс есть какие-то дополнительные сервисы, которые, опять же, удобно размещать внутри одного региона — для клиентов, которые в этом регионе работают. Обработчики REST, серверы авторизации, они менее критичны для работы клиента в целом, по ним можно переключаться с небольшой приемлемой задержкой, но не хочется изобретать велосипеды, как их мониторить и что с ними делать. Поэтому по максимуму мы пытаемся использовать уже существующие решения, а не развивать у себя какую-то компетенцию по дополнительным продуктам. И где-то мы банально используем переключение на уровне dns, причем живость сервиса определяем тем же самым dns. В Amazon есть сервис Route 53, но это не просто dns, в который можно записи внести и всё, — он гораздо более гибкий и удобный. Через него можно построить гео-распределённые сервисы с геолокациями, когда вы с его помощью определяете, откуда пришёл клиент, и даёте ему те или иные записи — с его помощью можно построить failover-архитектуры. Те же самые health-checks настраиваются в самом Route 53, вы задаёте endpoint, которые мониторятся, задаёте метрики, задаёте, по каким протоколам определять «живость» сервиса — tcp, http, https; задаёте периодичность проверок, определяющих, сервис живой или нет. И в самом dns прописываете, что будет primary, что будет secondary, куда переключаться, если срабатывает health-check внутри route 53. Всё это можно сделать какими-то другими инструментами, но чем это удобно — один раз настроили и потом вообще не думаем о том, как у нас делаются проверки, как у нас идёт переключение: всё работает само.

Мало ли, вдруг с ним что-то случится? Первое «но»: а как и чем резервировать сам route 53? Здесь мы стелем себе соломку заранее. Мы, к счастью, ни разу на эти грабли не наступали, но опять же, впереди у меня будет рассказ, почему мы задумывались, что всё-таки резервировать надо. API Amazon'a позволяет их спокойно отдавать в JSON, и у нас поднято несколько резервных серверов, куда мы это конвертируем, выгружаем в виде конфигов и имеем, грубо говоря, бэкапную конфигурацию. Несколько раз в сутки мы делаем полную выгрузку всех зон, которые у нас в route 53 заведены. В случае чего мы можем быстро развернуть её вручную, не потеряем данные настроек dns.

Сам балансировщик! Второе «но»: что в этой картине ещё не зарезервировано? У нас есть домены bitrix24.ru, bitrix24.com, .de — сейчас их штук 13 разных, которые работают по самым разным зонам. У нас распределение клиентов по регионам сделано очень просто. Так удобнее распределять по регионам, в зависимости от того, какая где пиковая нагрузка по сети. Мы пришли к следующему: в каждом регионе — свои балансировщики. Если происходит какая-то проблема с группой балансировщиков, то они резервируются на других площадках, и переключение между ними делается с помощью той же самой route53, потому что за счет короткого ttl переключение происходит максимум в течение 2, 3, 5 минут. Если это сбой на уровне какого-то одного балансировщика, то он просто выводится из эксплуатации и убирается из dns.

S3, правильно. Третье «но»: что еще не зарезервировано? Но история показывает, что происходит по-другому. Мы, размещая файлы, которые храним у пользователей в s3, – искренне верили, что он бронебойный и ничего там резервировать не надо. Вообще, Amazon описывает S3 как фундаментальный сервис, потому что сам Amazon использует S3 для хранения образов машин, конфигов, образов AMI, снэпшотов… И если падает s3, как это однажды случилось за эти 7 лет, сколько мы bitrix24 эксплуатируем, он за собой веером тянет кучу всего — недоступность старта виртуалок, сбой в работе api и так далее.

Поэтому мы пришли к следующей схеме: ещё несколько лет назад серьёзных объектных публичных хранилищ в России не было, и мы рассматривали вариант делать что-то своё… К счастью, мы этого делать не начали, потому что закопались бы в ту экспертизу, которой мы не обладаем, и наверняка накосячили бы. И упасть S3 может — так случилось однажды. Мы в итоге пришли к мысли, что хотим иметь, во-первых, резервирование, во-вторых, возможность работы с локальными копиями. Сейчас s3-совместимые хранилища есть у Mail.ru, есть у Яндекса, есть еще у ряда провайдеров. Нам не потребовалось каких-то серьёзных доработок по коду внутри приложения, и мы сделали следующий механизм: в s3 есть триггеры, которые срабатывают на создание/удаление объектов, у Amazon есть такой сервис, как Лямбда — это serverless запуска кода, который выполнится как раз при срабатывании тех или иных триггеров. Для конкретно российского региона мы используем сервис Mail.ru Hotbox, который по api совместим с s3.

Чтобы полноценно запустить работу с локальными копиями данных, нам нужна ещё обратная синхронизация, чтобы клиенты, которые находятся в российском сегменте, могли работать с хранилищем, которое к ним ближе. Мы сделали очень просто: если у нас срабатывает триггер, мы выполняем код, который скопирует объект в хранилище Mail.ru. Если мы видим, что клиент разместил какой-то файл, то мы у себя на уровне кода помещаем событие в очередь, обрабатываем его и делаем обратную репликацию. Mail вот-вот доделает триггеры у себя в хранилище — можно будет уже на уровне инфраструктуры исполнять обратную синхронизацию, пока же мы это делаем на уровне нашего собственного кода. Поэтому мы ждём до конца, когда появятся триггеры на уровне хранилища, чтобы независимо от того, откуда мы выполнили код, объект, который к нам попал, копировался в другую сторону. Чем она плоха: если у нас происходит какая-то работа с нашими объектами вне нашего продукта, то есть какими-то внешними средствами, мы это не учтём.

Если всё хорошо, мы работаем с тем хранилищем, которое к нам ближе: то есть наши клиенты, которые в Amazon, они работают с S3, а те, кто работает в России, они работают с Hotbox. На уровне кода у нас для каждого клиента прописываются оба хранилища: одно считается основным, другое бэкапным. Мы этот флажок можем ставить независимо по регионам и можем их туда-сюда переключать. Если срабатывает флажок, то у нас должен подключиться failover, и мы клиентов переключаем на другое хранилище. Один раз это уже случилось. На практике еще этим не пользовались, но механизм этот предусмотрели и думаем, что когда-то нам это самое переключение понадобится и пригодится.

Ой, а у вас Amazon сбежал…

В этом апреле — годовщина начала блокировок Телеграмм в России. Самый пострадавший провайдер, который под это попал, — Amazon. И, к сожалению, больше пострадали российские компании, которые работали на весь мир.

Если компания глобальная и Россия для неё — совсем маленький сегмент, 3-5% — ну, так или иначе, можно ими пожертвовать.

Если это сугубо российская компания — я уверен, что нужно размещаться локально — ну просто самим пользователям будет удобно, комфортно, рисков будет меньше.

Связность сегментов важна, и работать друг с другом они так или иначе должны. А если это компания, которая работает глобально, и у неё примерно поровну клиентов из России, и где-то по миру?

Спасибо этим самым провайдерам — они письмо успешно всем слили, и возникло понимание, что связность c Amazon может развалиться. Ещё в конце марта 2018-го Роскомнадзор направил самым большим операторам письмо, о том, что они планируют заблокировать несколько миллионов ip Amazon, для того чтобы заблокировать… мессенджер Zello. За несколько дней мы эти серверы настроили, подняли, и в общем, к моменту начала блокировок подготовились. Это была пятница, мы в панике прибежали к коллегам из servers.ru, со словами: «Друзья, нам нужно несколько серверов, которые будут стоять не в России, не в Amazon, а, например, где-нибудь в Амстердаме», для того чтобы иметь возможность хотя бы каким-нибудь образом поставить там собственные vpn и proxy для каких-то endpoint'ов, на которые мы никак не можем влиять, например endpont'ы того же s3 — нельзя попытаться поднять новый сервис и получить другой ip, нам все равно нужно туда достучаться. (Но это ровно до того момента, когда начали блокировать телеграм.) Настроив возможности обхода и поняв, что блокировку не ввели, мы, тем не менее, не стали все это дело разбирать. Любопытно, что РКН, посмотрев на шумиху и поднятую панику, сказал: «Не, мы сейчас блокировать ничего не будем». Так, на всякий случай.

Я вот вчера ночью смотрел: около миллиона ip продолжают блокироваться. И вот в 2019 году мы таки живём в условиях блокировок. Внезапно. Правда, Amazon почти в полном составе разблокировали, в пике доходило до 20 миллионов адресов… В общем, реальность такова, что связности, хорошей связности — ее может не быть. Или, как мы видели, не совсем техническим. Ее может не быть по техническим причинам — пожары, экскаваторы, всё такое. Но в простом варианте, как мы или еще помельче, можно на всякий случай иметь резервирование на уровне серверов, поднятых где-то еще, настроенных заранее vpn, proxy, с возможностью быстро на них переключать конфигурацию в тех сегментах, которые у вас критичны по связности. Поэтому кто-то большой и крупный, с собственными AS-ками, наверное, может этим рулить другими путями, — direct connect и прочие вещи уже на уровне l2. Это нам пригодилось неоднократно, когда начались блокировки Amazon, мы через них пускали в самом худшем случае как раз трафик S3, но постепенно все это разрулилось.

А как резервировать… целого провайдера?

Сейчас сценария на случай выхода из строя всего Amazon у нас нет. У нас похожий сценарий есть для России. Мы в России размещались у одного провайдера, у которого мы выбирали, чтобы было несколько площадок. И год назад мы столкнулись с проблемой: даже несмотря на то, что это два дата-центра, уже на уровне конфигурации сети провайдера могут быть проблемы, которые затронут все равно оба дата-центра. И мы можем получить недоступность на обеих площадках. Конечно, так и случилось. Мы в итоге пересмотрели архитектуру внутри. Она не очень сильно изменилась, но для России у нас сейчас две площадки, которые не у одного провайдера, а у двух разных. Если у одного что-то выйдет из строя, мы можем переключиться на другого.

Поэтому мы теоретически имеем представление о том, что мы, может быть, сделаем резервирование «Amazon — не Amazon», но на практике такого пока нет. Гипотетически мы для Amazon рассматриваем возможность резервировать на уровне другого провайдера; может быть, Google, может быть, еще кто-то… Но пока мы наблюдали на практике, что если у Amazon аварии на уровне одной availability-зоны случаются, то аварии на уровне целого региона — достаточно редкое явление.

Пара слов про автоматизацию

Всегда ли нужна автоматика? Тут уместно вспомнить эффект Даннинга-Крюгера. По оси «х» наши знания и опыт, которого мы набираемся, а по оси «у» — уверенность в наших действиях. Мы сначала не знаем ничего и совсем не уверены. Затем мы знаем немножко и становимся мега-уверенными — это так называемый «пик глупости», хорошо иллюстрируется картинкой «слабоумие и отвага». Дальше мы уже немножко научились и готовы идти в бой. Потом мы наступаем на какие-то мега-серьёзные грабли, попадаем в долину отчаяния, когда вроде что-то знаем, а на самом деле мы многого не знаем. Затем, по мере набора опыта, становимся уже более уверенными.

Мы стартовали — мы ничего не умели, практически все работы производились вручную. Наша логика про различные переключения автоматически на те или иные аварии — она очень хорошо описывается этим графиком. И вдруг мы наступаем на мега-грабли: у нас срабатывает false positive, и мы переключаем туда-сюда трафик, когда, по-хорошему, не стоило этого делать. Потом мы поняли, что можно на всё навесить автоматику и, типа, спать спокойно. А дальше приходим к пониманию, что ко всему надо относиться с умом. Следовательно, ломается репликация или ещё что-нибудь — вот та самая долина отчаяния. Но! То есть имеет смысл положиться на автоматику, предусмотрев возможность ложного срабатывания. если последствия могут быть разрушительными, то лучше отдать это на откуп дежурной смене, дежурным инженерам, которые убедятся, проследят, что действительно авария, и необходимые действия выполнят вручную…

Заключение

За 7 лет мы прошли путь от того, что, когда что-то падало, — была паника-паника, к пониманию, что проблем не существует, есть только задачи, их необходимо — и можно — решать. Когда вы строите какой-то сервис, посмотрите на него взглядом сверху, оцените все риски, которые могут случиться. Если вы сразу видите их — то заранее предусматривайте резервирование и возможность построения отказоустойчивой инфраструктуры, потому что любая точка, которая может выйти из строя и привести к неработоспособности сервиса — она обязательно это сделает. И даже если вам кажется, что какие-то элементы инфраструктуры точно не выйдут из строя — типа того же s3, всё равно имейте в виду, что они могут. И хотя бы в теории имейте представление о том, что вы будете с ними делать, если что-то все-таки случится. Имейте план по отработке рисков. Когда вы задумываетесь о том, чтобы делать все автоматикой или вручную, — оцените риски: что будет, если автоматика начнёт все переключать — не приведёт ли это к ещё худшей картине по сравнению с аварией? Возможно, где-то нужно использовать разумный компромисс между использованием автоматики и реакцией дежурного инженера, который оценит реальную картину и поймёт, нужно ли с ходу что-то переключить или «да, но не сейчас».

Разумный компромисс между перфекционизмом и реальными силами, временем, деньгами, которые вы можете потратить на ту схему, которая у вас в итоге будет.

Данный текст является дополненной и расширенной версией доклада Александра Демидова на конференции Uptime day 4.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть