SystemD Target. Группируем unit'ы

10/20/2016

Особый тип unit'ов systemd, о котором сегодня и пойдет речь, называется target. Юниты типа "target" должен обязательно иметь в своем названии суффикс ".target" (например my_target.target), располагаться в каталоге "/usr/lib/systemd/system" или "/etc/systemd/system" (юниты, лежащие в "/etc/*" имеют приоритет), ну и, само собой, быть доступным на чтение.

Сам по себе таргет не несет какой-либо функциональности, но он может елегантным образом группировать другие юниты и запускать или останавливать их скопом. Когда это может понадобиться? Рассмотрим сферу применения systemd target:

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

Рассмотрим каждый пункт подробнее.

Приложение состоит из нескольких компонент

Вообразите следующее: веб-сайт. Скорее всего у вас будет база данных, например mysql, веб-сервер, например nginx, интерпретатор php скриптов, например hhvm, а  еще в довесок самописная служба, выполняющая бэкап по расписанию, например backup.sh.

При обычном раскладе, чтобы всё это загрузить вы даете команды

systemctl start nginx
systemctl start mysql
systemctl start hhvm
systemctl start backup.timer

А можно создать unit, назвать его mysite.target и использовать всего одну команду

systemctl start mysite.target

С таргетами можно делать всё то же самое, что и с обычными юнитами, например их можно перезапускать:

systemctl restart mysite.target

Как же правильно составить файл systemd target? Давайте рассмотрим создание таргета на приведенном примере:

[Unit]
Description=mysite
Requires=nginx.service mysql.service hhvm.service backup.timer
After=nginx.service mysql.service hhvm.service backup.timer

Не забываем перечитывать конфигурацию:

systemctl daemon-reload

Готово! Вот так простым описанием зависимостей мы сгруппировали юниты. Запуская mysite.target, systemd увидит, что для своего запуска он требует такие и такие юниты, и запустит их. Помните, что директива "Requires=" жестко устанавливает зависимости и, если хотя бы один из юнитов по каким-то причинам не сможет запуститься, запуск таргета также не состоится. Если вам это не подходит, используйте вместо "Requires=" "Wants=". "Wants=" мягко устанавливает зависимость и не падает, если какой-то из компонент не сможет запуститься. Директивы "After=" и "Before=" зависимость не устанавливают, но устанавливают последовательность запуска. Один таргет может зависеть от другого таргета и т.д.

Запускается шаблон юнита

Как и в первом случае, вы не хотите работать с multi instance службой, взаимодействуя с каждым компонентов в отдельности, ведь их может быть 100 или даже 1000. И вместо

systemctl start my_daemon@1.service
systemctl start my_daemon@2.service
systemctl start my_daemon@X.service

Вы даете команду

systemctl start my_daemon.target

Файл таргета будет выглядеть так:

[Unit]
Description=my_daemon 
Requires=my_daemon@1.service my_daemon@2.service my_daemon@3.service
After=my_daemon@1.service my_daemon@2.service my_daemon@3.service

Загружается системный level

Действительно, как следует из заголовка 3-его пункта systemd target представляет собой аналог классических уровней sysv. Как и в sysv, вы всего лишь должны определить таргет, в который система будет загружаться по-умолчанию, командой

systemctl set-default my_target.target

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

systemctl list-dependencies

А писать таргеты вы уже научились из первых двух пунктов.

Удачи!

Темы: