Systemd

Systemd In Action. Part 1

Ivan Shapovalov, Like-all, Pavlo Rudyi

Part 2Part 3 Part 4

Systemd – это не система инициализации и даже не “системный менеджер” (как можно прочитать на freedesktop.org). Systemd как проект – это универсальный plumbing layer, набор служебных программ для совершенно разных задач.

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

Lennart Poettering and Kay Sievers

В данном эпизоде мы рассмотрели непосредственно систему инициализации (тоже называемую systemd), её основные концепции и принципы работы.

  1. Особенности и преимущества systemd
    • подход, основанный на зависимостях между задачами
      • более логично, чем (например) событийный подход Upstart или ручная расстановка порядка действий из sysvinit
      • при попытке запуска некоторой задачи сначала запускаются все её зависимости; если что-то не запустилось – цепочка действий прерывается
      • отдельно задаются зависимости требования (Wants/Requires) и зависимости упорядочивания (After/Before)
      • “врождённая” параллелизация
    • cлежение за запущеными сервисами
      • механизм cgroups для группировки процессов, принадлежащих разным сервисам
      • дочерние процессы не могут выйти из-под контроля
      • для инспекции дерева cgroups предусмотрены утилиты systemd-cgls, systemd-cgtop
      • появляется возможность иерархичного задания общих ограничений по ресурсам (потреблению памяти, CPU и т.д.)
      • элементы супервизора (задание действий при падении, автоматический перезапуск, сторожевые таймеры)
    • взаимодействие с udev (как пример — файл с правилами из поставки systemd)
      • устройство = юнит (для устройств, помеченных TAG+="systemd", создаются *.device-юниты, см. ниже)
      • из правил udev возможен также запуск произвольных юнитов (ENV{SYSTEMD_WANTS}+="foo.service")
    • предусмотрен ряд способов динамического запуска сервисов (наподобие xinetd), что может экономить ресурсы системы
    • значительное уменьшение роли шелл-скриптов при загрузке системы вплоть до полного избавления от таковых (стоит отметить, что никаких ограничений на запуск шелл-скриптов не предполагается, речь исключительно о самом ините)
    • всесторонний и обширный D-Bus API практически у каждого из компонентов
  2. Юниты (units)
    • Юнит – базовая сущность, участвующая в построении дерева зависимостей
      • один юнит – одно действие
      • юнит может описывать не только запуск демона:
        Тип юнита Что описывает
        service демон или что-либо, что можно запустить
        device факт подключения какого-либо устройства (имя юнита генерируется из sysfs-имени устройства)
        target ничего не описывает, группирует другие юниты в дереве зависимостей
        mount точку монтирования файловой системы (имя юнита должно соотвествовать пути до точки монтирования)
        automount аналог autofs: точку автомонтирования (должен существовать *.mount-юнит с тем же именем)
        timer аналог cron: периодический запуск другого юнита (по умолчанию запускаться будет *.service-юнит с тем же именем)
        socket аналог xinetd: запуск юнита при подключении к указанному сокету (по умолчанию запускаться будет *.service-юнит с тем же именем)
        path запуск юнита по событию доступа к какому-либо пути в файловой системе (по умолчанию запускаться будет *.service-юнит с тем же именем)
        slice группирует другие юниты в дереве cgroups, позволяя иерархично задавать ограничения по используемым ресурсам
    • Посмотреть весь список и состояние юнитов можно с помощью:
      • systemctl status — отображение общего состояния системы и перечисление юнитов, которым соответствуют какие-либо запущенные процессы
      • systemctl list-units (или просто systemctl) — отображение таблицы, в которую входят все активные в данный момент или упавшие юниты
        (systemctl --failed — только упавшие юниты)
    • Юнит может быть шаблоном: если вызван юнит foo@bar и существует юнит foo@, то “bar” считается параметром и подставляется в текст юнита foo@ вместо определённых спецификаторов (%i и аналогичных)
    • Файлы юнитов могут храниться в трёх директориях, имеющих друг над другом приоритет:
      Директория Назначение
      /usr/lib/systemd/system “системные” юниты, поставляемые вместе с приложениями
      /run/systemd/system динамически создаваемые (напр., через API) юниты
      /etc/systemd/system юниты и исправления, внесённые администратором (данная директория имеет наивысший приоритет)
    • Действия с юнитами:
      • systemctl start ЮНИТЫ, systemctl stop ЮНИТЫ — запустить или остановить указанные юниты немедленно
      • systemctl enable ЮНИТЫ, systemctl disable ЮНИТЫ — добавить указанные юниты в “автозапуск” или убрать их оттуда
        • enable не подразумевает start, disable не подразумевает stop
        • даже если сделать disable, юнит всё равно может быть запущен как зависимость
      • systemctl kill [-s СИГНАЛ] [--kill-who main|control|all] — убить все процессы, принадлежащие юниту
      • systemctl mask ЮНИТЫ, systemctl unmask ЮНИТЫ — замаскировать юниты (запретить их запуск любым способом, в т. ч. как зависимость) или размаскировать их

      Несколько слов про автозапуск. Концепция уровней запуска (runlevels) была заменена более общей концепцией target-юнитов: например, multi-user.target — эквивалент runlevel 3.

      Поэтому добавление сервиса в какой-либо ранлевел (т. е. в автозапуск) теперь осуществляется посредством создания искусственной зависимости между нужным target-юнитом и рассматриваемым.

    • Структура файла юнита.Формат файла юнита похож на *.desktop (и, следовательно, на *.ini). Существуют две секции, допустимые в юнитах любого типа, и некоторое количество секций, специфичных для “своих” типов юнитов.Разберём наиболее частоиспользуемые опции в трёх наиболее частоиспользуемых секциях.
      • Секция [Unit] — общие параметры, применимые к любому типу юнита.
        Директива Описание
        Description= текстовое описание юнита
        Wants=, Requires=, Requisite=, BindsTo= зависимости требования различного рода
        After=, Before= зависимости порядка
      • Cекция [Install] — описание автозапуска (операции enable/disable выполняют действия, описанные в данной секции).
        Директива Описание
        WantedBy=, RequiredBy= имена юнитов, для которых нужно создавать искусственную зависимость типа Wants/Requires от этого юнита (идиома: WantedBy=multi-user.target)
        Also= имена юнитов, для которых тоже нужно сделать enable/disable вместе с этим
      • Секция [Service] — описание запускаемого процесса.
        Директива Описание
        Type= характер запускаемого процесса:

        • forking — демон
        • simple — foreground-процесс (не форкается)
        • oneshot — единовременная задача (systemd будет ждать завершения процесса)
        ExecStart=, ExecStop= путь к исполняемым файлам, которые требуется запускать при старте и остановке юнита (каждый из этих параметров опционален)
        RemainAfterExit= применимо только при Type=oneshot и определяет, считать ли юнит активным после окончания работы процесса
      • Примеры вспомогательных директив.
        Директива Описание
        Private*=, ProtectSystem=, ProtectHome=, NoNewPrivileges= директивы базового обеспечения безопасности
        MemoryLimit=, CPULimit= управление ограничениями ресурсов
        User=, Group= запуск от имени определённого пользователя

TO BE CONTINUED

Part 2Part 3 Part 4