
Как-то в один момент я решил написать статью про поставку в виде контейнеров докер и deb-пакетов, но когда начал, меня почему-то понесло в далекие времена первых персональных компьютеров и даже калькуляторов. В общем, вместо сухих сравнений докера и deb получились вот такие вот размышления на тему эволюции, кои и представляю на Ваш суд.
Любой продукт, какой бы он ни был, должен каким-то образом добраться до продуктовых серверов, должен быть настроен и запущен. Вот об этом и будет эта статья.
Размышлять я буду в историческом контексте, «что вижу — о том пою», что я видел, когда начинал только писать код и что наблюдаю сейчас, что мы сами используем в настоящий момент и почему. Статья не претендует на полноценное исследование, некоторые моменты упущены, это мой личный взгляд на то, что было и что есть сейчас.
Итак, в старые добрые времена… самый ранний способ поставки, который я застал — это были кассеты от магнитофонов. У меня был компьютер БК-0010.01…
Эпоха калькуляторов
Нет, был еще более ранний момент, был еще калькулятор МК-61 и МК-52.

Следующей модификацией был калькулятор МК-52, у него уже появилось какое-то подобие энергонезависимого хранения данных. Теперь уже игру или программу не надо было вбивать вручную, а, проделав некоторые магические пассы кнопками, она загружалась сама.
Объем самой большой программы в калькуляторе был 105 шагов, а размер постоянной памяти в МК-52 — 512 шагов.
Кстати, если есть фанаты этих калькуляторов, кто читает эту статью — в процессе написания статьи я нашел и эмулятор калькулятора для андроид, и программы для него. Вперед, в прошлое!
Небольшое отступление про МК-52 (из википедии)
МК-52 летал в космос на корабле «Союз ТМ-7». Его предполагалось использовать для расчёта траектории посадки в случае, если выйдет из строя бортовой компьютер.
МК-52 с блоком расширения памяти «Электроника-Астро» с 1988 года поставлялся на корабли ВМФ в составе штурманского вычислительного комплекта.
Первые персональные компьютеры


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

Эпоха интернет
Постепенно сложность программных систем еще усложняется, от монолита и декстопных приложений происходит переход к распределенным системам, тонким клиентам и микросервисам. Теперь нужно уже конфигурировать не одну программку, а их набор, причем так, чтобы они дружили все вместе.
Изменалась полностью концепция, пришел Интернет, наступила эпоха облачных сервисов. Пока еще толко в начальной стадии, в виде сайтов, особо сервисами никто и не грезил. но это было поворотным моментом в индустрии как разработки, так и собственно поставки приложений.
Для себя я отметил, что в этот момент произошла смена поколений разработчиков (или это было только в моем окружении), и сложилось такое ощущение, что все старые добрые способы поставки были позабыты в один момент и все началось с самого начала: всю поставку стали делать наколеночными скриптами и назвали это гордо «Continuous delivery». По факту начался какой-то период бардака, когда старое позабыто и не используется, а нового попросту нет.
Я помню времена, когда у нас в компании, где я тогда работал (не буду называть), вместо того, чтобы делать сборку через ant (maven тогда еще не был популярен или вообще не было), народ просто собирал jar в IDE и безмятежно коммитил его в SVN. Соответственно, разворачивание заключалось в доставании файла из SVN и копированию его по SSH на нужную машину. Вот так просто и топорно.
В это же время поставка простых сайтов на PHP делалась уж совсем примитивно простым копированием поправленного файла через FTP на целевую машину. Иногда не было и такого — код правили вживую на продуктовом сервере, и было особым шиком, если были где-то бэкапы.
RPM- и DEB-пакеты

Дистрибутивы семейства Debian пошли похожим путем и реализовали поставку в виде deb-пакетов, что так же неизменно до наших дней.
Пакетные менеджеры позволяют поставлять сами программные продукты, конфигурировать их в процессе установки, управлять зависимостями между разными пакетами, осуществлять удаление продуктов и зачистку лишнего в процессе деинсталляции. Т.е. по бОльшей части это все, что нужно, именно поэтому они и продержались несколько десятилетий практически без изменений.
Облачность добавила в пакетные менеджеры установку не только с физических носителей, но и из облачных репозиториев, но принципиально мало что изменилось.
Стоит заметить, что в настоящее время есть некоторые поползновения в сторону ухода от deb и перереход на snap-пакеты, но об этом позже.
Так вот, это новое поколение облачных разработчиков, которое не знало ни DEB, ни RPM, тоже потихоньку росло, набиралось опыта, продукты усложнялись, и нужны были какие-то более разумные способы поставки, нежели FTP, bash-скриптики и подобные студенческие поделки.
И здесь на сцену выходит Docker, эдакая смесь виртуализации, разграничения ресурсов и способа поставки. Это сейчас модно, молодежно, но нужен ли он для всего? Панацея ли это?
По моим наблюдениям, очень часто Docker предлагается не как разумный выбор, а просто потому, что об этом, с одной стороны, говорят в сообществе, и те, кто предлагают, только его и знают. С другой стороны, о старых добрых системах упаковки по большей части молчат — они есть и есть, свое дело делают тихо и незаметно. В такой ситуации другого выбора особо-то и нет — выбор очевиден — Docker.
Попробую поделиться опытом, как у нас проходило внедрение Docker, и что в результате получилось.
Самописные скрипты
Изначально были bash-скрипты, которые деплоили jar-архивы на нужные машины. Управлял этим процессом Jenkins. Это успешно работало, благо сам по себе jar-архив уже является сборкой, содержащей в себе классы, ресурсы и даже конфигурацию. Если сложить в него все по максимуму — то разложить его скриптом — это не самое сложное, что нужно
Но у скриптов есть несколько недостатков:
- скрипты обычно пишутся на скорую руку и потому настолько примитивны, что содержат только один самый благополучный сценарий. Этому способствует то, что разработчик заинтересован в скорейшей поставке, а нормальный скрипт требует вложение приличного количества ресурсов
- как следствие предыдущего пункта, скрипты не содержат процедуры деинсталляции
- нет установленной процедуры апгрейда
- при появлении нового продукта надо писать новый скрипт
- нет поддержки зависимостей
Конечно, можно написать навороченный скрипт, но, как я писал выше — это время на разработку, причем не самое малое, а времени, как известно, всегда не хватает.
Это все очевидно ограничивает круг применения такого способа развертывания только простейшими системами. Настал момент это менять.
Docker

С какими неудобствами мы столкнулись?
- Проблемы с сетью в режиме bridge
- Неудобно смотреть логи в контейнере (если они никуда не вынесены отдельно в файловую системы хост-машины)
- Периодически странное зависание ElasticSearch внутри контейнера, причину так и не установили, контейнер официальный
- Нудобно пользоваться шеллом внутри контейнера — все сильно урезано, нет привычных инструментов
- Большой размер собираемых контейнеров — дорого хранить
- Из-за большого размера контейнеров сложно поддерживать множественные версии
- Более длительная сборка, в отличие от других способов (скрипты или deb-пакеты)
С другой стороны, чем Spring-сервис в виде jar-архива хуже деплоить через тот же deb? Реально ли нужна изоляция ресурсов? Стоит ли лишаться удобных инструментов операционной системы, запихивая сервис в сильно урезанный контейнер?
Как показала практика — в реальности это не нужно, deb-пакета хватает в 90% случаев.
Когда же все-таки старый добрый deb не срабатывает и когда действительно нам был необходим докер?
Для нас это было развертыванием сервисов на python. Множество библиотек, нужных для машинного обучения и отсуствующих в стандартной поставке операционной системы (а то, что там было — не тех версий), хаки с настройками, необходимость разных версий для разных сервисов, живущих на одной и той же хост-системе привели к тому, что единственным разумный способом поставки этой ядерной смеси оказался докер. Трудоемкость сборки докер-контейнера оказалась ниже, чем идея упаковать все это в отдельные deb-пакеты с зависимостями, да собственно никто в здравом уме за это бы и не взялся.
Второй момент, где планируется использовать докер — для развертывания сервисов по схеме blue-green deploy. Но здесь хочется получить постепенное увеличение сложности: сначала собираются deb-пакеты, а затем уже из них собирается докер-контейнер.
Snap-пакеты

Как итог, у нас сейчас в разумном сочетании используются как deb-пакеты, так и докер-контейнеры, которые, возможно, в отдельных случаях мы заменим на snap-пакеты.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
А что для поставки используете Вы?
29.89% Самописные скрипты52
12.64% Копируем ручками на FTP22
20.69% deb-пакеты36
13.22% rpm-пакеты23
2.3% snap-пакеты4
56.9% Docker-images99
11.49% Образы виртуальных машин20
4.6% Клонируем HDD целиком8
7.47% puppet13
24.14% ansible42
12.07% Другое21
Проголосовали 174 пользователя. Воздержались 60 пользователей.