Как-то так исторически сложилось, что IT-индустрия по любому поводу разбивается на два условных лагеря: которые «за» и которые «против». Причем предмет споров может быть абсолютно произвольным. Какая ОС лучше: Win или Linux? На смартфоне Android или iOS? Хранить все в облаках или заливать на холодные RAID-хранилища и класть винты в сейф? Имеют ли PHP-шники право называться программистами? Эти споры носят, временами, исключительно экзистенциальный характер и не имеют под собой никакой прочей, кроме спортивного интереса, базы.
Так уж получилось, что с появлением контейнеров и всей этой любимой нами кухни с докером и условным k8s начались и споры «за» и «против» использования новых возможностей в различных сферах бэкэнда. (Заранее оговоримся, что хотя чаще всего в данном рассуждении в качестве оркестратора будет указываться Kubernetes, принципиального значения выбор именно этого инструмента не имеет. Вместо него можно подставить любой другой, какой вам кажется наиболее удобным и привычным.)
И, казалось бы, был бы это простой спор между двумя сторонами одной медали. Такой же бессмысленный и беспощадный, как извечное противостояние Win vs Linux, в котором адекватные люди вполне себе существуют где-то посередине. Вот только в случае контейнеризации не все так просто. Обычно в таких спорах не бывает правой стороны, но в случае «применять» или «не применять» контейнеры для хранения БД все становится с ног на голову. Потому что в определённом смысле правы и сторонники и противники подобного подхода.
Светлая Сторона
Кратко описать аргументацию Светлой Стороны можно одной фразой: “Алло, 2к19 за окном!” Звучит как популизм, безусловно, но если вникать в ситуацию детально, там есть свои плюсы. Их-то сейчас и разберём.
Предположим, у вас есть крупный веб-проект. Он мог изначально строиться на основе микросервисного подхода, либо же в какой-то момент пришёл к нему эволюционным путём — это не очень важно, на самом деле. Вы раскидали наш проект по отдельным микросервисам, настроили оркестрацию, балансировку нагрузки, масштабирование. И теперь с чистой совестью попиваете мохито в гамаке во время хабра-эффектов вместо того, чтобы поднимать упавшие сервера. Но во всех действиях надо быть последовательным. Очень часто контейнеризируется только непосредственно само приложение — код. А что ещё у нас есть помимо кода?
Правильно, данные. Сердце любого проекта — его данные: это может быть как типичная СУБД — MySQL, Postgre, MongoDB, так и хранилища, используемых для поиска (ElasticSearch), key-value хранилища для кеширования — например, redis, и т. д. Сейчас мы не будем говорить о кривых вариантах реализации бэкэнда, когда БД падает из-за плохо написанных запросов, а вместо этого поговорим об обеспечении отказоустойчивости этой самой БД под клиентской нагрузкой. Ведь когда мы контейнеризируем наше приложение и позволяем ему свободно масштабироваться для обработки любого количество входящих запросов, это закономерно увеличивает и нагрузку на базу данных.
Фактически, канал обращения к базе данных и сервер, на котором она крутится, становятся игольным ушком в нашем прекрасном контейнеризированном бэкэнде. При этом основной мотив контейнерной виртуализации — подвижность и пластичность структуры, позволяющие организовать распределение пиковой нагрузки по всей доступной нам инфраструктуре максимально эффективно. То есть, если мы не контейнеризируем и не раскатываем по кластеру все имеющиеся элементы системы — мы допускаем очень серьезную ошибку.
Намного логичнее кластеризировать не только само приложение, но и сервисы, отвечающие за хранение данных. При кластеризации и разворачивании независимо работающих и распределяющих между собой нагрузку веб-серверов в k8s мы уже решаем проблему синхронизации данных — тех же комментариев к постам, если приводить в пример какое-то СМИ или блогоплатформу. У нас в любом случае заводится внутрикластерное, пусть даже виртуальное, представление БД как ExternalService. Вопрос в том, что сама БД пока не кластеризирована — развернутые в кубике веб-серверы забирают информацию об изменениях из нашей статичной боевой базы, которая крутится отдельно.
Чувствуете подвох? Мы используем k8s или Swarm для того, чтобы распределить нагрузку и избежать падения основного веб-сервера, но мы не делаем этого для БД. Но ведь если упадет БД, то во всей нашей кластеризированной инфраструктуре нет смысла — толку нам от пустых веб-страниц, возвращающих ошибку доступа к базе данных?
Именно поэтому кластеризировать нужно не только веб-серверы, как это обычно и делается, но и инфраструктуру базы данных. Только таким образом мы можем обеспечить полноценно работающую в одной упряжке, но при этом независимую друг от друга структуру. При этом даже если у нас «рухнет» половина из нашего бэкэнда под нагрузкой — остальная выживет, и система синхронизации БД между собой в пределах кластера и возможность бесконечного масштабирования и разворачивания новых кластеров поможет быстро выйти на необходимые мощности — были бы стойки в дата-центре.
Кроме того, распределенная в кластерах модель БД позволяет уносить эту самую БД туда, где она необходима; если мы говорим о глобальном сервисе, то довольно нелогично крутить веб-кластер где-то в районе Сан-Франциско и при этом гонять пакеты при обращении к базе данных в Подмосковье и обратно.
Также контейнеризация БД позволяет выстроить все элементы системы на одном уровне абстракции. Что, в свою очередь, делает возможным управление этой самой системой прямо из кода, разработчиками, без активного привлечения админов. Подумалось разработчикам, что нужна отдельная СУБД для нового подпроекта — легко! написали yaml-файл, загрузили в кластер и готово.
Ну и само собой, внутренняя эксплуатация упрощается в разы. Скажите, сколько раз вы зажмуривались в моменты, когда новый член команды совал руки в боевую БД по работе? Которая у вас, по факту, одна и вот прямо сейчас крутится? Конечно, все мы тут люди взрослые, и у нас где-то есть свеженький бэкап, а еще дальше — за полкой с бабушкиными огурцами и старыми лыжами — еще один бэкап, возможно даже на холодном хранилище, потому что однажды уже ваш офис горел. Но все равно, каждое введение нового члена команды, имеющего доступ к боевой инфраструктуре и, конечно же, к боевой базе данных — это ведро валидола для всех окружающих. Ну кто его, новичка, знает, может он косорукий? Страшно, согласитесь.
Контейнеризация и, по сути, распределенная физическая топология БД вашего проекта помогает подобных валидольных моментов избежать. Не доверяете новичку? Окей! Поднимем ему собственный кластер для работы и отключим от остальных кластеров БД — синхронизация только по ручному пушу и синхронному повороту двух ключей (один тимлиду, второй админу). И все счастливы.
А теперь настало время переобуться в противников кластеризации БД.
Тёмная Сторона
Рассуждая, почему же не стоит контейнеризировать базу данных и продолжать крутить ее на одном центральном сервере, не будем опускаться до риторики ортодоксов и утверждений вида «деды крутили БД на железе, и мы будем!» Вместо этого давайте попробуем придумать ситуацию, в которой контейнеризация действительно приносила бы ощутимые дивиденды.
Согласитесь, проектов, которым реально нужна база в контейнере, можно пересчитать по пальцам одной руки не самого лучшего фрезеровщика. В большинстве своем, даже само использование k8s или Docker Swarm бывает избыточно — довольно часто к этим инструментам прибегают из-за общей хайповости технологий и установок «всевышних» в лице гендиров загнать все в облака и контейнеры. Ну, потому что сейчас это модно и все так делают.
Минимум в половине случаев использование кубернетиса или просто докера на проекте избыточно. Вопрос в том, что не все команды или аутсорс-компании, нанятые обслуживать инфраструктуру клиента, отдают себе отчет в этом. Хуже — когда контейнеры навязываются, потому что это встает в определенное количество монет клиенту.
Вообще, бытует мнение, что докер/кубик-мафия тупо подминает под себя клиентов, отдающих эти инфраструктурные вопросы на аутсорс. Ведь для того, чтобы работать с кластерами, нужны инженеры, которые способны на это и понимают вообще архитектуру внедренного решения. Мы как-то уже описывали наш кейс с изданием Republic — там мы обучили команду клиента работать в реалиях кубернетиса, и все остались довольны. И это было порядочно. Зачастую же «внедряльщики» k8s берут инфраструктуру клиента в заложники — ведь теперь только они понимают, как там все работает, на стороне клиента специалистов нет.
А теперь представьте, что таким образом мы отдаем не только веб-серверную часть на откуп аутсорсу, но еще и обслуживание БД. Мы говорили, что БД — это сердце, а потеря сердца фатальна для любого живого организма. Короче, перспективы не самые лучшие. Так что вместо хайпового кубернетиса многим проектам стоило бы просто не жлобиться на нормальный тариф на AWS, который решит все проблемы с нагрузкой на их сайт/проект. Но AWS уже не модно, а понты дороже денег — к сожалению, и в IT-среде тоже.
Окей. Возможно, кластеризация проекту реально нужна, но если с со stateless-приложениями все понятно, то как тогда организовать достойное обеспечение сетевой связности кластеризированной базы данных?
Если мы говорим о бесшовном инженерном решении, которым и представляется переход на k8s, то главная наша головная боль — это репликация данных в кластеризируемой БД. Какие-то СУБД изначально довольно лояльно относятся к распределению данных между отдельными своими экземплярами. Многие же другие не столь приветливы. И довольно часто основным аргументом в выборе СУБД для нашего проекта становится отнюдь не способность реплицироваться с минимальными ресурсными и инженерными издержками. Особенно если проект изначально не планировался как микросервисный, а просто эволюционировал в эту сторону.
Думаем, о скорости работы сетевых дисков рассказывать не надо — они медленные. Т.е. реальной возможности, в случае чего, переподнять экземпляр СУБД где-то, где больше, к примеру, процессорных мощностей или свободной оперативной памяти, у нас всё равно нет. Мы очень быстро упрёмся в производительность виртуализированной дисковой подсистемы. Соответственно, СУБД должна быть прибита к своему собственному персональному набору машин, находящихся в непосредственной близости. Либо же надо как-то отдельно окостыливать достаточно быструю синхронизацию данных на предполагаемые резервы.
В продолжение темы виртуальных ФС: Docker Volumes, к сожалению, не беспроблемны. В целом, в таком деле как долгосрочное надёжное хранение данных хотелось бы обходиться максимально простыми технически схемами. И добавление нового слоя абстракции из ФС контейнера в ФС родительского хоста — уже само по себе риск. Но когда ещё и в работе системы обеспечения контейнеризации возникают сложности с транслированием данных между этими слоями, тогда уж совсем беда. На данный момент большая часть известных прогрессивному человечеству проблем вроде бы искоренена. Но сами понимаете, чем сложнее механизм, тем проще он ломается.
В свете всех этих «приключений» намного выгоднее и проще держать БД в одном месте, и даже если вам потребовалась контейнеризация приложения — пусть оно крутится само по себе и через распределительный шлюз получает одновременную связь с БД, которая будет читаться и писаться лишь один раз и в одном месте. Такой подход снижает вероятность ошибок и рассинхронизаций до минимальных значений.
К чему мы ведем? К тому, что контейнеризация БД уместна там, где в ней есть реальная необходимость. Нельзя запихнуть базу фулл-аппа и крутить ее так, будто бы у вас два десятка микросервисов — это так не работает. И это нужно четко понимать.
Вместо вывода
Если вы ждете внятного вывода «виртуализировать или нет БД», то огорчим: его здесь не будет. Потому что при создании любого инфраструктурного решения надо руководствоваться не модой и прогрессом, а в первую очередь, здравым смыслом.
Существуют проекты, на которые принципы и инструменты, идущие с кубернетисом, ложатся идеально, и в таких проектах наступает мир хотя бы в бэкэнд-области. А есть проекты, которым нужна не контейнеризация, а нормальная серверная инфраструктура, потому что они принципиально не могут перемасштабироваться под микросервисную кластерную модель, ибо упадут.
Источник: habr.com