Optimisation du noyau avec un conteneur Docker privilégié

10

Je construis un conteneur pour régler les paramètres du noyau pour un équilibreur de charge. Je préfère déployer ces modifications sur l'hôte dans une image à l'aide d'un seul conteneur privilégié. Par exemple:

docker run --rm --privileged ubuntu:latest sysctl -w net.core.somaxconn=65535

Lors des tests, les modifications prennent effet, mais uniquement pour ce conteneur. J'avais l'impression qu'avec un conteneur entièrement privilégié, les modifications apportées à / proc changeraient réellement le système d'exploitation sous-jacent.

$docker run --rm --privileged ubuntu:latest \
    sysctl -w net.core.somaxconn=65535
net.core.somaxconn = 65535

$ docker run --rm --privileged ubuntu:latest \
    /bin/bash -c "sysctl -a | grep somaxconn"
net.core.somaxconn = 128

Est-ce ainsi que les conteneurs privilégiés sont censés fonctionner?

Suis-je en train de faire quelque chose de stupide?

Quelle est la meilleure façon d'apporter des changements durables?

Informations sur la version:

Client version: 1.4.1
Client API version: 1.16
Go version (client): go1.3.3
Git commit (client): 5bc2ff8
OS/Arch (client): linux/amd64
Server version: 1.4.1
Server API version: 1.16
Go version (server): go1.3.3
Git commit (server): 5bc2ff8

Exemple de commande avec monté / proc:

$ docker run -v /proc:/proc ubuntu:latest \
    /bin/bash -c "sysctl -a | grep local_port"
net.ipv4.ip_local_port_range = 32768    61000

$ docker run -v /proc:/proc --privileged ubuntu:latest \
    /bin/bash -c "sysctl -p /updates/sysctl.conf"
net.ipv4.ip_local_port_range = 2000 65000

$ docker run -v /proc:/proc ubuntu:latest \
    /bin/bash -c "sysctl -a | grep local_port"
net.ipv4.ip_local_port_range = 32768    61000

$ docker run -v /proc:/proc --privileged ubuntu:latest \
    /bin/bash -c "sysctl -a | grep local_port"
net.ipv4.ip_local_port_range = 32768    61000
allingeek
la source
Dois-je faire quelque chose de stupide comme mount / proc comme volume?
allingeek
Montage essayé / proc: / proc sans chance. Les appels suivants à sysctl -a renvoient les valeurs d'origine.
allingeek
Il semble que maintenant cela fonctionne sur Docker 18.09
Jairo Andres Velasco Romero

Réponses:

8

Ce paramètre particulier tombe sous l'influence de l'espace de noms réseau dans lequel le docker s'exécute.

En règle générale, /procles paramètres qui sont pertinents à l'échelle du système sont modifiés, mais techniquement, vous modifiez les paramètres dans /proc/netlesquels les résultats sont renvoyés par espace de noms réseau.

Notez qu'il /proc/nets'agit en fait d'un lien symbolique vers /proc/self/netcar il reflète vraiment les paramètres de l'espace de noms dans lequel vous effectuez le travail.

Matthew Ife
la source
Donc, si j'effectue ces modifications dans un conteneur avec / proc monté et --net host, je peux apporter des modifications à l'hôte. Mais si je comprends votre réponse, les conteneurs suivants conserveront les anciennes valeurs (amorcées à partir des paramètres persistants de l'hôte) dans son propre espace de noms. J'aurais besoin d'exécuter ce conteneur avec quelque chose comme CAP_NET_ADMIN pour apporter les mêmes modifications à l'exécution dans le conteneur de l'équilibreur de charge. Ça sonne bien?
allingeek
Oui, l'exécution avec CAP_NET_ADMIN ne devrait pas poser de problème lorsque vous lui avez instancié un espace de noms.
Matthew Ife
Matthew_Ife Pas un problème dans ce cas où le conteneur devrait être privilégié. Il me semble que CAP_NET_ADMIN pourrait permettre d'échapper à la confinement du docker (au moins le conteneur pourrait reconfigurer son interface pour se faire passer pour un autre conteneur)
Ángel
@Angel Cela dépendrait du lien de sortie configuré dans Docker. En règle générale, il convient de mettre l'application du trafic dans l'espace de noms parent. Il ne serait pas possible de basculer les espaces de noms ailleurs car vous avez besoin de CAP_SYS_ADMIN pour cela.
Matthew Ife
Donc, utiliser --net = host fonctionnera?
Jairo Andres Velasco Romero
7

Docker 1.12+ a un support natif pour modifier les valeurs sysctl à l'intérieur des conteneurs. Voici un extrait de la documentation :

Configurer les paramètres du noyau à espace de noms (sysctls) lors de l'exécution

--Sysctl définit les paramètres du noyau à espace de noms (sysctls) dans le conteneur. Par exemple, pour activer le transfert IP dans l'espace de noms du réseau de conteneurs, exécutez cette commande:

docker run --sysctl net.ipv4.ip_forward=1 someimage

En utilisant votre exemple, la bonne façon de relancer net.core.somaxconnserait:

docker run ... --sysctl net.core.somaxconn=65535 ...
hyperknot
la source
3

Le conteneur privilégié utilise toujours son propre espace de noms de processus pour /proc. Ce que vous pouvez faire est de monter le réel /procà l'intérieur du conteneur:

docker run --rm --privileged -v /proc:/host-proc ubuntu:latest \
  'echo 65535 > /host-proc/sys/net/core/somaxconn'
Ange
la source
Je viens de l'essayer et cela ne fonctionne pas.
allingeek
Du peu que je connais de docker; il est censé être une instance autonome, comme une prison sur FreeBSD, donc il peut être facilement déplacé, redéployé, etc ... Vous ne devez pas mélanger le docklet avec le système d'exploitation hôte.
DutchUncle
2
Il existe plusieurs cas valides pour utiliser des conteneurs privilégiés et cela semble être le cas parfait. Tous les conteneurs utilisent le même noyau sous-jacent. Les conteneurs standard montent / proc en lecture seule.
allingeek
@allingeek CAP_NET_ADMIN peut en effet être le bit manquant.
Ángel
1
Testé avec NET_ADMIN et cela ne fonctionne toujours pas - docker run --cap-add NET_ADMIN --net = host -v / proc: / proc_host ubuntu: 14.04 bash -c 'echo 1> / proc_host / sys / net / ipv4 / ip_forward '&& sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 0
tomdee
2

Cela fonctionne pour moi avec Docker 1.5.0:

docker run --privileged --net=host --rm ubuntu:latest /bin/sh -c \
   'echo 65535 > /proc/sys/net/core/somaxconn'   
Charles Offenbacher
la source