19 сентября в Москве состоялся первый тематический митап HUG (Highload++ User Group), который был посвящён микросервисам. На нём прозвучал доклад «Эксплуатация микросервисов: размер имеет значение, даже если у вас Kubernetes», в котором мы поделились обширным опытом компании «Флант» в области эксплуатации проектов с микросервисной архитектурой. В первую очередь он будет полезен всем разработчикам, задумывающимся о применении этого подхода в своём настоящем или будущем проекте.



Представляем видео с докладом (50 минут, гораздо информативнее статьи), а также основную выжимку из него в текстовом виде.

NB: Видео и презентация доступны также в конце этой публикации.

Введение


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

Начну с такого графика, автором которого (в 2015 году) стал Martin Fowler:



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

Дополню этот график для случая использования Kubernetes:



Почему приложению с микросервисами стало лучше? Потому что такая архитектура выдвигает серьёзные требования к архитектуре, которые в свою очередь отлично закрываются возможностями Kubernetes. С другой стороны, часть этой функциональности будет полезна и для монолита, особенно по той причине, что типичный на сегодняшний день монолит — это не совсем монолит (подробности будут далее в докладе).

Как видно, итоговый график (когда и монолитное, и микросервисное приложения в инфраструктуре с Kubernetes) не очень-то отличается от изначального. Далее речь будет идти о приложениях, эксплуатируемых с использованием Kubernetes.

Полезная и вредная микросервисность


И тут главная мысль:



Что же такое нормальная микросервисная архитектура? Она должна приносить вам реальную пользу, увеличивая эффективность работы. Если вернуться к графику, то вот она:



Если называть её полезной, то на другой стороне графика будет вредная микросервисность (мешает работе):



Возвращаясь к «главной мысли»: стоит ли вообще доверять моему опыту? С начала этого года я посмотрел 85 проектов. Не все они были микросервисными (такой архитектурой обладали примерно от трети до половины из них), но это всё равно большое число. Нам (компании «Флант») как аутсорсерам удаётся видеть широкое разнообразие приложений, разрабатываемых как в маленьких компаниях (с 5 разработчиками), так и в крупных (~500 разработчиков). Дополнительным плюсом является то, что мы видим, как эти приложения живут и развиваются на протяжении многих лет.

Зачем микросервисы?


На вопрос о пользе микросервисов есть весьма конкретный ответ у уже упомянутого Martin Fowler:

  1. чёткие границы модульности;
  2. независимый деплой;
  3. свобода выбора технологий.

Я много разговаривал с архитекторами и разработчиками программного обеспечения и спрашивал, зачем им микросервисы. И составил свой список их ожиданий. Вот что получилось:



Если описать «в ощущениях» некоторые из пунктов, то:

  • чёткие границы модулей: вот у нас есть страшный монолит, а теперь всё будет аккуратно разложено по Git-репозиториям, в которых всё «по полочкам», не перемешано тёплое с мягким;
  • независимость деплоя: мы сможем выкатывать сервисы независимо, чтобы разработка шла быстрее (параллельно публиковать новые фичи);
  • независимость разработки: мы можем отдать этот микросервис той команде/разработчику, а тот — другой, благодаря чему сможем быстрее разрабатывать;
  • большая надёжность: если случится частичная деградация (упадёт один микросервис из 20), то перестанет работать лишь одна кнопка, а система в целом продолжит функционировать.

Типовая (вредная) микросервисная архитектура


Чтобы объяснить, почему в реальности всё не так, как мы ожидаем, я представлю собирательный образ микросервисной архитектуры, основанный на опыте из множества различных проектов.

Примером будет служить абстрактный интернет-магазин, собирающийся конкурировать с Amazon или хотя бы OZON. Его микросервисная архитектура выглядит так:



По совокупности причин, эти микросервисы написаны на разных платформах:



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



Каковы её последствия?


У Fowler'а и на этот счёт есть статья — о «расплате» за использование микросервисов:



А мы посмотрим, оправдались ли наши ожидания.

Чёткие границы модулей…


Но сколько микросервисов нам в действительности нужно поправить, чтобы выкатить изменение? Можем ли мы вообще разобраться, как всё работает, без распределённого трассировщика (ведь любой запрос обрабатывается половиной микросервисов)?

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



Независимость деплоя…


Технически она достигнута: мы можем перекатить каждый микросервис отдельно. Но на практике нужно учитывать, что всегда выкатывается множество микросервисов, причём нам нужно учитывать порядок их выката. По-хорошему нам вообще нужно в отдельном контуре тестировать, в правильном ли порядке мы выкатываем релиз.

Свобода выбора технологии…


Она есть. Только стоит помнить, что зачастую свобода граничит с беспределом. Очень важно здесь не выбирать технологии только для того, чтобы «поиграть» с ними.

Независимость разработки…


Как сделать тестовый контур для всего приложения (из такого множества компонентов)? А ведь ещё надо его поддерживать в актуальном виде. Всё это приводит к тому, что реальное количество тестовых контуров, которое мы в принципе можем содержать, оказывается минимальным.

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

Раздельное масштабирование…


Да, но оно ограничено в области используемых СУБД. В приведённом примере архитектуры не будет проблем у Cassandra, но будут у MySQL и PostgreSQL.

Большая надёжность…


Мало того, что в действительности вывод из строя одного микросервиса зачастую ломает корректное функционирование всей системы, так есть ещё и новая проблема: сделать отказоустойчивым каждый микросервис очень сложно. Потому что в микросервисах используются разные технологии (memcache, Redis и т.п.), для каждого нужно всё продумать и реализовать, что, конечно, возможно, но требует огромных ресурсов.

Измеримость нагрузки…


С этим действительно всё хорошо.

«Лёгкость» микросервисов…


У нас не только появились огромные сетевые накладные расходы (приумножаются запросы на DNS и т.п.), но и из-за множества подзапросов мы начали реплицировать данные (хранить кэши), что привело к значительному объёму хранилищ.

И вот каков итог соответствия нашим ожиданиям:



Но и это ещё не всё!


Потому что:

  • Скорее всего нам потребуется шина сообщений.
  • Как сделать консистентный бэкап на нужный момент времени? Единственный реальный вариант — выключить трафик для этого. Но как это сделать на production?
  • Если идёт речь о поддержке нескольких регионов, то организовать устойчивость в каждом из них — очень трудоёмкая задача.
  • Появляется проблема внесения централизованных изменений. Например, если нам нужно обновить версию PHP, то потребуется сделать коммит в каждый репозиторий (а их — десятки).
  • Рост операционной сложности навскидку получается экспоненциальным.

Что со всем этим делать?


Начинайте с монолитного приложения. Опыт Fowler'а говорит о том, что практически все успешные микросервисные приложения начинались с монолита, который стал слишком большим, после чего и был разбит. В то же самое время практически все системы, построенные как микросервисные с самого начала, рано или поздно испытывали серьёзные проблемы.

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

Но что делать, если мы уже оказались в такой ситуации?


Первый шаг к решению любой проблемы — согласиться с ней и понять, что это проблема, что мы больше не хотим страдать.

Если в случае разросшегося монолита (когда у нас закончилась возможность докупать для него ресурсы), мы его разрезаем, то в данном случае получается обратная история: когда чрезмерная микросервисность уже не помогает, а мешает — отрезайте лишнее и укрупняйте!

Например, для рассмотренного выше собирательного образа…

Избавьтесь от самых сомнительных микросервисов:



Объедините все микросервисы, отвечающие за генерацию фронтенда:



… в один микросервис, написанный на одном (современном и нормальном, как вы сами считаете) языке/фреймворке:



У него будет один ORM (одна СУБД) и сначала пара приложений:



… а вообще туда можно перенести гораздо больше, получив такой результат:



Причём в Kubernetes мы всё это запускаем отдельными экземплярами, а значит, что мы всё ещё можем измерять нагрузку и отдельно масштабировать их.

Резюмируя


Посмотрите на картину шире. Очень часто все эти проблемы с микросервисами возникают из-за того, что кто-то взял свою задачу, но хотел «поиграть в микросервисы».

В слове «микросервисы» часть «микро» является лишней. Они «микро» лишь по той причине, что меньше огромного монолита. Но не надо думать о них как о чём-то маленьком.

И для финальной мысли вернёмся к изначальному графику:



Написанное к нему примечание (справа наверху) сводится к тому, что навыки команды, которая делает ваш проект, всегда первичны — именно они сыграют ключевую роль в вашем выборе между микросервисами и монолитом. Если у команды не хватает умений, но она начинает делать микросервисы, история точно будет фатальной.

Видео и слайды


Видео с выступления (~50 минут; к сожалению, оно не передаёт многочисленные эмоции посетителей, что во многом определяло настроение доклада, но уж как есть):



Презентация доклада:



P.S.


Другие доклады в нашем блоге:


Вероятно, вас также заинтересуют следующие публикации:

Комментарии (18)


  1. viiy
    12.10.2018 19:02
    +1

    А после объединения микросервисов в логически связанные сервисы возникает мысль — «а нужен ли нам вобще kubernetes?» Но лучше молчать, а то опозоришься.


    1. distol Автор
      12.10.2018 21:22

      Для нас Kubernetes — это просто один из инструментов. И очень мощный инструмент. И как и у любого мощного инструмента — у него достаточно высокий входной платеж. Нам, конечно же, удобней делать все проекты в Kubernetes, так-как именно для нас — так быстрей и удобней. Понятно, что в общем случае в первую очередь стоит исходить из возможностей команды и реальных потребностей проекта. Во многих может быть проще и правильней два хоста и docker-compose.


    1. stul5tul
      13.10.2018 03:15
      +1

      А после объединения микросервисов в логически связанные сервисы возникает мысль — «а нужен ли нам вобще kubernetes?» Но лучше молчать, а то опозоришься.

      Конечно Kubernetes это оверлишний управляющий софт, казалось бы, но… А чем замените?

      Все равно нужно для серьезного проекта:

      • хоть какой-то надежный деплой, с возможностью отката в случае сбоя деплоя;
      • green-blue deployment или быстрые откаты до предыдущих версий в случае выкатки ошибочного кода;
      • запускать экземпляр сервиса, мониторить здоровье экземпляра сервиса, перезапускать экземпляр сервиса при сбое;
      • мониторить загрузку нод, запускать на менее загруженной ноде;
      • запускать дополнительный экземпляр сервиса при росте нагрузке;
      • направлять и перенаправлять трафик на нужный экземпляр сервиса;
      • staging, тестирование нового функционала на части пользователей;
      • под Kubernetes полным полно адаптированного софта и best practics и готовых к развертыванию пакетов Prometheus/Grafana/ELK, иначе придется настраивать нечто подобное ручками


      В комментариях предложите пожалуйста варианты для реализации описанного выше, но решения проще, чем Kubernetes. Очень нужно.

      Склоняюсь или переплачивать на ненужный фунционал Kubernetes лишним рабочим временем и лишними управляющими нодами Kubernetes.
      Или реализовывать на базе nomad/consul/registrator.


      1. VolCh
        13.10.2018 15:52

        Как минимум большинство требований закрывает docker swarm. Для автомасштабирования нужна будет внешняя обвязка, масштабирующая в ответ на изменение метрик. Изучали этот вариант?


        1. ambrozimikoni
          13.10.2018 23:55

          Как минимум большинство требований закрывает docker swarm.

          habr.com/company/itsumma/blog/345976
          Swarm при смерти
          Когда Соломона Хайкеса спросили жив ли Docker Swarm, он ответил (в Твиттере): «Docker продолжит поддерживать и Kubernetes и Swarm на высшем уровне и будет стимулировать их взаимное развитие. Открытость и возможность выбора создают более здоровую экосистему для всех.» Проблема же здесь в том, что Docker Swarm поддерживается недостаточно хорошо. Совсем нет. Команда разработки Docker Swarm и горстка их опенсурсных разработчиков не смогут тягаться с сообществом Kubernetes. Как бы не был хорош Docker UI, Kubernetes UI гораздо лучше. Это почти как если бы Docker опустился до статуса маргинальной консалтинговой фирмы в мире контейнеров.


          1. VolCh
            15.10.2018 01:24

            Я больше года не слежу за ченжлогами в связи со сменой обязанностей, отвечали лишь по требованиям на текущий (вернее на год+ назад момент).


      1. distol Автор
        13.10.2018 17:34
        -1

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


  1. olegbunin
    12.10.2018 19:21

    Ребят, а поставьте на нас ссылку:
    www.meetup.com/HighLoad-User-Group

    :)

    PS: Сорян, я не увидел ссылку :) Спасибо!


  1. GilevVyacheslav
    12.10.2018 21:22

    разве это всё не очевидно?


    1. distol Автор
      12.10.2018 21:23

      И да и нет. И чем больше я общаюсь с людьми и получаю обратной связи по конкретно этому докладу — скорей нет, чем да. Если вам очевидно — вы молодец!


  1. dab00
    12.10.2018 21:24

    // TODO: рассказать заказчику какая у него должна быть архитектура (и не забыть про Cassandra)


  1. vlsinitsyn
    13.10.2018 02:18

    Полностью согласен с автором. Сейчас микросервисы пихают куда надо и не надо.
    Зачем? Это модно и креативно. Для архитекторов замечательная задача нарисовать много блоков со стрелочками. За хорошие деньги и много думать не надо — разукрупняй все.
    Для программеров, на самом деле, легче и приятней кодить свой маленький модуль на чем хочешь и как хочешь не беспокоясь о смежниках.
    А потом и получается нечто монстрообразное и малопригодное для эксплуатации.
    Но к тому времени проект уже завершен (тупо кончились деньги), все получили свои оплаты и скилы и радостно свалили на новые проекты по внедрению микросервисов.
    Самое смешное, что архитекторы этого ужаса запишут в свои заслуги успешные внедрения микросервисов в крупных организациях и будут просить еще больше денег на следующей работе.


    1. distol Автор
      13.10.2018 17:31
      -1

      Это далеко не всегда так плохо, как вы описываете. По крайней мере "фантазеров" и "дойщиков" сразу видно и с ними все понятно. Очень часто я вижу и у архитекторов и у разработчиков большую и абсолютно искреннюю надежду, что микросервисная архитектура значительно упростит их жизнь, на практике же часто выходит боком. Об этом и пытался рассказать.


      1. vlsinitsyn
        13.10.2018 21:55

        Ну так я и не утверждаю, что архитектура из примера на слайде родилась по причине намеренного саботажа. Все из лучших побуждений, как всегда…
        На самом деле, ключевой, на мой взгляд момент в докладе, что успешное внедрения чаще происходит при движении от монолита. А изначальное планирование такой архитектуры скорее ведет к неудаче. В докладе делается предположение, что это происходит из за лучшего знания предметной области. Я думаю, что это не самая главная причина. Плохое знание предметной области ведет к неудаче и на монолите. Принципиальная же разница в том, на мой взгляд, что при движении от монолита, гораздо более четко и конкретно осознается проблема и для чего именно меняется архитектура. Отсюда проистекает более рациональный, объективно обусловленный подход к проектированию.
        При проектировании же 'с нуля', такого четкого понимания часто нет. А исходят, зачастую, лишь из субъективных, не достаточно обоснованных, представлений о том, что проект должен делаться на микросервисах, недооценивая момент значительного, как предположено в докладе, экспоненциального роста сложности.
        По моему опыту, есть два варианта, почему такое происходит. Один, когда архитектор хорошо знает именно такую архитектуру и изначально закладывает ее в каждый свой проект не особо задумываясь о необходимости. Происходит как в анекдоте про проктолога, который удалял гланды через задний проход. Никто не ставит под сомнения скилы такого специалиста — они у него несомненно имеются. Но зачем?
        Другой, когда кто-то (а часто и весь тим архитекторов во главе с бизнес начальством) в компании, где-то прослушал доклад на тему 'очередная панацея' и, окрыленные услышанным, не имея вообще никакого опыта (все же так просто и очевидно было в докладе на слайдах!), принимается решение — внедрять. Зачем? почему? как? — по ходу разберемся. Вероятность успеха в таком случае — примерно как выиграть в лотерею.


  1. z0mb1ek
    13.10.2018 17:24

    Немного обидно было про 85 проектов за год и везде одно и тоже. Мы зашли сразу с ориентиром на Kubernetes и без 20k dns запросов :)


  1. prozac_ua
    13.10.2018 17:24

    34 микросервиса на слайде. У нас их ~350 и я не вижу как это все работало бы на монолите (или что сейчас аутсорсеры продают).

    «Навыки команды первичны» это 100%. Но причем тут Kubernetes и микросервисы? Buzzwords anchors?


    1. distol Автор
      13.10.2018 17:27

      Но причем тут Kubernetes и микросервисы? Buzzwords anchors?

      Тут я вынужден просить прощения — доклад изначально планировался больше про эксплуатацию и про Kubernetes, как и обычно… а получился больше про архитектуру. Кажется я сказал об этом в начале. В любом случае прошу простить.


    1. ambrozimikoni
      13.10.2018 22:55
      +1

      34 микросервиса на слайде. У нас их ~350 и я не вижу как это все работало бы на монолите (или что сейчас аутсорсеры продают).

      Разве в тексте статьи сказано, что всегда и все должны использовать монолиты?
      У нас как раз проект типа того, что на слайде — интернет-магазин. И да, вполне успешно живет всего на 3 сервисах. Kubernetes используется для reliability