Il mese scorso ho parlato all'ApacheCon sui Cgroup. Sembra che pochissimi utenti Linux (incluso il sottoscritto fino a non molto tempo fa) abbiano familiarità con i Cgroup e la loro potenza. È un peccato, perché i Cgroup sono molto potenti e consentono di allocare le risorse sui server in modo molto più granulare rispetto a qualsiasi altro strumento disponibile nel toolkit di Linux. Inoltre, è integrato direttamente nel kernel e viene fornito di serie con la maggior parte delle distribuzioni Linux.
In questo articolo spiegherò come utilizzare i Cgroup con Docker, come una sorta di seguito di un altro discorso che ho tenuto al Docker Meetup ad Austin, in Texas.
Questo articolo richiede una comprensione di base dei Cgroup. Se i Cgroup sono una novità assoluta per te, ti consiglio di dare un’occhiata alle mie slide dell'ApacheCon e alle risorse alla fine. Non preoccuparti, però, non andremo troppo a fondo. Se dai solo una rapida occhiata alle slide, dovresti essere in grado di afferrare i concetti di base.
Docker e Cgroup
Docker viene fornito con due driver diversi: LXC e libcontainer. Il driver LXC è il driver legacy, mentre libcontainer è il driver nuovo e predefinito. Nella maggior parte dei casi, libcontainer è il driver preferito, poiché è lì che avviene l'innovazione (ad esempio docker exec non funziona con il driver LXC).
È tuttavia importante notare che esistono due driver diversi, poiché non tutte le funzionalità dei Cgroup sono state ancora portate su libcontainer (o almeno esposte a Docker). Quando si utilizza il driver LXC, si passano semplicemente gli argomenti LXC in modo diretto, mentre con libcontainer ci sono argomenti espliciti per le policy dei Cgroup esposti a Docker. Sarà necessario impostare esplicitamente un driver all'avvio del daemon Docker, quindi non è possibile eseguire i due driver contemporaneamente.
Ecco un esempio di come puoi verificare:
[bash light=”true”] # Con il driver LXC$ docker run -d –name=’lxc_test’ \
–lxc-conf="lxc.cgroup.cpu.shares=50" \
busybox
# Con il driver libcontainer
$ docker run -d –name=’libcontainer_test’ \
–cpu-shares=50 \
busybox
[/bash]
Ecco una panoramica di alcune funzionalità dei Cgroup e di come si mappano tra i due driver:
| Funzionalità | Libcontainer | LXC |
|---|---|---|
| Quota CPU relativa | -c, –cpu-shares | –lxc-conf=”lxc.cgroup.cpu.shares” |
| Blocco su un core CPU | –cpuset-cpus | –lxc-conf=”lxc.cgroup.cpuset.cpus” |
| Limite memoria | -m, –memory | –lxc-conf=”lxc.cgroup.cpuset.mems” |
LXC
Se desideri utilizzare il driver LXC per Docker, dovrai prima abilitarlo. Il metodo per farlo varia a seconda della distribuzione Linux, ma ecco le istruzioni su come abilitare il driver LXC su Ubuntu 14.04.
Come accennato in precedenza, in questo modo si rinuncia ad alcune funzionalità. Pertanto, a meno che non si abbia realmente bisogno di una funzionalità non ancora esposta in Docker tramite libcontainer, è consigliabile attenersi al driver predefinito.
Alcune utili policy dei Cgroup che non sono ancora state esposte in libcontainer includono il throttling dell'I/O (trattato nella presentazione), che può essere molto utile per determinate applicazioni.
Se hai deciso di utilizzare il driver LXC, l'aggiunta di argomenti è molto semplice. Tutto ciò che devi fare è aggiungere l'argomento --lxc-conf e passare la policy dei Cgroup che desideri impostare.
Libcontainer
Come puoi vedere nella tabella sopra, le policy di base dei Cgroup sono già esposte nella versione corrente di Docker (la 1.6 al momento della stesura di questo articolo).
Utilizzare queste policy è molto semplice. Se ad esempio desideri bloccare un container Docker sul primo core della CPU, dovrai aggiungere --cpuset-cpus=0 al tuo docker run comando.
Puoi anche utilizzare l'argomento --cgroup-parent con libcontainer e impostare manualmente vincoli di risorse più granulari. Lo mapperesti quindi a quel gruppo utilizzando l'argomento.
Demo: Docker con i Cgroup
Nello screencast qui sotto, useremo due container Docker (‘low_prio’ e ‘high_prio’). Utilizziamo il container di base ‘busybox’ ed eseguiamo md5sum /dev/urandom per simulare un processo ad alto consumo di CPU. Per impostazione predefinita, questo consumerebbe tutte le risorse CPU disponibili. Tuttavia, applicheremo due policy Cgroup per gestire le risorse. Per prima cosa useremo ‘cpuset.cpus’ per vincolare i container allo stesso core della CPU (core 0).
Successivamente useremo ‘cpu.shares’ per assegnare una quota di CPU relativa. Assegniamo al container ‘low_prio’ un valore di 20 e a ‘high_prio’ un valore di 80. Ciò significa che il 20% della CPU sarà allocato al container ‘low_prio’ e l’80% della CPU sarà allocato al container ‘high_prio’. Si noti tuttavia che la quota relativa è una scala arbitraria (avremmo potuto usare anche 2 e 8 come valori).
Dopo aver dimostrato che la gestione delle risorse funziona effettivamente, avviamo lo stesso set di container senza alcuna policy Cgroup per vedere come si comportano.
Come riferimento, ecco i comandi utilizzati per avviare i container.
[bash light=”true”] $ docker run -d \–name=’low_prio’ \
–cpuset-cpus=0 \
–cpu-shares=20 \
busybox md5sum /dev/urandom
$ docker run -d \
–name=’high_prio’ \
–cpuset-cpus=0 \
–cpu-shares=80 \
busybox md5sum /dev/urandom
[/bash]
Riepilogo
Se gestisci più container Docker sullo stesso host, l’uso di Cgroup per gestire le risorse tra i container ha molto senso. Ad esempio, potresti avere alcune attività di elaborazione in background in esecuzione in un container e un altro container che serve contenuti agli utenti. In tal caso, puoi utilizzare le tue nuove conoscenze per assicurarti di dare la priorità ai container rivolti agli utenti rispetto alle attività in background.
Commenti
Ancora nessun commento. Scrivi il primo.