Come utilizzare i cgroup per limitare tutti i processi tranne la whitelist a una singola CPU?


26

C'è una guida ai cgroup di Red Hat che è forse una specie di utile (ma non risponde a questa domanda).

So come limitare un processo specifico a una CPU specifica, durante il comando per avviare quel processo, tramite:

Innanzitutto, inserendo il seguente * in /etc/cgconfig.conf:

mount {
  cpuset =  /cgroup/cpuset;
  cpu =     /cgroup/cpu;
  cpuacct = /cgroup/cpuacct;
  memory =  /cgroup/memory;
  devices = /cgroup/devices;
  freezer = /cgroup/freezer;
  net_cls = /cgroup/net_cls;
  blkio =   /cgroup/blkio;
}

group cpu0only {
  cpuset {
    cpuset.cpus = 0;
    cpuset.mems = 0;
  }
}

Quindi avvia un processo e assegnalo specificamente a quel cgroup usando:

cgexec -g cpuset:cpu0only myprocessname

Posso limitare automaticamente tutte le istanze di un nome di processo specifico (penso che sia corretto) inserendo quanto segue /etc/cgrules.conf:

# user:process  controller  destination
*:myprocessname cpuset      cpu0only

La mia domanda è: come posso fare il contrario ?

In altre parole, come posso assegnare tutti i processi tranne un set specifico di processi autorizzati e i loro figli a un cgroup limitato?


Sulla base di ciò che ho studiato, ma non ho testato, credo che una soluzione parziale sarebbe:

Aggiungi un cgroup "senza restrizioni":

group anycpu {
  cpuset {
    cpuset.cpus = 0-31;
    cpuset.mems = 0;  # Not sure about this param but it seems to be required
  }
}

Assegna esplicitamente il mio processo al gruppo senza restrizioni e tutto il resto al gruppo con restrizioni:

# user:process  controller  destination
*:myprocessname cpuset      anycpu
*               cpuset      cpu0only

Tuttavia, l'avvertimento su questo sembra essere (dalla lettura dei documenti, non dai test, così granello di sale) che i figli di myprocessnamesaranno riassegnati al cpu0onlycgroup ristretto .

Un possibile approccio alternativo sarebbe quello di creare un utente per l'esecuzione myprocessnamee avere tutti i processi di quell'utente senza restrizioni e tutto il resto limitato. Tuttavia, nel mio caso d'uso reale, il processo deve essere eseguito da root e ci sono altri processi che devono anche essere eseguiti da root che dovrebbero essere limitati.

Come posso farlo con i cgroups?


Se ciò non è possibile con i cgroups (che ora sospetto sia il caso), le mie idee di soluzioni parziali sono corrette e funzioneranno come penso?

* Dichiarazione di non responsabilità: questo probabilmente non è un esempio di codice minimo; non capisco tutte le parti, quindi non so quali non siano necessarie.

Risposte:


30

AGGIORNAMENTO: Notare che la seguente risposta si applica a RHEL 6. In RHEL 7, la maggior parte dei cgroups sono gestiti da systemd e libcgroup è deprecato.


Dal momento che questo distacco domanda ho studiato tutta la guida che ho linkato sopra, così come la maggior parte della cgroups.txt documentazione e cpusets.txt . Ora so più di quanto mi aspettassi di conoscere i cgroups, quindi risponderò alla mia domanda qui.

Esistono diversi approcci che puoi adottare. Il contatto della nostra azienda presso Red Hat (un architetto tecnico) ha raccomandato di non applicare una limitazione generale di tutti i processi rispetto a un approccio più dichiarativo, limitando solo i processi che volevamo specificamente limitati. La ragione di ciò, secondo le sue affermazioni sull'argomento, è che è possibile che le chiamate di sistema dipendano dal codice dello spazio utente (come i processi LVM) che, se limitato, potrebbe rallentare il sistema, l'opposto dell'effetto previsto. Così ho finito per limitare diversi processi con nomi specifici e lasciare tutto il resto da solo.

Inoltre, voglio menzionare alcuni dati di base del cgroup che mi mancavano quando ho pubblicato la mia domanda.


I cgroup non dipendono dall'installazione libcgroup. Tuttavia, si tratta di un set di strumenti per la gestione automatica della configurazione dei cgroup e delle assegnazioni dei processi ai cgroups e può essere molto utile.

Ho scoperto che anche gli strumenti di libcgroup possono essere fuorvianti, poiché il pacchetto libcgroup è basato su una propria serie di astrazioni e ipotesi sull'uso dei cgroup, che sono leggermente diverse dall'attuale implementazione dei cgroup a livello di kernel. (Posso fare degli esempi ma ci vorrebbe del lavoro; commenta se sei interessato.)

Pertanto, prima di utilizzare strumenti libcgroup (come /etc/cgconfig.conf, /etc/cgrules.conf, cgexec, cgcreate, cgclassify, etc.) ho fortemente raccomando di avere molta familiarità con il /cgroupfilesystem virtuale in sé, e creare manualmente cgroups, gerarchie cgroup (comprese le gerarchie con più sottosistemi allegati, che libcgroup sneakily e abstract leakily di distanza), riassegnando i processi a diversi cgroup correndo echo $the_pid > /cgroup/some_cgroup_hierarchy/a_cgroup_within_that_hierarchy/taskse altri compiti apparentemente magici che si libcgroupsvolgono sotto il cofano.


Un altro concetto di base che mi mancava era che se il /cgroupfilesystem virtuale è montato sul vostro sistema a tutti (o, più precisamente, se uno qualsiasi dei sottosistemi di cgroup alias "controllori" sono montati a tutti), allora ogni processo sul vostro intero sistema è in un cgroup. Non esiste una cosa come "alcuni processi sono in un cgroup e altri no".

Esiste quello che viene chiamato il cgroup radice per una determinata gerarchia, che possiede tutte le risorse del sistema per i sottosistemi collegati. Ad esempio, una gerarchia di cgroup a cui sono collegati i sottosistemi cpuset e blkio, avrebbe un cgroup di root che possederebbe tutti i cpus sul sistema e tutti i blkio sul sistema e potrebbe condividere alcune di tali risorse con i cgroup secondari. Non puoi limitare il cgroup di root perché possiede tutte le risorse del tuo sistema, quindi limitarlo non avrebbe nemmeno senso.


Alcuni altri semplici dati che mi mancavano su libcgroup:

Se lo usi /etc/cgconfig.conf, dovresti assicurarti che chkconfig --list cgconfigmostra che cgconfigè impostato per essere eseguito all'avvio del sistema.

Se si modifica /etc/cgconfig.conf, è necessario eseguire service cgconfig restartper caricare le modifiche. (E i problemi con l'arresto del servizio o l'esecuzione cgclearsono molto comuni quando si scherza con i test. Per il debug, ad esempio lsof /cgroup/cpuset, si consiglia se cpusetè il nome della gerarchia di cgroup che si sta utilizzando.)

Se si desidera utilizzare /etc/cgrules.conf, è necessario assicurarsi che il "daemon del motore delle regole del cgroup" ( cgrulesengd) sia in esecuzione: service cgred starte chkconfig cgred on. (E dovresti essere consapevole di una possibile ma improbabile condizione di gara relativa a questo servizio, come descritto nella Guida alla gestione delle risorse di Red Hat nella sezione 2.8.1 in fondo alla pagina.)

Se vuoi scherzare manualmente e configurare i tuoi cgroups usando il filesystem virtuale (che consiglio per il primo utilizzo), puoi farlo e quindi creare un cgconfig.conffile per rispecchiare la tua configurazione usando cgsnapshotcon le sue varie opzioni.


E infine, l'informazione chiave che mi mancava quando ho scritto quanto segue:

Tuttavia, l'avvertenza su questo sembra essere ... che i figli di nomecrocessname verranno riassegnati al cgroup limitato cpu0only.

Avevo ragione, ma c'è un'opzione di cui non ero a conoscenza.

cgexec è il comando per avviare un processo / eseguire un comando e assegnarlo a un cgroup.

cgclassify è il comando per assegnare un processo già in esecuzione a un cgroup.

Entrambi impediranno anche cgred( cgrulesengd) di riassegnare il processo specificato a un diverso cgroup basato su /etc/cgrules.conf.

Entrambi cgexece cgclassifysupportano la --stickybandiera, che impedisce inoltrecgred di riassegnare i processi figlio in base a /etc/cgrules.conf.


Quindi, la risposta alla domanda mentre l'ho scritta (sebbene non l'installazione che ho finito per implementare, a causa dei consigli del nostro architetto tecnico Red Hat sopra menzionati) è:

Crea il cpu0onlye anycpucgroup come descritto nella mia domanda. (Assicurarsi che cgconfigsia impostato per essere eseguito all'avvio.)

Fai la * cpuset cpu0onlyregola come descritto nella mia domanda. (E assicurarsi che cgredsia impostato per essere eseguito all'avvio.)

Avviare tutti i processi che voglio senza restrizioni con: cgexec -g cpuset:anycpu --sticky myprocessname.

Tali processi saranno illimitati e anche tutti i loro processi figlio saranno illimitati. Tutto il resto del sistema sarà limitato alla CPU 0 (una volta riavviato, poiché cgrednon applica cgrules ai processi già in esecuzione a meno che non cambino il loro EUID). Questo non è del tutto consigliabile, ma era quello che inizialmente avevo richiesto e si può fare con i cgroups.


Wow. freddo. come ha ottenuto 0 voti?
Mikeserv,

@mikeserv, grazie. :) Rispondi alla tua domanda: controlla le date; Ho appena scritto questa risposta ieri.
Wildcard il

1
l'ho visto. ma è stato 24 ore fa. probabilmente la sua causa è lunga. le cose buone a volte possono essere trascurate in quel modo. e comunque, le risposte con molti voti molto presto sono molto raramente buone - le informazioni non possono essere così utili se così tante persone già lo sanno. questo è uno dei buoni, però. i cgroup sono misteriosi.
Mikeserv,
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.