Ricerca nel sito web

Gestire le risorse con cgroups in systemd


I Cgroup gestiscono le risorse per applicazione anziché per i singoli processi che compongono un'applicazione.

Per me, come amministratore di sistema, non c'è niente di più frustrante dell'esaurire inaspettatamente una risorsa informatica. In più di un'occasione, ho riempito tutto lo spazio disponibile su disco in una partizione, ho esaurito la RAM e non ho avuto abbastanza tempo della CPU per eseguire le mie attività in un periodo di tempo ragionevole. La gestione delle risorse è uno dei compiti più importanti svolti dagli amministratori di sistema.

Lo scopo della gestione delle risorse è garantire che tutti i processi abbiano un accesso relativamente uguale alle risorse di sistema di cui hanno bisogno. La gestione delle risorse implica anche garantire che la RAM, lo spazio sul disco rigido e la capacità della CPU vengano aggiunti quando necessario o razionati quando ciò non è possibile. Inoltre, agli utenti che monopolizzano le risorse di sistema, intenzionalmente o accidentalmente, dovrebbe essere impedito di farlo.

Esistono strumenti che consentono agli amministratori di sistema di monitorare e gestire varie risorse di sistema. Ad esempio, gli strumenti principali e simili consentono di monitorare l'utilizzo di memoria, I/O, spazio di archiviazione (disco, SSD, ecc.), rete, spazio di scambio, utilizzo della CPU e altro ancora. Questi strumenti, in particolare quelli incentrati sulla CPU, si basano principalmente sul paradigma secondo cui il processo in esecuzione è l'unità di controllo. Nella migliore delle ipotesi, forniscono un modo per modificare il numero corretto e, attraverso questo, la priorità, o per interrompere un processo in esecuzione. (Per informazioni sui numeri interessanti, vedere Monitoraggio degli host Linux e Windows con Glances.)

Altri strumenti basati sulla gestione tradizionale delle risorse in un ambiente SystemV sono gestiti dal file /etc/security/limits.conf e dai file di configurazione locale situati in /etc/security/limits.d directory . Le risorse possono essere limitate in modo abbastanza grezzo ma utile dall'utente o dal gruppo. Le risorse che possono essere gestite includono vari aspetti della RAM, tempo totale della CPU al giorno, quantità totale di dati, priorità, numero valido, numero di accessi simultanei, numero di processi, dimensione massima del file e altro ancora.

Utilizzo di cgroups per la gestione dei processi

Una delle principali differenze tra systemd e SystemV è il modo in cui gestiscono i processi. SystemV tratta ogni processo come un'entità a sé stante. systemd raccoglie i processi correlati in gruppi di controllo, chiamati cgroups (abbreviazione di control groups), e gestisce le risorse di sistema per il cgroup nel suo insieme. Ciò significa che le risorse possono essere gestite per applicazione anziché dai singoli processi che compongono un'applicazione.

Le unità di controllo per i cgroup sono chiamate unità slice. Le sezioni sono una concettualizzazione che consente a systemd di ordinare i processi in un formato ad albero per una facile gestione.

Visualizzazione dei cgroup

Inizierò con alcuni comandi che permettono di visualizzare vari tipi di informazioni sui cgroup. Il comando systemctl status visualizza le informazioni sulla sezione su un servizio specificato, inclusa la relativa sezione. Questo esempio mostra il demone 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 ~]#

Questo è un eccellente esempio del motivo per cui trovo systemd più utilizzabile di SystemV e del vecchio programma init. Ci sono molte più informazioni qui di quelle che SystemV potrebbe fornire. La voce cgroup include la struttura gerarchica in cui system.slice è systemd (PID 1) e atd.service è un livello inferiore e parte del system .slice. La seconda riga della voce cgroup mostra anche l'ID del processo (PID) e il comando utilizzato per avviare il demone.

Il comando systemctl mostra più voci cgroup. L'opzione --all mostra tutte le porzioni, comprese quelle che non sono attualmente attive:

[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 ~]#

La prima cosa da notare su questi dati è che mostrano le sezioni utente per gli UID 0 (root) e 1000, che è il mio login utente. Vengono mostrate solo le sezioni e non i servizi che fanno parte di ciascuna sezione. Questi dati mostrano che viene creata una sezione per ciascun utente nel momento in cui effettua l'accesso. Ciò può fornire un modo per gestire tutte le attività di un utente come una singola entità cgroup.

Esplora la gerarchia di cgroup

Finora tutto va bene, ma i cgroup sono gerarchici e tutte le unità di servizio funzionano come membri di uno dei cgroup. Visualizzare quella gerarchia è semplice e utilizza un vecchio comando e uno nuovo che fa parte di systemd.

Il comando ps può essere utilizzato per mappare i processi e le loro posizioni nella gerarchia del cgroup. Tieni presente che è necessario specificare le colonne di dati desiderate quando si utilizza il comando ps. Ho ridotto in modo significativo il volume di output di questo comando di seguito, ma ho provato a lasciarne abbastanza in modo che tu possa avere un'idea di cosa potresti trovare sui tuoi sistemi:

[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>

Puoi visualizzare l'intera gerarchia con il comando systemd-cgls, che è un po' più semplice perché non richiede opzioni complesse.

Ho accorciato considerevolmente questa visualizzazione ad albero. ma ne ho lasciato abbastanza per darti un'idea della quantità di dati e dei tipi di voci che dovresti vedere quando esegui questa operazione sul tuo sistema. L'ho fatto su una delle mie macchine virtuali ed è lunga circa 200 righe; la quantità di dati dalla mia postazione di lavoro principale è di circa 250 righe:

[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>

Questa visualizzazione ad albero mostra tutte le sezioni utente e sistema, nonché i servizi e i programmi in esecuzione in ciascun cgroup. Notare le unità chiamate "ambiti", che raggruppano programmi correlati in un'unità di gestione, all'interno di user-1000.slice nell'elenco sopra. Il cgroup user-1000.slice/session-7.scope contiene la gerarchia del programma desktop della GUI, a partire dalla sessione del display manager LXDM e tutte le sue attività secondarie, incluse cose come la shell Bash e la GUI Thunar gestore di file.

Le unità di ambito non sono definite nei file di configurazione ma vengono generate a livello di codice come risultato dell'avvio di gruppi di programmi correlati. Le unità ambito non creano né avviano i processi in esecuzione come parte di quel cgroup. Tutti i processi nell'ambito sono uguali e non esiste una gerarchia interna. La vita di un ambito inizia quando viene creato il primo processo e termina quando l'ultimo processo viene distrutto.

Apri diverse finestre sul desktop, come emulatori di terminale, LibreOffice o qualunque cosa tu voglia, quindi passa a una console virtuale disponibile e avvia qualcosa come top o Midnight Commander. Esegui il comando systemd-cgls sul tuo host e prendi nota della gerarchia generale e delle unità di ambito.

Il comando systemd-cgls fornisce una rappresentazione più completa della gerarchia del cgroup (e dei dettagli delle unità che lo compongono) rispetto a qualsiasi altro comando che ho trovato. Preferisco la sua rappresentazione più pulita dell'albero rispetto a quella fornita dal comando ps.

Con un piccolo aiuto dai miei amici

Dopo aver trattato queste nozioni di base, avevo programmato di entrare più in dettaglio sui cgroup e su come usarli, ma ho scoperto una serie di quattro eccellenti articoli di Steve Ovens di Red Hat sul sito gemello di Opensource.com, Enable Sysadmin. Piuttosto che riscrivere sostanzialmente gli articoli di Steve, ho deciso che sarebbe stato molto meglio sfruttare la sua esperienza su cgroup collegandoli ad essi:

  1. Un'introduzione ai cgroup da parte di un amministratore di sistema Linux
  2. Come gestire i cgroup con CPUShares
  3. Gestire i cgroup nel modo più difficile: manualmente
  4. Gestire i cgroup con systemd

Divertitevi e imparate da loro, come ho fatto io.

Altre risorse

Ci sono molte informazioni su systemd disponibili su Internet, ma molte sono concise, ottuse o addirittura fuorvianti. Oltre alle risorse menzionate in questo articolo, le seguenti pagine Web offrono informazioni più dettagliate e affidabili sull'avvio di systemd. Questo elenco è cresciuto da quando ho iniziato questa serie di articoli per riflettere la ricerca che ho svolto.

  • Il progetto Fedora ha una buona guida pratica a systemd. Ha praticamente tutto ciò che devi sapere per configurare, gestire e mantenere un computer Fedora utilizzando systemd.
  • Il progetto Fedora ha anche un buon cheat sheet che fa riferimenti incrociati ai vecchi comandi SystemV con quelli systemd comparabili.
  • La pagina man systemd.unit(5) contiene un bell'elenco delle sezioni del file unit e delle relative opzioni di configurazione insieme a descrizioni concise di ciascuna.
  • La documentazione di Red Hat contiene una buona descrizione della struttura dei file Unit oltre ad altre informazioni importanti.
  • Per informazioni tecniche dettagliate su systemd e le ragioni per crearlo, consulta la descrizione di systemd di Freedesktop.org. Questa pagina è una delle migliori che ho trovato perché contiene molti collegamenti ad altra documentazione importante e accurata.
  • La sezione "More systemd fun" di Linux.com offre informazioni e suggerimenti più avanzati su systemd.
  • Vedere la pagina man per systemd.resource-control(5).
  • Nella Guida per l'utente e l'amministratore del kernel Linux, vedere la voce Control Group v2.

C'è anche una serie di articoli profondamente tecnici per amministratori di sistema Linux scritti da Lennart Poettering, il progettista e sviluppatore principale di systemd. Questi articoli sono stati scritti tra aprile 2010 e settembre 2011, ma sono attuali tanto quanto lo erano allora. Gran parte di tutto ciò che di buono è stato scritto su systemd e sul suo ecosistema si basa su questi documenti.

  • Ripensare il PID 1
  • systemd per amministratori, parte I
  • systemd per amministratori, parte II
  • systemd per amministratori, parte III
  • systemd per amministratori, parte IV
  • systemd per amministratori, parte V
  • systemd per amministratori, parte VI
  • systemd per amministratori, parte VII
  • systemd per amministratori, parte VIII
  • systemd per amministratori, parte IX
  • systemd per amministratori, parte X
  • systemd per amministratori, parte XI