Управление тем, какие сервисы включены в “срез” systemd.

Вопрос или проблема

Я переписал этот вводный абзац, пытаясь скрыть свое презрение к systemd. Я остановлюсь на том, что нахожу “логику” systemd озадачивающей, и оставлю это как есть. Теперь к вопросу:

Я пытался сократить время загрузки, указанное командой systemd-analyze time, на крошечном Raspberry Pi Zero 2W. Операционная система примерно на 95% основана на Debian с небольшим добавлением Raspberry Pi для работы с оборудованием.

Я начал с составления списка активных файлов единиц, и из этого списка выбрал несколько service, которые, как я был уверен, можно удалить без последствий:

$ systemctl list-unit-files --state=enabled
...
rpi-display-backlight.service      enabled enabled
rpi-eeprom-update.service          enabled enabled
...
$

Я решил отключить оба этих сервиса следующим образом:

$ sudo systemctl disable rpi-eeprom-update.service rpi-display-backlight.service
Removed "/etc/systemd/system/halt.target.wants/rpi-display-backlight.service".
Removed "/etc/systemd/system/poweroff.target.wants/rpi-display-backlight.service".
Removed "/etc/systemd/system/reboot.target.wants/rpi-display-backlight.service".
Removed "/etc/systemd/system/multi-user.target.wants/rpi-eeprom-update.service".

К сожалению, я обнаружил, что время загрузки (как сообщается командой systemd-analyze time) фактически увеличилось примерно на 3 секунды. Я пере-загружал несколько раз, чтобы получить “среднее”; увеличение на 3 секунды выглядело реальным и стойким. Мне стало интересно, может ли это повышение быть связано с тем, что systemd пробует снова запустить эти службы. Поэтому я посмотрел на зависимости с другими “единицами” systemd:

$ systemctl list-dependencies rpi-eeprom-update.service
rpi-eeprom-update.service

$ systemctl list-dependencies rpi-display-backlight.service
rpi-display-backlight.service
● └─system.slice
$

Я воспринял первый результат (rpi-eeprom) как указание на отсутствие других зависимостей. Второй результат (rpi-display) сбивает меня с толку. Я немного изучил вопрос о .slice с тех пор, но он все еще мало (на самом деле совсем не) имеет для меня смысла. Что приводит к моему вопросу:

Кто-нибудь может объяснить, как редактировать этот system.slice и удалить rpi-display-backlight.service?

Кажется, у вас есть какое-то недопонимание по поводу того, что такое слайсы. Позвольте мне сначала предоставить немного фона.

Слайс — это единица иерархии учета ресурсов systemd: зависимость от слайса не заставит сервис запускаться. Наоборот: служба не будет разрешена для запуска, пока не будет установлен учет ресурсов (т.е. виртуальные файловые системы /sys и /sys/fs/cgroup не будут смонтированы). Это происходит сразу после того, как монтируется настоящий корневой файловый система, так что это не слишком ограничение.

Любые единицы, которые управляют процессами (в основном, единицы области и службы), могут быть назначены определённым слайсам: если не определён более специфичный слайс, по умолчанию для любого системного *.service или *.scope является system.slice. Любые экземплярные единицы службы (те, у которых в имени есть @) получают по-суб-слайсу system.slice, который может отслеживать использование ресурсов всех экземпляров этого конкретного шаблона.

Например:

  • все системные службы, для которых не определён более конкретный слайс, включены в system.slice
  • если вы активируете процессы getty для последовательных портов с, например, systemctl enable [email protected], вы автоматически получите system-serial\x2dgetty.slice, который отслеживает общее использование ресурсов всеми службами serial-getty@.... Это под-слайс system.slice.
  • все входы пользователей, управляемые systemd-logind, суммируются в user.slice, и каждое входное подключение пользователя отслеживается отдельно под-слайсом user-<UID>.slice. Это включает пользовательские службы, т.е. фоновые службы на пользователя: см. systemctl --user list-units --type=service.
  • если вы запускаете виртуальные машины или контейнеры под управлением systemd-machined, вы получите machine.slice, который отслеживает общее использование ресурсов всеми ВМ/контейнерами, и под-слайс machine-<VM/container ID>.slice, отслеживающий конкретную каждую ВМ/контейнер.

Для более интуитивного понимания попробуйте запустить systemd-cgtop и представьте, что у вас что-то нагружает вашу систему, но вы точно не знаете, что. Это какой-то пользователь делает что-то, чего не следует, или это сервисный процесс, который неправильно настроен или подвергся внешней атаке?

По вашему усмотрению, вы можете активировать отслеживание лимитов ресурсов и устанавливать ограничения на использование ресурсов для любого сервисного или слайса. Например, если у вас есть система, в которой выполняется конкретная критическая служба и некоторые неважные, вы можете поместить неважные службы в отдельный слайс (возможно, под-слайс system.slice), затем добавить ConditionMemoryPressure=, ConditionCPUPressure= и/или ConditionIOPressure= к этому слайсу, чтобы система автоматически завершила все неважные процессы (или не начала их в первую очередь, если неважные процессы включают *.timer единицы для выполнения периодических неважных задач) если система, по-видимому, находится под высокой нагрузкой на память/ЦП/ввод-вывод, соответственно. См. man systemd.resource-control для получения более подробной информации.

Если вы хотите отдельно отслеживать использование ресурсов конкретной службы или группы служб, вы можете добавить строку Slice=something.slice в раздел [Service] соответствующих служб.

Ваш следующий вопрос может звучать так: “Почему тогда rpi-display-backlight.service имеет зависимость от system.slice, а у rpi-eeprom-update.service её нет?” Честно говоря, я не знаю точно. Но я бы предположил, что это, вероятно, означает, что rpi-eeprom-update – это служба типа Type=oneshot, которая не должна оставлять запущенные долгоживущие процессы, а rpi-display-backlight запускает, по крайней мере, один сервисный процесс, чьё использование ресурсов учитывается как часть system.slice, так как не определён более специфичный слайс, а system.slice является умолчанием для всех служб.

Ещё раз: если у единицы есть зависимость от слайс-юнита, это не будет вызывать попытки systemd заново запустить эту единицу. Это просто означает, что любое использование ресурсов долгосрочными процессами, запускаемыми этой единицей, будет учтено в указанном слайсе.

Если вы хотите изменить зависимость слайса у rpi-display-backlight.service, просто добавьте файл /etc/systemd/system/rpi-display-backlight.service.d/override.conf с содержимым:

[Service]
Slice=system-separate.slice

если вы хотите, чтобы rpi-display-backlight.service находилась в отдельном под-слайсе, который всё равно учитывается в system.slice, или

[Service]
Slice=separate.slice

если вы хотите, чтобы его использование ресурсов не учитывалось в результатах system.slice.

Как всегда, после изменения файлов конфигурации сервиса выполните systemctl daemon-reload. Или сделайте изменения с помощью systemctl edit rpi-display-backlight.service, что делает это за вас автоматически (и позволяет вам легко отменить ваши изменения или снова отредактировать, если есть ошибка синтаксиса).

.

Ответ или решение

Система инициализации systemd, несмотря на свои преимущества, может быть действительно сложной для понимания на первый взгляд, особенно для тех, кто впервые сталкивается с таким подходом. Ваша задача связана с оптимизацией времени загрузки на маленьком Raspberry Pi Zero 2W, где ресурсы особенно ограничены и каждая секунда на счету.

Теория

Сначала давайте разберемся, что такое "срез" (slice) в контексте systemd. systemd организует регулирование ресурсов через иерархию срезов, которая позволяет более гибко управлять использованием ресурсов системой. Это особенно актуально для служб, где необходимо ограничивать использование CPU, памяти или ввода-вывода.

Срезы в systemd задают логическую организацию для слежения за использованием ресурсов. Все системные сервисы, которые не имеют более специфического среза, по умолчанию находятся в system.slice. Это не значит, что срез напрямую влияет на запуски сервисов или их перезапуск. Это всего лишь организует их в определенную группировку для учета используемых ими системных ресурсов.

Пример

В вашем случае, рпи-display-backlight.service имеет зависимость от system.slice. Это не значит, что systemd будет пытаться перезапускать этот сервис, если он выключен. Это лишь указывает, что рпи-display-backlight.service будет учитывать свои ресурсы как часть общей группы system.slice.

С другой стороны, отсутствие явной зависимости у rpi-eeprom-update.service может быть связано с тем, что это сервис Type=oneshot, который не предназначен для запуска долгоживущих процессов, и после выполнения своей задачи он завершает работу.

Применение

Если вы хотите совершенно избежать учета ресурса конкретного сервиса внутри system.slice или организовать его ресурсы отдельно, вы можете настроить отдельный срез. Это делается добавлением конфигурации Slice= в соответствующий файл конфигурации сервиса.

Вот шаги, которые могут помочь вам настроить это:

  1. Создайте файл с нужной конфигурацией для переопределения конфигурации существующего сервиса. Например, для рпи-display-backlight.service, создайте директорию, если она еще не существует, и файл override.conf:
sudo mkdir -p /etc/systemd/system/rpi-display-backlight.service.d/
sudo nano /etc/systemd/system/rpi-display-backlight.service.d/override.conf
  1. В файле override.conf добавьте следующие строки, чтобы назначить отдельный срез:
[Service]
Slice=system-separate.slice

Эта строка гарантирует, что рпи-display-backlight.service будет находиться в отдельно подсчитывающейся подсрезке system.slice. Если вы хотите, чтобы он вообще не учитывался в system.slice, настройте Slice=separate.slice.

  1. После изменений всегда нужно перезагружать демона systemd, чтобы он учел новые конфигурации:
sudo systemctl daemon-reload

Также учтите, что для внесения изменений удобнее использовать команду systemctl edit, которая упрощает управление конфигурациями и автоматически выполняет перезагрузку демона.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...