Управление ресурсами с помощью cgroups в systemd

Меня как системного администратора немного больше расстраивает, чем неожиданное исчерпание вычислительных ресурсов. Более чем в одном случае я заполнял все доступное дисковое пространство в разделе, у меня заканчивалась оперативная память и не хватало процессорного времени для выполнения моих задач в разумные сроки. Управление ресурсами — одна из важнейших задач, которую выполняют системные администраторы.

Смысл управления ресурсами состоит в том, чтобы гарантировать, что все процессы имеют относительно равный доступ к необходимым им системным ресурсам. Управление ресурсами также включает обеспечение того, чтобы ОЗУ, пространство на жестком диске и емкость ЦП добавлялись, когда это необходимо, или нормировались, когда это невозможно. Кроме того, следует запретить делать это пользователям, которые намеренно или случайно потребляют системные ресурсы.

Существуют инструменты, позволяющие системным администраторам контролировать различные системные ресурсы и управлять ими. Например, top и подобные инструменты позволяют отслеживать использование памяти, ввода-вывода, хранилища (диск, SSD и т. Д.), Сети, пространства подкачки, использования ЦП и тд. Эти инструменты, особенно те, которые ориентированы на ЦП, в основном основаны на парадигме, согласно которой выполняемый процесс является единицей управления. В лучшем случае они предоставляют способ отрегулировать хорошее число — и, следовательно, приоритет — или остановить запущенный процесс.

Другие инструменты, основанные на традиционном управлении ресурсами в среде SystemV, управляются /etc/security/limits.confфайлом и локальными файлами конфигурации, расположенными в /etc/security/limits.dкаталоге. Ресурсы могут быть ограничены довольно грубым, но полезным способом пользователем или группой. Ресурсы, которыми можно управлять, включают различные аспекты ОЗУ, общее время процессора в день, общий объем данных, приоритет, хорошее число, количество одновременных входов в систему, количество процессов, максимальный размер файла и многое другое.

Использование cgroups для управления процессами

Одно из основных различий между systemd и SystemV заключается в том, как они обрабатывают процессы. SystemV рассматривает каждый процесс как отдельную сущность. systemd собирает связанные процессы в группы управления, называемые cgroups (сокращение от control groups), и управляет системными ресурсами для cgroup в целом. Это означает, что ресурсами можно управлять для каждого приложения, а не отдельными процессами, составляющими приложение.

Блоки управления для контрольных групп называются блоками слайсов. Срезы — это концептуализация, которая позволяет systemd упорядочивать процессы в древовидном формате для простоты управления.

Просмотр контрольных групп

Я начну с некоторых команд, которые позволяют просматривать различные типы информации о контрольных группах. Команда systemctl status <service>отображает информацию о срезе указанной службы, включая ее срез. В этом примере показан atдемон:

[root@testvm1 ~]# systemctl status atd.service
● atd.service - Deferred execution scheduler
Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2020-09-23 12:18:24 EDT; 1 day 3h ago
Docs: man:atd(8)
Main PID: 1010 (atd)
Tasks: 1 (limit: 14760)
Memory: 440.0K
CPU: 5ms
CGroup: /system.slice/atd.service
└─1010 /usr/sbin/atd -f
Sep 23 12:18:24 testvm1.both.org systemd[1]: Started Deferred execution scheduler.
[root@testvm1 ~]#

Это отличный пример одной из причин, по которой я считаю systemd более удобной, чем SystemV и старую программу init. Здесь гораздо больше информации, чем может предоставить SystemV. Запись cgroup включает в себя иерархическую структуру, в которой — system.sliceэто systemd (PID 1), а atd.serviceэто один уровень ниже и является частью system.sliceВторая строка записи cgroup также показывает идентификатор процесса (PID) и команду, используемую для запуска демона.

Команда systemctlпоказывает несколько записей cgroup. --allОпция показывает все кусочки, в том числе те, которые в настоящее время не активны:

[root@testvm1 ~]# systemctl -t slice --all
UNIT                             LOAD   ACTIVE   SUB    DESCRIPTION
-.slice                          loaded active   active Root Slice
system-getty.slice               loaded active   active system-getty.slice
system-lvm2\x2dpvscan.slice      loaded active   active system-lvm2\x2dpvscan.slice
system-modprobe.slice            loaded active   active system-modprobe.slice
system-sshd\x2dkeygen.slice      loaded active   active system-sshd\x2dkeygen.slice
system-systemd\x2dcoredump.slice loaded inactive dead   system-systemd\x2dcoredump.slice
system-systemd\x2dfsck.slice     loaded active   active system-systemd\x2dfsck.slice
system.slice                     loaded active   active System Slice
user-0.slice                     loaded active   active User Slice of UID 0
user-1000.slice                  loaded active   active User Slice of UID 1000
user.slice                       loaded active   active User and Session Slice

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

11 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.
[root@testvm1 ~]#

Первое, на что следует обратить внимание в этих данных, — это то, что они показывают пользовательские фрагменты для UID 0 (root) и 1000, что является моим логином пользователя. Это показывает только срезы, а не сервисы, которые являются частью каждого среза. Эти данные показывают, что срез создается для каждого пользователя в момент его входа в систему. Это может обеспечить способ управления всеми задачами пользователя как единой сущностью контрольной группы.

Изучите иерархию cgroup

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

psКоманда может быть использована для отображения процессов и их места в иерархии контрольной группы. Обратите внимание, что при использовании psкоманды необходимо указать нужные столбцы данных . Я значительно уменьшил объем вывода этой команды ниже, но я попытался оставить достаточно, чтобы вы могли почувствовать, что вы можете найти в своих системах:

[root@testvm1 ~]# ps xawf -eo pid,user,cgroup,args
    PID USER     CGROUP                      COMMAND
      2 root     -                           [kthreadd]
      3 root     -                            \_ [rcu_gp]
      4 root     -                            \_ [rcu_par_gp]
      6 root     -                            \_ [kworker/0:0H-kblockd]
      9 root     -                            \_ [mm_percpu_wq]
     10 root     -                            \_ [ksoftirqd/0]
     11 root     -                            \_ [rcu_sched]
     12 root     -                            \_ [migration/0]
     13 root     -                            \_ [cpuhp/0]
     14 root     -                            \_ [cpuhp/1]
<SNIP>
 625406 root     -                            \_ [kworker/3:0-ata_sff]
 625409 root     -                            \_ [kworker/u8:0-events_unbound]
      1 root     0::/init.scope              /usr/lib/systemd/systemd --switched-root --system --deserialize 30
    588 root     0::/system.slice/systemd-jo /usr/lib/systemd/systemd-journald
    599 root     0::/system.slice/systemd-ud /usr/lib/systemd/systemd-udevd
    741 root     0::/system.slice/auditd.ser /sbin/auditd
    743 root     0::/system.slice/auditd.ser  \_ /usr/sbin/sedispatch
    764 root     0::/system.slice/ModemManag /usr/sbin/ModemManager
    765 root     0::/system.slice/NetworkMan /usr/sbin/NetworkManager --no-daemon
    767 root     0::/system.slice/irqbalance /usr/sbin/irqbalance --foreground
    779 root     0::/system.slice/mcelog.ser /usr/sbin/mcelog --ignorenodev --daemon --foreground
    781 root     0::/system.slice/rngd.servi /sbin/rngd -f
    782 root     0::/system.slice/rsyslog.se /usr/sbin/rsyslogd -n
<SNIP>
    893 root     0::/system.slice/sshd.servi sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
   1130 root     0::/user.slice/user-0.slice  \_ sshd: root [priv]
   1147 root     0::/user.slice/user-0.slice  |   \_ sshd: root@pts/0
   1148 root     0::/user.slice/user-0.slice  |       \_ -bash
   1321 root     0::/user.slice/user-0.slice  |           \_ screen
   1322 root     0::/user.slice/user-0.slice  |               \_ SCREEN
   1323 root     0::/user.slice/user-0.slice  |                   \_ /bin/bash
 498801 root     0::/user.slice/user-0.slice  |                   |   \_ man systemd.resource-control
 498813 root     0::/user.slice/user-0.slice  |                   |       \_ less
   1351 root     0::/user.slice/user-0.slice  |                   \_ /bin/bash
 123293 root     0::/user.slice/user-0.slice  |                   |   \_ man systemd.slice
 123305 root     0::/user.slice/user-0.slice  |                   |       \_ less
   1380 root     0::/user.slice/user-0.slice  |                   \_ /bin/bash
 625412 root     0::/user.slice/user-0.slice  |                   |   \_ ps xawf -eo pid,user,cgroup,args
 625413 root     0::/user.slice/user-0.slice  |                   |   \_ less
 246795 root     0::/user.slice/user-0.slice  |                   \_ /bin/bash
 625338 root     0::/user.slice/user-0.slice  |                       \_ /usr/bin/mc -P /var/tmp/mc-root/mc.pwd.246795
 625340 root     0::/user.slice/user-0.slice  |                           \_ bash -rcfile .bashrc
   1218 root     0::/user.slice/user-1000.sl  \_ sshd: dboth [priv]
   1233 dboth    0::/user.slice/user-1000.sl      \_ sshd: dboth@pts/1
   1235 dboth    0::/user.slice/user-1000.sl          \_ -bash
<SNIP>
   1010 root     0::/system.slice/atd.servic /usr/sbin/atd -f
   1011 root     0::/system.slice/crond.serv /usr/sbin/crond -n
   1098 root     0::/system.slice/lxdm.servi /usr/sbin/lxdm-binary
   1106 root     0::/system.slice/lxdm.servi  \_ /usr/libexec/Xorg -background none :0 vt01 -nolisten tcp -novtswitch -auth /var/run/lxdm/lxdm-:0.auth
 370621 root     0::/user.slice/user-1000.sl  \_ /usr/libexec/lxdm-session
 370631 dboth    0::/user.slice/user-1000.sl      \_ xfce4-session
 370841 dboth    0::/user.slice/user-1000.sl          \_ /usr/bin/ssh-agent /bin/sh -c exec -l bash -c "/usr/bin/startxfce4"
 370911 dboth    0::/user.slice/user-1000.sl          \_ xfwm4 --display :0.0 --sm-client-id 2dead44ab-0b4d-4101-bca4-e6771f4a8ac2
 370930 dboth    0::/user.slice/user-1000.sl          \_ xfce4-panel --display :0.0 --sm-client-id 2ce38b8ef-86fd-4189-ace5-deec1d0e0952
 370942 dboth    0::/user.slice/user-1000.sl          |   \_ /usr/lib64/xfce4/panel/wrapper-2.0 /usr/lib64/xfce4/panel/plugins/libsystray.so 6 23068680 systr
ay Notification Area Area where notification icons appear
 370943 dboth    0::/user.slice/user-1000.sl          |   \_ /usr/lib64/xfce4/panel/wrapper-2.0 /usr/lib64/xfce4/panel/plugins/libpulseaudio-plugin.so 8 2306
8681 pulseaudio PulseAudio Plugin Adjust the audio volume of the PulseAudio sound system
 370944 dboth    0::/user.slice/user-1000.sl          |   \_ /usr/lib64/xfce4/panel/wrapper-2.0 /usr/lib64/xfce4/panel/plugins/libxfce4powermanager.so 9 2306
8682 power-manager-plugin Power Manager Plugin Display the battery levels of your devices and control the brightness of your display
 370945 dboth    0::/user.slice/user-1000.sl          |   \_ /usr/lib64/xfce4/panel/wrapper-2.0 /usr/lib64/xfce4/panel/plugins/libnotification-plugin.so 10 2
3068683 notification-plugin Notification Plugin Notification plugin for the Xfce panel
 370948 dboth    0::/user.slice/user-1000.sl          |   \_ /usr/lib64/xfce4/panel/wrapper-2.0 /usr/lib64/xfce4/panel/plugins/libactions.so 14 23068684 acti
ons Action Buttons Log out, lock or other system actions
 370934 dboth    0::/user.slice/user-1000.sl          \_ Thunar --sm-client-id 2cfc809d8-4e1d-497a-a5c5-6e4fa509c3fb --daemon
 370939 dboth    0::/user.slice/user-1000.sl          \_ xfdesktop --display :0.0 --sm-client-id 299be0608-4dca-4055-b4d6-55ec6e73a324
 370962 dboth    0::/user.slice/user-1000.sl          \_ nm-applet
<SNIP>

Вы можете просмотреть всю иерархию с помощью systemd-cglsкоманды, которая немного проще, поскольку не требует каких-либо сложных параметров.

Я значительно сократил это древовидное представление. также, но я оставил достаточно, чтобы дать вам некоторое представление об объеме данных, а также о типах записей, которые вы должны увидеть, когда сделаете это в своей системе. Я сделал это на одной из моих виртуальных машин, и это примерно 200 строк; объем данных с моей основной рабочей станции составляет около 250 строк:

[root@testvm1 ~]# systemd-cgls
Control group /:
-.slice
├─user.slice
│ ├─user-0.slice
│ │ ├─session-1.scope
│ │ │ ├─  1130 sshd: root [priv]
│ │ │ ├─  1147 sshd: root@pts/0
│ │ │ ├─  1148 -bash
│ │ │ ├─  1321 screen
│ │ │ ├─  1322 SCREEN
│ │ │ ├─  1323 /bin/bash
│ │ │ ├─  1351 /bin/bash
│ │ │ ├─  1380 /bin/bash
│ │ │ ├─123293 man systemd.slice
│ │ │ ├─123305 less
│ │ │ ├─246795 /bin/bash
│ │ │ ├─371371 man systemd-cgls
│ │ │ ├─371383 less
│ │ │ ├─371469 systemd-cgls
│ │ │ └─371470 less
│ │ └─user@0.service …
│ │   ├─dbus-broker.service
│ │   │ ├─1170 /usr/bin/dbus-broker-launch --scope user
│ │   │ └─1171 dbus-broker --log 4 --controller 12 --machine-id 3bccd1140fca488187f8a1439c832f07 --max-bytes 100000000000000 --max-fds 25000000000000 --max->
│ │   ├─gvfs-daemon.service
│ │   │ └─1173 /usr/libexec/gvfsd
│ │   └─init.scope
│ │     ├─1137 /usr/lib/systemd/systemd --user
│ │     └─1138 (sd-pam)
│ └─user-1000.slice
│   ├─user@1000.service …
│   │ ├─dbus\x2d:1.2\x2dorg.xfce.Xfconf.slice
│   │ │ └─dbus-:1.2-org.xfce.Xfconf@0.service
│   │ │   └─370748 /usr/lib64/xfce4/xfconf/xfconfd
│   │ ├─dbus\x2d:1.2\x2dca.desrt.dconf.slice
│   │ │ └─dbus-:1.2-ca.desrt.dconf@0.service
│   │ │   └─371262 /usr/libexec/dconf-service
│   │ ├─dbus-broker.service
│   │ │ ├─1260 /usr/bin/dbus-broker-launch --scope user
│   │ │ └─1261 dbus-broker --log 4 --controller 11 --machine-id
<SNIP>
│   │ └─gvfs-mtp-volume-monitor.service
│   │   └─370987 /usr/libexec/gvfs-mtp-volume-monitor
│   ├─session-3.scope
│   │ ├─1218 sshd: dboth [priv]
│   │ ├─1233 sshd: dboth@pts/1
│   │ └─1235 -bash
│   └─session-7.scope
│     ├─370621 /usr/libexec/lxdm-session
│     ├─370631 xfce4-session
│     ├─370805 /usr/bin/VBoxClient --clipboard
│     ├─370806 /usr/bin/VBoxClient --clipboard
│     ├─370817 /usr/bin/VBoxClient --seamless
│     ├─370818 /usr/bin/VBoxClient --seamless
│     ├─370824 /usr/bin/VBoxClient --draganddrop
│     ├─370825 /usr/bin/VBoxClient --draganddrop
│     ├─370841 /usr/bin/ssh-agent /bin/sh -c exec -l bash -c "/usr/bin/startxfce4"
│     ├─370910 /bin/gpg-agent --sh --daemon --write-env-file /home/dboth/.cache/gpg-agent-info
│     ├─370911 xfwm4 --display :0.0 --sm-client-id 2dead44ab-0b4d-4101-bca4-e6771f4a8ac2
│     ├─370923 xfsettingsd --display :0.0 --sm-client-id 261b4a437-3029-461c-9551-68c2c42f4fef
│     ├─370930 xfce4-panel --display :0.0 --sm-client-id 2ce38b8ef-86fd-4189-ace5-deec1d0e0952
│     ├─370934 Thunar --sm-client-id 2cfc809d8-4e1d-497a-a5c5-6e4fa509c3fb --daemon
│     ├─370939 xfdesktop --display :0.0 --sm-client-id 299be0608-4dca-4055-b4d6-55ec6e73a324
<SNIP>
└─system.slice
  ├─rngd.service
  │ └─1650 /sbin/rngd -f
  ├─irqbalance.service
  │ └─1631 /usr/sbin/irqbalance --foreground
  ├─fprintd.service
  │ └─303383 /usr/libexec/fprintd
  ├─systemd-udevd.service
  │ └─956 /usr/lib/systemd/systemd-udevd
<SNIP>
  ├─systemd-journald.service
  │ └─588 /usr/lib/systemd/systemd-journald
  ├─atd.service
  │ └─1010 /usr/sbin/atd -f
  ├─system-dbus\x2d:1.10\x2dorg.freedesktop.problems.slice
  │ └─dbus-:1.10-org.freedesktop.problems@0.service
  │   └─371197 /usr/sbin/abrt-dbus -t133
  ├─sshd.service
  │ └─893 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
  ├─vboxservice.service
  │ └─802 /usr/sbin/VBoxService -f
  ├─crond.service
  │ └─1011 /usr/sbin/crond -n
  ├─NetworkManager.service
  │ └─765 /usr/sbin/NetworkManager --no-daemon
  ├─switcheroo-control.service
  │ └─787 /usr/libexec/switcheroo-control
 <SNIP>

Это древовидное представление показывает все пользовательские и системные срезы, а также службы и программы, работающие в каждой контрольной группе. Обратите внимание на единицы, называемые «областями», которые группируют связанные программы в единицу управления user-1000.sliceв приведенном выше списке. Группа user-1000.slice/session-7.scopecgroup содержит иерархию программ рабочего стола графического интерфейса пользователя, начиная с сеанса диспетчера отображения LXDM и всех его подзадач, включая такие вещи, как оболочка Bash и файловый менеджер графического интерфейса пользователя Thunar.

Единицы области видимости не определены в файлах конфигурации, но генерируются програмно в результате запуска групп связанных программ. Единицы области видимости не создают и не запускают процессы, выполняемые как часть этой контрольной группы. Все процессы в рамках области действия равны, и нет внутренней иерархии. Жизнь области начинается, когда создается первый процесс, и заканчивается, когда последний процесс уничтожается.

Откройте несколько окон на рабочем столе, например эмуляторы терминала, LibreOffice или что угодно, затем переключитесь на доступную виртуальную консоль и запустите что-то вроде topили Midnight Commander . Запустите systemd-cglsкоманду на своем хосте и обратите внимание на общую иерархию и единицы измерения.

Эта systemd-cglsкоманда обеспечивает более полное представление иерархии контрольных групп (и подробностей о составляющих ее единицах), чем любая другая команда, которую я нашел. Я предпочитаю более четкое представление дерева, чем то, что psпредоставляет команда.