virli/tutorial/docker-advanced/security.md

3.7 KiB

Limiter les ressources

Lorsque l'on gère un environnement de production, on souhaite bien évidemment éviter tout déni de service autant que possible. Ou parfois, contenir un programme métier avec une fuite mémoire, dans certaines limites : il vaut parfois mieux le tuer et le relancer automatiquement, plutôt que d'attendre que potentiellement un autre processus se fasse tuer à sa place.

Pour cela, Docker expose tout un arsenal, reposant sur les cgroups du noyau Linux, que l'on verra plus en détail dans un prochain cours.

Mémoire

Comme on peut s'y attendre, il est possible de limiter la mémoire que peut occuper un conteneur avec l'option -m/--memory.

CPU

En ce qui concerne la limitation d'utilisation du CPU, ce n'est pas aussi simple. En effet, on ne peut pas définir le nombre d'instructions par seconde qu'un conteneur est autorisé à consommer.

On ne peut définir qu'un taux d'utilisation relatif par rapport à l'ensemble du système (ou du groupe de processus auquel il appartient). Ce taux est appliqué par l'ordonnanceur, lorsqu'il détermine la prochaine tâche qui sera exécutée.

Ainsi, lorsque la machine n'est pas chargée, que le processeur n'a pas constamment du travail à effectuer, l'ordonnanceur ne va pas empêcher une tâche très consommatrice en puissance de calcul de s'exécuter.

Par contre, sous une forte charge, si l'on défini que notre conteneur exécutant un cpuburn ne peut pas utiliser plus de 50% des ressources de la machine, ce pourcentage ne pourra effectivement pas être dépassé, l'ordonnanceur privilégiant alors les autres processus du système.

Par défaut, le taux maximal (1024 = 100%) d'utilisation CPU est donné aux nouveaux conteneurs, on peut le réduire en utilisant l'option -c/--cpu-shares : 512 = 50%, par exemple.

Sécuriser l'exécution

En plus des dénis de service, on peut également vouloir se protéger contre des attaques provenant des conteneurs eux-mêmes. On n'est pas à l'abri d'une vulnérabilité dans un des services exécuté dans un conteneur. Plusieurs mécanismes sont mis en place pour accroître la difficulté du rebond.

Capabilities

Un certain nombre de capabilities Linux sont retirées par Docker au moment de l'exécution du conteneur, on peut utiliser les options --cap-add et --cap-drop pour respectivement ajouter et retirer une capabilities.

Notez que l'option --privileged ne retire aucune capabilities à l'exécution.

Nous verrons dans un prochain cours exactement ce que permettent ces capabilities.

seccomp

Si les capabilities sont un regroupement grossiers de fonctionnalités du noyau, seccomp est un filtre que l'on peut définir pour chaque appel système. Liste blanche, liste noire, tout est possible.

Docker filtre notamment tous les appels systèmes qui pourraient débordés à l'extérieur du conteneur : il n'est par exemple pas possible de changer l'heure dans un conteneur, car il n'y a aujourd'hui aucun mécanisme pour isoler les visions des dates d'un conteneur à l'autre.

Voici par exemple un fichier de profil seccomp, interdisant l'utilisation de l'appel système nanosleep(2) (utilisé notamment par sleep(1)) :

```js { "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "names": [ "nanosleep" ], "action": "SCMP_ACT_ERRNO", "args": [], "comment": "", "includes": {}, "excludes": {} } ] } ```

On peut ensuite l'appliquer à un conteneur Docker :

``` 42sh$ docker container run -it --security-opt seccomp=nanosleep.json ubuntu /bin/bash (cntnr)$ sleep 42 sleep: cannot read realtime clock: Operation not permitted ```