Come creare cgroup di utenti con systemd


14

Uso lxccontenitori non privilegiati Arch Linux. Ecco le informazioni di base sul sistema:

[chb@conventiont ~]$ uname -a
Linux conventiont 3.17.4-Chb #1 SMP PREEMPT Fri Nov 28 12:39:54 UTC 2014 x86_64 GNU/Linux

È un kernel personalizzato / compilato con user namespace enabled:

[chb@conventiont ~]$ lxc-checkconfig 
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
Multiple /dev/pts instances: enabled

--- Control groups ---
Cgroup: enabled
Cgroup clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled
Macvlan: enabled
Vlan: enabled
File capabilities: enabled

Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig

[chb@conventiont ~]$ systemctl --version
systemd 217
+PAM -AUDIT -SELINUX -IMA -APPARMOR +SMACK -SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID -ELFUTILS +KMOD +IDN 

Purtroppo, al momento systemdnon gioca bene lxc. Soprattutto l'impostazione cgroupsper un utente non root sembra non funzionare bene o non ho familiarità con il modo di farlo. lxcavvierà un contenitore in modalità senza privilegi solo quando può creare i cgroup necessari /sys/fs/cgroup/XXX/*. Questo tuttavia non è possibile lxcperché systemdmonta la rootgerarchia di cgroup in /sys/fs/cgroup/*. Una soluzione alternativa sembra essere la seguente:

for d in /sys/fs/cgroup/*; do
        f=$(basename $d)
        echo "looking at $f"
        if [ "$f" = "cpuset" ]; then
                echo 1 | sudo tee -a $d/cgroup.clone_children;
        elif [ "$f" = "memory" ]; then
                echo 1 | sudo tee -a $d/memory.use_hierarchy;
        fi
        sudo mkdir -p $d/$USER
        sudo chown -R $USER $d/$USER
        echo $$ > $d/$USER/tasks
done

Questo codice crea le cgroupdirectory corrispondenti nella cgroupgerarchia per un utente non privilegiato. Tuttavia, succede qualcosa che non capisco. Prima di eseguire quanto sopra vedrò questo:

[chb@conventiont ~]$ cat /proc/self/cgroup 
8:blkio:/
7:net_cls:/
6:freezer:/
5:devices:/
4:memory:/
3:cpu,cpuacct:/
2:cpuset:/
1:name=systemd:/user.slice/user-1000.slice/session-c1.scope

Dopo aver eseguito il codice di cui sopra che vedo nella shell, l'ho eseguito in:

[chb@conventiont ~]$ cat /proc/self/cgroup 
8:blkio:/chb
7:net_cls:/chb
6:freezer:/chb
5:devices:/chb
4:memory:/chb
3:cpu,cpuacct:/chb
2:cpuset:/chb
1:name=systemd:/chb

Ma in qualsiasi altra shell vedo ancora:

[chb@conventiont ~]$ cat /proc/self/cgroup 
8:blkio:/
7:net_cls:/
6:freezer:/
5:devices:/
4:memory:/
3:cpu,cpuacct:/
2:cpuset:/
1:name=systemd:/user.slice/user-1000.slice/session-c1.scope

Quindi, posso avviare il mio lxccontenitore senza privilegi nella shell che ho eseguito il codice sopra menzionato ma non in nessun altro.

  1. Qualcuno può spiegare questo comportamento?

  2. Qualcuno ha trovato un modo migliore per impostare il necessario cgroupscon una versione corrente di systemd( >= 217)?

Risposte:


13

Una soluzione migliore e più sicura è installarla cgmanagered eseguirla con systemctl start cgmanager(su una systemddistribuzione basata su). Puoi avere il tuo rootutente o se hai i sudodiritti sull'host creare cgroupsper il tuo utente senza privilegi in tutti i controller con:

sudo cgm create all $USER
sudo cgm chown all $USER $(id -u $USER) $(id -g $USER)

Una volta che sono stati creati per il tuo utente senza privilegi, può spostare i processi a cui ha accesso nel suo cgroupper ogni controller usando:

cgm movepid all $USER $PPID

Più sicuro, più veloce, più affidabile dello script di shell che ho pubblicato.

Soluzione manuale:

Per rispondere 1.

for d in /sys/fs/cgroup/*; do
        f=$(basename $d)
        echo "looking at $f"
        if [ "$f" = "cpuset" ]; then
                echo 1 | sudo tee -a $d/cgroup.clone_children;
        elif [ "$f" = "memory" ]; then
                echo 1 | sudo tee -a $d/memory.use_hierarchy;
        fi
        sudo mkdir -p $d/$USER
        sudo chown -R $USER $d/$USER
        echo $$ > $d/$USER/tasks
done

Ero ignaro di quello che stava succedendo esattamente quando ho scritto quella sceneggiatura, ma leggere questo e sperimentare un po 'mi ha aiutato a capire cosa sta succedendo. Quello che sto sostanzialmente facendo in questo script è creare una nuova cgroupsessione per l'attuale, userche è quello che ho già affermato sopra. Quando eseguo questi comandi nella corrente shello li eseguo in uno script e lo faccio in modo che venga valutato nella corrente shelle non in un subshell(tramite . scriptThe .è importante che funzioni!) È che non apro solo una nuova sessione per userma aggiungi la shell corrente come processo che viene eseguito in questo nuovo cgroup. Posso ottenere lo stesso effetto eseguendo lo script in una subshell e quindi scendere nella cgroupgerarchia in chb subcgroupe utilizzareecho $$ > tasksper aggiungere la shell corrente a ogni membro di chb cgroup hierarchy.

Quindi, quando corro lxcin quella shell corrente, anche il mio contenitore diventerà un membro di tutte le chb subcgroups di cui fa parte la corrente shell. Vale a dire che il mio containereredita lo cgroupstato del mio shell. Questo spiega anche perché non funziona in nessun'altra shell che non fa parte degli attuali chb subcgroups.

Passo ancora a 2.. Probabilmente dovremo aspettare un systemdaggiornamento o ulteriori Kernelsviluppi per systemdadottare un comportamento coerente, ma preferisco comunque l'impostazione manuale poiché ti costringe a capire cosa stai facendo.


non puoi semplicemente montare i dir cgroups da qualche altra parte (domanda onesta) ? ci sono state molte controversie sui cgroups di linux e systemd l'anno scorso quando il manutentore dei cgroups apparentemente decise di dare l'autorizzazione di systemd per nome e altre app simili senza nome sulla gestione dei cgroups nello spazio utente. non sono sicuro di come sia andata a finire, ma so che era abbastanza chiaro se un utente potesse farlo un anno fa.
Mikeserv,

Probabilmente avrei potuto farlo, ma avrei dovuto impedire a systemd di montare la directory root del cgroup in primo luogo. Ogni volta che accedo alla mia macchina systemd monterà la gerarchia di root del cgroup di root in / sys / fs / cgroup e aggiunge un cgroup di utenti solo sotto la parte systemd del cgroup di root (lo puoi vedere sopra). La differenza tra distribuzioni basate su systemd e non basate su systemd prima che cambino è che, ad esempio, la gestione del cgroup di Ubuntu non è nelle mani del demone init.
lord.garbage

Viene invece gestito da un programma come ad esempio cgmanager. Oppure puoi farlo a mano come suggerito nel link a kernel.org che ho pubblicato sopra. Al momento non ho una comprensione abbastanza profonda della gestione del cgroup di systemd per giocherellare con esso più in profondità di quanto non faccia ora. Ma spero che questo cambierà presto.
lord.garbage

1
È vero, ricordo che hai affermato che in un commento a una risposta che ho dato molto tempo fa.
Chiederò

1
Il trucco è fondamentalmente: sudo systemctl start cgmanager && sudo cgm create all $USER && sudo cgm chown all $USER $(id -u) $(id -g) && sudo cgm movepid all $USER $PPID. L'ultimo comando deve essere eseguito nella shell corrente per aggiungerlo al nuovo cgroup per $USER.
lord.garbage,

0

In realtà in Archlinux, questo non funzionerà ad es. Con un utente non privilegiato (consigliato quando si usano contenitori unpriv. Lxc). cioè che l'utente non ha sudo :)

Invece, definisci il gruppo in /etc/cgconfig.conf, attiva cgconfig, cgrules (libcgroup in AUR), aggiungi anche cgrules, done .. unpriv. l'utente avrà anche gli stessi diritti.

In systemd 218 (non so quando, ma sembra che si debbano aggiungere altre due condizioni in quanto non sono impostate quando vengono create dal modo cgconfig):

cat /etc/cgconfig.conf

group lxcadmin {
perm {
    task {
        uid = lxcadmin;
        gid = lxcadmin;
    }
    admin {
        uid = lxcadmin;
        gid = lxcadmin;
    }
}
cpu { }
memory { memory.use_hierarchy = 1; }  
blkio { }
cpuacct { }
cpuset { 
    cgroup.clone_children = 1;
    cpuset.mems = 0;
    cpuset.cpus = 0-3; 
}
devices { }
freezer { }
hugetlb { }
net_cls { }
}

cat /etc/cgrules.conf
lxcadmin        *       lxcadmin/

Supponendo che lo spazio dei nomi sia compilato nel kernel.

Questo è un modello, cpus può essere in base a quanti core hai, mem può essere impostato su un valore reale, ecc. Ecc.

EDIT 2: Infine, in systemd, se desideri utilizzare l'avvio automatico con un utente così privilegiato, puoi fare:

cp /usr/lib/systemd/system/lxc{,admin}\@.service, quindi aggiungi User = lxcadmin

e abilitarlo per il contenitore di lxcadmin chiamato lolz systemctl abilitare lxcadmin @ lolz.


Grazie @Anthon, non potrò mai ottenere la formattazione del codice proprio in questi siti Web, x
Malina Salina,

Grazie. Scusa per il ritardo della risposta. Il tuo primo punto, "In realtà in Archlinux, questo non funzionerà, ad esempio, con un utente non privilegiato (consigliato quando si utilizzano contenitori unpriv. Lxc). Vale a dire che l'utente non ha sudo :)" non è valido in quanto è necessario solo l' rootamministratore per creare e chownvoi in tutti i cgroupcontroller. Questo è perfettamente bene e sicuro. movepidpuò essere fatto senza rootdiritti e, quindi, il nonpriv. l'utente non ha bisogno di alcun sudodiritto. (A proposito, libcgroupnon dovrebbe più essere usato. RHEL e altri l'hanno deprecato.)
lord.garbage

@Brauner. Come si avvia automaticamente all'avvio, quindi i contenitori dell'utente non privilegiato? In realtà le tue soluzioni elencate hanno funzionato (e sottinteso) solo un utente sudo. Il mio no. Hai chiesto come risolverlo. Ad ogni modo, c'è appena stato un aggiornamento e cgconfig ora non si avvia, poiché user.slices viene aggiunto automaticamente, prima delle impostazioni di cgconfig sembra. Questi sono privi di autorizzazioni utente (possibilmente un bug di regressione, lo sto esaminando ora). Non ho detto che fosse la soluzione migliore . Era la soluzione / a alla tua richiesta. :) Ma i miei container non si avviano ora, grrr.
Malina Salina,

Il motivo per cui ho elencato systemctl abilita lxcadmin @ container era che root poteva decidere di eseguire un contenitore unpriv all'avvio. Se l'utente stesso lo utilizza in --user (land), si avvierebbe solo quando accede, non molto utile per un server. E una nota sul tuo commento. chowning un utente in tutti i controller, consente a quell'utente di iniziare a spostare i pid nello spazio host, credo, il che rappresenta un rischio per la sicurezza.
Malina Salina,

Ehm, a quanto pare è quello che stavi facendo con il tuo metodo inizialmente elencato immagino, ma guarda questo, anche se si tratta di Ubuntu Systemd pacchetto bugs.launchpad.net/ubuntu/+source/systemd/+bug/1413927 Ma qualcosa è stato aggiornato in giorni scorsi cambiando la logica .. Sto cercando di rintracciarla.
Malina Salina,

0

Quindi ho riscontrato lo stesso problema quando provavo a far funzionare i contenitori non privilegiati LXC su CentOS 7. Non volevo usare cgmanagerperché non mi piace introdurre servizi aggiuntivi se non assolutamente necessari. Quello che ho finito invece è patching systemd usando alcune patch dal pacchetto ubuntu e una patch personalizzata per espandere l'elenco dei controller di cgroup. Ho le fonti necessarie per creare un RPM sul mio account GitHub su https://github.com/CtrlC-Root/rpmdist . Ho anche versioni patchate di shadow-utils (per subuid e subgid) e pam (per loginuid). Dopo aver installato questi RPM e configurato un utente per eseguire container non privilegiati (assegnare subuid e subgid, allocare coppie veth in lxc-usernet, creare .config / lxc / default.conf, ecc.) Posso eseguire correttamente i contenitori LXC non privilegiati.

EDIT: Un altro motivo per cui non volevo usare cgmanager è perché non volevo che i miei utenti normali dovessero usare sudo. Gli utenti regolari dovrebbero essere in grado di accedere e tutto dovrebbe "funzionare" immediatamente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.