Архитектура приложения
Виртуальные серверы против Docker: НАСТОЯЩИЕ плюсы и минусы
Будут ли будущие приложения по-прежнему использовать контейнеризацию?
Я снова ловлю себя на том, что плыву против постоянно меняющегося течения поп-технологий, чтобы вернуть в нашу индустрию рациональное мышление и разум, которых, кажется, так не хватает в наши дни. Опять же, я, вероятно, получу письмо с ненавистью за то, что напишу это, пусть будет так. Как сказал мне один коллега-инженер: «Эй, Бо, ты не ошибаешься…»
Для справки, только потому, что вы можете что-то сделать или только потому, что все остальные делают это, не означает, что вы должны делать то же самое.
Как архитектор приложений, вам довольно часто приходится смотреть, почему кто-то использует определенную технологию в своем стеке приложений, и задавать действительно сложные вопросы:
- — Почему это действительно здесь? и
- «Почему мы делаем что-то таким образом?» и
- «Какую действительно большую проблему это пытается решить?», и
- «Действительно ли поддержание этого сэкономит деньги компании через десять или более лет — или это просто будет стоить нам много времени и денег, чтобы вырвать его, когда никто не использует или не поддерживает его?»
Это действительно трудные вопросы, на которые должны ответить настоящие архитекторы. Меня не волнует, насколько крута технология прямо сейчас. Как это будет выглядеть через 10–20 лет, когда вас не станет, но компания по-прежнему использует это программное обеспечение, за создание которого они заплатили вам?
В подавляющем большинстве приложений, в 9 случаях из 10, что-то устанавливается в стек технологий, потому что какой-то разработчик (который не был архитектором как таковым) без задней мысли добавил это в кодовую базу или технический стек. Причин тому много и они разные, но «почему», вероятно, можно разделить на: технология была крутой, она пользовалась популярностью в толпе, или с ней было просто интересно работать, или это то, чему я научился. на моей последней работе, и они стремились использовать ту же технологию, которую они уже знали и хорошо знали.
Этот разработчик уже давно перешел к тому, чтобы испортить чужой стек приложений, но его плохие решения теперь навсегда встроены в наше основное приложение. (Вздох)
Нам это действительно нужно?
Но какую РЕАЛЬНУЮ проблему действительно решила эта технология?
Это становится тенденцией среди ведущих промышленников и технологов, а также в моей собственной работе, что лучшая часть на самом деле не является частью; или в случае стека технологий лучшая технология не использует [дополнительную] технологию в стеке.
Это означает, что для того, чтобы добавить технологию или библиотеку в технический стек в наши дни, вам, черт возьми, лучше иметь чертовски вескую причину, исключительный вариант использования, который на самом деле экономит время и деньги компании, и это должно быть чем-то. это не усложняет текущую архитектуру дополнительными ресурсами для использования и управления новой технологией, особенно если она добавляет какой-либо шаг в конвейер CI/CD.
Я знаю. Это звучит жестко. И для некоторых людей это, вероятно, так. Тем не менее, корпоративная архитектура часто сильно отличается от того, что нам удается впихнуть в гараж, стартап или даже приложения для малого бизнеса.
Предприятия не любят меняться, по крайней мере, не очень часто. Изменения стоят дорого, и вы не тот, кто платит по счетам.
К сожалению, в наши дни философия «меньше значит больше» на самом деле не работает в большинстве реальных приложений, потому что есть вероятность, что вы уже внедрили целую массу вредных привычек: ненужные технологии, такие как ORM, абстракции DBAL, фреймворки пользовательского интерфейса и т. д. даже контейнеры в 15 различных средах с командой разработчиков, которая привыкла развертывать в этих хранилищах. Удаление ненужных технологий из стека обойдется дороже, чем их неиспользование. Так что да, я понимаю. Не волнуйтесь, вы в безопасности.
Если он уже есть, не меняйте его. Если только это не убивает ваше время безотказной работы, время отклика становится ледяным, производительность снижается или это препятствует вашему масштабированию. Тогда у вас есть более серьезные проблемы, которые нам нужно решить.
В основном в этой статье я собираюсь сосредоточиться на архитектурных различиях между…
Виртуальные машины против контейнеров
Я был приятно удивлен, а также воодушевлен, узнав, что в архитектурном сообществе в настоящее время бушуют здоровые дебаты о том, какое решение лучше: контейнеры или просто голые виртуальные машины.
Не так уж иронично, что сторонники контейнеров придумали довольно уничижительный термин «монолитный», чтобы описать любого, кто не использует контейнеризацию. Как теперь уничижительно называть приложения толпы контейнеров? Как насчет «сломанных» приложений? Кажется, этот термин подходит.
На самом деле ни один из этих терминов не является точным. Приложения, которые просто развертываются на виртуальных машинах, не обязательно являются «монолитными». На самом деле они могут быть совершенно противоположными. Все зависит от того, какие действительно незначительные отличия в вашей архитектуре.
Откуда взялись контейнеры?
Для тех, кто не знает, контейнеры существуют с момента появления «Linux Containers» или LXC, своего рода программного обеспечения для виртуализации ОС, дебютировавшего в 2008 году. Но на самом деле контейнеры появились только в 2013 году. начал набирать обороты и приниматься людьми, внедряющими Docker, который сам по себе является улучшенной оболочкой для LXC.
Контейнеры лишь немного изменили способ развертывания кода разработчиками в облаке, а преимущества контейнеризации приложений, как я уже упоминал, до сих пор горячо обсуждаются в архитектурных кругах.
Основное различие между виртуальными машинами и контейнерами заключается в том, что виртуальная машина представляет собой виртуализацию оборудования, а контейнер — виртуализацию операционной системы, работающей на виртуальной машине (сервере).
Проще говоря, когда я думаю о контейнере, я просто думаю о «приложении», потому что, в конце концов, это все, что мы запускаем в производство. Приложение, работающее на серверной ОС.
Перенесемся на десятилетие вперед, и границы между виртуализацией оборудования и виртуализацией ОС начинают стираться. До такой степени, что нам нужно спросить себя, действительно ли нам нужна виртуализация контейнеров?
Почему бы просто не использовать виртуальную машину в качестве контейнера и покончить с этим?
"Бо, потому что контейнер объемом 2 ГБ нельзя переносить".
Верно. Я понимаю, но мы говорим здесь не столько о переносимости, сколько о ненужной абстракции. То есть запуск разных приложений на одном сервере с использованием общей ОС. Привет? Apache и Nginx делают это изначально. Виртуализация ОС не требуется. Настройте разные порты для каждого виртуального хоста, как это делает Docker. Бум. Сделанный.
Зачем мне снова контейнер? Серьезно. Что контейнер действительно делает для меня?
Виртуальные машины/серверы
Виртуальная машина или виртуальный сервер — это всего лишь полнофункциональный сервер, работающий на реальном оборудовании, о котором вам не нужно беспокоиться. Гипервизор позаботится о виртуализации, и вам не нужно беспокоиться о том, что у вас есть 15 экземпляров Linux или Windows, работающих где угодно и на любом оборудовании. AWS, Azure и GoogleCloud и др. al., теперь сделайте управление этими «экземплярами» виртуальных серверов детской игрой.
В частности, используя AWS в качестве моего примера, если вы хотите развернуть новый код в распределенном приложении (это будет приложение с балансировкой нагрузки), вы развертываете свой код в своем промежуточном экземпляре, создаете копию этого экземпляра, а затем добавляете новый идентификатор экземпляра к вашей эластичной среде. Elastic Beanstalk от AWS позаботится обо всем остальном. Опять бум. Сделанный.
Да, виртуальная машина — это гораздо больший файл, чем контейнер Docker; и нет, вы не можете переместить экземпляр виртуальной машины AWS, скажем, в GoogleCloud, ну, по крайней мере, пока. Я уверен, что кто-то где-то этим занимается…
Контейнеры
Контейнер — это гораздо меньший файл, чем виртуальная машина, поскольку он содержит только код вашего приложения, а не все файлы, необходимые для запуска полноценного сервера.
Но контейнер немного сложнее, чем просто код вашего приложения. Ваша кодовая база также содержит довольно много файлов конфигурации, которые сообщают контейнерной службе (обычно Docker, обертывающей LXC), как настроить и даже развернуть ваши файлы как изолированное приложение, работающее на вашем экземпляре виртуального сервера с поддержкой LXC (Docker).
В других статьях о контейнерах и виртуальных машинах я заметил, что некоторые люди утверждали, что контейнер на самом деле проще, чем использование виртуальной машины, потому что код контейнера не должен включать все файлы ОС, которые могут раздуваться до гигабайт.
Хотя технически это верно, в реальном мире развертывание кода происходит не совсем так, поэтому сравнение несколько условное. Никто не загружает целые виртуальные машины для развертывания кода. Я могу так же легко развернуть только код приложения на сервере, сконфигурированном для запуска моего приложения без всех необходимых файлов ОС.
На самом деле нет никакой разницы. Просто имейте в виду, что для контейнерного приложения по-прежнему требуется код конфигурации LXC И предварительно настроенный сервер LXC для работы.
Честно говоря, в конце концов, это просто другая конфигурация. Таким образом, контейнерная версия НЕ обязательно проще в этом отношении; на самом деле контейнеры часто требуют гораздо больше кода конфигурации для развертывания, чем просто кодовая база виртуальной машины.
Действительно ли контейнерный код более портативный?
Что некоторые люди ошибаются в своем анализе простоты использования, так это то, что они полагают, что проще использовать контейнеры в случае переносимости кода. Да, вы можете заархивировать и развернуть контейнер здесь, там или где угодно без всех базовых файлов ОС, которые есть у виртуальной машины.
Но это не всегда так просто.
Идея совместного использования контейнера между коллегами и публикой — довольно крутое преимущество. Без сомнения. Однако даже в этом случае контейнер может быть не полностью переносимым, или его нужно «упростить», чтобы он работал с разными версиями ОС, а вам определенно нужны разные контейнеры для разных ОС. Это зависит от того, какая у вас ОС хоста и что она позволяет разрешить.
В случае с локальными машинами вам необходимо установить собственное программное обеспечение виртуальной машины Docker для локального запуска образа Docker. Итак, теперь мы снова вернулись к настройке виртуальных машин. Я просто указываю, что контейнеры не являются какой-то золотой панацеей. Для их запуска требуется много настроек и установка дополнительного программного обеспечения.
«Но, но… развертывание контейнера с кодом вашего приложения так же просто, если не проще, чем развертывание кода на виртуальной машине, работающей в эластичной среде. Верно? Вы просто бросаете контейнер в микросервис, и он просто запускается, верно?»
Ну, не совсем так.
В AWS, используя их ECS (Elastic Container Service), вам по-прежнему необходимо определить и настроить экземпляры хоста, на которых будут работать ваши контейнеры. Взгляните на следующую диаграмму из AWS:
Вы, как разработчик, часто не видите никакой этой инфраструктуры, но ваши сотрудники SysOps уже определили и развернули эту инфраструктуру в фоновом режиме. Все, что вы видите, это то, что Дженкинс запускает любую команду развертывания, но в фоновом режиме под капотом происходит целый карнавал активности только для того, чтобы вы могли иметь эту так называемую «переносимость» контейнерного кода, «которая так проста в использовании!» На самом деле это не так уж и портативно, как вы думаете, особенно для сложных корпоративных приложений.
Добавление еще одного слоя
Контейнеризация требует, чтобы мы добавили еще один уровень виртуализации в стек технологий.
В наши дни конфигурация для контейнеризации не так уж и сложна, но тем не менее мы добавляем еще один уровень в технический стек, который на самом деле что для нас делает? Делает наш код более переносимым между машинами разработчиков? Уменьшает дрейф окружающей среды?
Не так быстро — хотя контейнеры могут помочь с дрейфом среды (это условие, когда код между средами разработки, тестирования, промежуточной и рабочей среды не синхронизируется и вызывает ошибки), у вас все равно нет гарантии, что эти среды будут то же самое, потому что контейнеры не учитывают настройку всего, что может потребоваться для существования на виртуальной машине, на которой размещается ваш контейнерный код.
Контейнеризация действительно усложняет технологический стек и особенно конвейер CI/CD. Напрасно так? Это зависит от того, насколько управляемым вы хотите, чтобы в конечном итоге стал технический стек вашего приложения.
Хорошая архитектура приложения может легко преодолеть и устранить потребность в контейнерах. (Думаю, позже мне нужно будет написать пример статьи об этой архитектуре.)
Стоит ли использовать контейнеры?
Это зависит от вашего архитектора и архитектуры, которую они уже развернули, и того, к чему привыкла ваша команда.
Если вы привыкли писать код с использованием контейнеров, и эта инфраструктура уже существует и хорошо известна, не меняйте ее. Вам будет проще и выгоднее придерживаться курса с уже установленной контейнерной инфраструктурой.
Однако за 20 лет, что я занимаюсь созданием и развертыванием приложений, я заметил, что нам, инженерам, нравится создавать действительно большие вещи, на самом деле целые фреймворки, которые, как правило, решают довольно небольшие проблемы. Или мы создаем действительно большие вещи, которые служат только для того, чтобы абстрагироваться от того, что мы должны делать в коде в любом случае (потому что мы ленивы). Мы пытаемся облегчить себе жизнь, но в итоге все, что мы делаем, это усложняем сантехнику.
Мы потратим месяцы на создание чего-то, что сэкономит нам несколько часов работы, которую мы должны делать в любом случае, то есть писать код, за которым легко следить, который легко отлаживать и который не абстрагирует магию от нашего взгляда.
Так работает Laravel, очень популярный PHP-фреймворк. Он делает много тяжелой работы и волшебства под капотом, используя подслащенный синтаксис, за которым часто нелегко следовать или отлаживать. Большинство фреймворков такие. Они облегчают нашу работу, но за счет дополнительной сложности.
ORM — еще один хороший пример. Эти вещи начались с предоставления нам возможности абстрагировать объекты данных (модели) от базы данных. Нам даже не нужно было писать SQL для большинства из них для базовых запросов. Наши объекты просто появились со всеми необходимыми данными и коллекциями. Это было волшебно, правда?
Да, не так быстро.
ORM — довольно маленькие вещи, которые можно использовать для гаражных и малых бизнес-приложений, но как только вы начинаете серьезно работать, их производительность ужасна. А в случае с Doctrine, одной из самых популярных корпоративных ORM для PHP, вам нужно выучить совершенно новый язык DQL, чтобы запустить эту штуку. И конфигурация отбрасывает вас на один из нижних уровней ада для чего-то большего, чем базовые связи между таблицами.
GraphQL — еще одна из этих абстракций, которые сейчас очень модно использовать, но на самом деле это не обязательно. Фактически, он пытается захватить не только ваш DBAL (уровень абстракции базы данных), но и хочет стать вашей инфраструктурой API. Это очень самоуверенная абстракция, которая делает написание JSON-запросов на JavaScript — чертовски круто! Нет, это так. Я серьезно, это действительно классная программа. Без сомнения. Но какой ценой?
Конечно, GraphQL только что сэкономил вам 30 минут на написании запроса внутри какой-то модели, а затем его передачи на уровень API и сервиса. Но что происходит с фреймворком GraphQL под капотом с большими сложными запросами? Или что произойдет, когда через десять лет этот код перестанет широко использоваться или поддерживаться, и никто больше не захочет с ним играть?
Подобно GraphQL и ORM, контейнеризация действительно находится в одной лодке, она не решает столько проблем, сколько создает по своей сути с точки зрения усложнения кодовой базы и стека технологий.
Нет, я совершенно серьезен. Какую БОЛЬШУЮ проблему на самом деле решает контейнеризация? Если это действительно решает только небольшую проблему, то его там не должно быть. Это просто не так.
Кроме того, каждый раз, когда вы добавляете уровень виртуализации, вы будете страдать от некоторого снижения производительности.
Я думаю, что самый важный вопрос, который мы должны задать себе как архитекторы: действительно ли нам нужна какая-либо новая технология для запуска кода приложения? Действительно ли это экономит время или это просто «чертовски круто» для наших наиболее распространенных случаев использования?
Если нет, если он нам действительно не нужен, то зачем мы добавляем его в стек технологий? Потому что какой-то инженер подумал, что это круто и/или модно? Потому что Google или Facebook используют его и теперь открыли исходный код? У них есть миллиарды долларов, чтобы писать и переписывать любой код, какой они хотят; вы, я и компания, в которой мы работаем, скорее всего, нет. Это не наши деньги, чтобы тратить их на то, что, возможно, является новейшей «причудливой технологией».
«Лучшая часть — это отсутствие части». — Илон Маск
Слишком часто нам, инженерам, нравится следовать за толпой в плане того, что нового и интересного сейчас используют все действительно крутые ребята из Google и Facebook. Но то, что инженеры Google написали что-то для своего технического стека, не означает, что это должно быть и у нас.
В приведенной ниже статье содержится некоторая ценная информация о внутренней работе Google — и это не то, что вы можете подумать, говоря о том, что Google — сплошь гении…
Несколько лет назад Angular был в моде, ну, потому что скучающие инженеры в Google изобрели его и начали поощрять людей использовать его. В течение примерно десяти лет (если быть точным, 12 лет) мы перешли от AngularJS к Angular 2, который не был обратно совместим, а теперь к Angular 15. И с каждой итерацией мы получаем больше сложности и изменений, а не меньше. Дело в том, что если вы написали свое приложение как SPA (одностраничное приложение) на Angular 4, многие инженеры перешли на 12 или даже 15, и они больше не хотят играть с 4 или 6 или чем-то еще. Скучный! Вот такая вчерашняя новость.
Теперь мы видим, что все больше и больше людей отказываются от Angular в пользу React. Что произойдет, когда Angular перестанет быть золотым детищем, которым НИКТО больше не захочет пользоваться? Как компания будет привлекать инженеров для дальнейшей поддержки? Тратить больше денег, чтобы попытаться привлечь их?
Обратите внимание на статью ниже о том, почему я не использую Angular или SPA в своих проектах.
Каждый день я получаю предложения о работе по электронной почте от рекрутеров, которые ищут людей с многолетним опытом работы в Angular. Они идут в мусорку. Извините, это не моя проблема. Выберите свою технологию, мы все одинаково относимся к любому технологическому стеку или технологии, которая нам нравится или не нравится.
Когда-то микросервисы были в моде, но теперь мы обнаружили, что управление 37 различными изолированными сервисами — настоящая головная боль. Затем, чтобы заставить эти микросервисы надежно взаимодействовать друг с другом, требуется, чтобы мы установили еще большую инфраструктуру, такую как службы очередей сообщений, которые еще больше усложняют приложение и делают его почти полностью непереносимым.
Если бы мы с самого начала правильно спроектировали приложение, понадобились бы нам все эти движущиеся части? Может быть, но, вероятно, нет.
Какую ценность на самом деле предлагают контейнеры?
Я не говорю, что контейнеры бесполезны или что они не работают. Совершенно очевидно, что они работают, и они работают хорошо, когда используются в правильно развернутой среде. Они могут добавить определенный уровень (каким бы небольшим) облегчения циклу разработки и обеспечить некоторый уровень переносимости кода.
По иронии судьбы, я могу получить (более или менее) тот же уровень переносимости кода, заархивировав исходный код и развернув его на предварительно настроенной виртуальной машине, как это делает Docker. (Нет, это не так просто сделать. Создание образа Docker, без сомнения, тривиально в командной строке.) Я хочу сказать, что вам все равно нужна предварительно настроенная виртуальная машина в обоих случаях.
Таким образом, необходимо задать вопрос: действительно ли эти контейнеры необходимы и какую действительно большую проблему на самом деле решает контейнер? Есть ли способ разрабатывать код, не добавляя кучу программного обеспечения на мой локальный компьютер (кроме моей любимой IDE или текстового редактора) и на серверы, которые мы развертываем?
Можем ли мы вообще писать код без установки Node.JS и локальных инструментов сборки? Я делаю. Каждый день.
Читая на кофейной гуще и используя историю в качестве руководства, я полагаю, что мы увидим, как причуда контейнеризации начнет ослабевать. Мы уже наблюдаем это, когда Angular заменяется React, а микросервисы снова устаревают в пользу так называемых «монолитных» приложений и архитектуры.
Скоро никто не захочет играть с приложениями, использующими Angular, микросервисы или любые другие причудливые технологии, добавленные в технологический стек 5 или 10 лет назад.
Хотели бы вы разрабатывать и поддерживать код, написанный на Angular.JS? Нет, вы бы хотели вырвать его и заменить на более новую версию. И когда вы обнаружите, что это не вариант, вы, скорее всего, перейдете к поиску компании с технологическим стеком, с которым вам действительно нравится играть.
Архитекторов нанимают, чтобы уберечь компанию от дорогостоящих ошибок еще долго после того, как разработчики ушли дальше.
Хотите верьте, хотите нет, но инженеры и архитекторы обнаруживают, что правильно модульное приложение SOA / MVC / или N-уровня намного проще в управлении и чертовски быстрее, чем десятки микросервисов, работающих в своих собственных частных Айдахо, обменивающихся данными через TCP/ IP вместо шины CPU.
Заключение
В конце концов, настоящие архитекторы занимаются внедрением наилучшей ремонтопригодной инфраструктуры с наилучшей возможной ценностью для компании или предприятия. Нас наняли, чтобы уберечь компанию от дорогостоящих ошибок еще долго после того, как разработчики ушли дальше.
Я вижу некоторую ценность в контейнеризации. И если вы уже используете его, не останавливайтесь, если он уже встроен в культуру разработки и технический стек вашей компании. Но кому-то действительно пришлось бы раскачивать мою лодку одним адским вариантом использования, чтобы заставить меня использовать контейнеры вместо виртуальных машин при запуске нового приложения.
Так что давай, раскачай мою лодку и расскажи мне, как ты используешь контейнеры, где виртуальные машины не могут выполнять ту же работу. Мне будет интересно услышать ваши комментарии.
Бо Бошан — архитектор веб-приложений с более чем 20-летним опытом разработки приложений корпоративного класса в облаке; он является участником многочисленных проектов с открытым исходным кодом; и основатель WebTigers и ведущий разработчик Tiger Platform.
Дополнительные материалы на PlainEnglish.io.
Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .
Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.