Дистрибьюция Java приложений
Удивительно, но факт - дистрибьюция Java приложений в 21 веке по прежнему огромный костыль. Разработчики до сих пор придумывают способы вроде rsync/copy-paste/wget для установки java приложений на сервер. И только монструозные enterprise production ready платформы иногда позволяют сделать чуть больше - откатить приложение на предыдущую версию. В этой статье я хотел бы рассказать о доступном и простом способе организации дистрибьюции.
deb и apt
В мире существует множество действительно гигантских репозиториев приложений и инструментов по их дистрибьюции. Самые большие, по ощущениям, - это AppStore, Google Play, Debian/Ubuntu репозитории и CentOS/Fedora YUM репозитории. Например, в Ubuntu репозитории для версии 15.04 содержится около 90000 приложений (без учета различных версий). Почему бы не воспользоваться провернной временем системой и для дистрибьюции Java приложений? Тем более, что:
- большинство серверов и так используют Debian/Ubuntu
- проверенный временем инструмент: первый релиз был 16 лет назад
- нативная поддержка в операционной системе
Для начала немного о системе дистрибьюции приложений в Debian/Ubuntu. Она состоит из двух основных частей:
- deb пакеты
- apt (Advanced Package Tool) инструменты
deb пакеты
deb это бинарный дистрибутив приложения. Он состоит из 3 основных частей:
- метаинформация. Производитель, версия, зависимости на другие пакеты (очень похоже на maven), описание и пр.
- непосредственно приложение. .tar.gz архив
- (опционально) скрипты, которые будут выполняться во время установки
Структура .tar.gz архива может быть абсолютно произвольной. Однако, чтобы Ваше приложение было похоже на все остальные приложения системы, оно должно следовать структуре каталогов Debian/Ubuntu:
- /etc - конфиги
- /etc/init.d/ - скрипты запуска демонов
- /usr/bin - исполняемые файлы
- /usr/lib - библиотеки
- /var/log - логи
В зависимости от Вашего приложения каталоги могут немного отличаться, но общая структура надеюсь понятна.
Еще одной важной особенностью deb пакетов является возможность запускать скрипты во время установки. Эти скрипты тоже хранятся в deb пакете и имеют стандартное именование. Каждый скрипт может выполняться в определенную фазу установки. Установка пакета делится на несколько фаз:
- preinst
- inst
- postinst
- prerm
- rm
- postrm
Существует множество различных промежуточных фаз и различные комбинации состояния инсталляции. Нас они мало интересуют, но тем кто хочет разобраться можно почитать официальную документацию. Обычно эти скрипты настраивают ротацию и архивирование логов, задают начальные значения конфигураций (например, root-пароль для mysql). Если же у вас конечное бизнес-приложение, то лучше взять какое-нибудь нормальное средство автоматизации вроде Ansible, Chief, Puppet.
apt
apt - это набор инструментов для работы с deb пакетами. Он позволяет:
- конфигурировать репозитории и работать с ними: добавлять, удалять, менять, обновлять индекс
- управлять пакетами: устанавливать, удалять, обновлять, искать
apt репозиторий в упрощенном виде - это HTTP сервер, который раздает deb пакеты. У него есть индекс (файл), который доступен по стандартному пути и непосредственно бинарники, путь к которым находится в индексе.
Связывая все воедино
После того как стала понятна примерная схема работы связки deb + apt, можно попробовать их интегрировать. Примерная схема такая:
- создания deb пакета в фазе package
- публикация получившегося пакета в фазе deploy
Для этого есть несколько maven плагинов.
jdeb
Схема его работы достаточно проста:
- перечислить файлы и директории, которые попадут в результирующий .tar.gz архив
- указать пермиссии
Более полная документация о возможностях плагина можно узнать на официальной странице.
apt-maven-plugin
Работает с репозиторием заданным в distributionManagement как с apt репозиторием, а не maven репозиторием. Хотя ничего не мешает их использовать одновременно под одним url. Их layout’ы совместимы между собой.
Пример конфигурации выглядит следующим образом:
<plugin>
<groupId>com.aerse.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>deploy</id>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
<configuration>
<component>main</component>
<codename>strepo</codename>
</configuration>
</plugin>
И секция distributionManagement (ничего необычного):
<distributionManagement>
<repository>
<id>maven-release-repo</id>
<url>http://example.com/maven</url>
</repository>
</distributionManagement>
После выполнения фазы deploy, http://example.com/maven станет еще и apt репозиторием. И можно смело писать:
sudo add-apt-repository "deb http://example.com/maven strepo main"
sudo apt-get update
sudo apt-get install <artifactId>
Немного любимого enterprise
Манца любого java-enterprise разработчика звучит следующим образом:
- security
- stability
- high availability production ready platform
Все это отлично решается, если устроить apt репозиторий из самого популярного хостинга для разработчиков: s3. Вкупе с cloudfront, он даёт гарантию 99.9% надёжности и географическую распределённость.
Делается это опять же достаточно просто. Надо подключить плагин для работы с s3:
<build>
<extensions>
<extension>
<groupId>org.springframework.build</groupId>
<artifactId>aws-maven</artifactId>
<version>5.0.0.RELEASE</version>
</extension>
</extensions>
</build>
Поменять url в секции distributionManagement на имя bucket’a:
<distributionManagement>
<repository>
<id>maven-release-repo</id>
<url>s3://example.bucket</url>
</repository>
</distributionManagement>
И настроить доступ к вашему bucket’у:
<servers>
<server>
<id>maven-release-repo</id>
<username>apikey</username>
<password>apisecret</password>
</server>
</servers>
На конечных серверах для доступа к такому репозиторию существует специальный плагин: apt-transport-s3. К сожалению его еще нет в официальных репозиториях, поэтому необходимо добавить вручную один из репозиториев, где он содержится:
sudo add-apt-repository ppa:leonard-ehrenfried/apt-transport-s3
sudo apt-get install apt-transport-s3
После чего можно уже указывать наш s3 репозиторий:
sudo add-apt-repository "deb s3://apikey:apisecret@s3.amazonaws.com/example.bucket strepo main"
Итого
В результате всех манипуляций установка приложения:
- mvn clean deploy
На любом Debian/Ubuntu сервере в любой точке мира:
- apt-get update
- apt-get install artifactId