Kernel-Tuning mit privilegiertem Docker-Container

10

Ich baue einen Container, um die Kerneleinstellungen für einen Load Balancer zu optimieren. Ich würde es vorziehen, diese Änderungen mit einem einzigen privilegierten Container auf dem Host in einem Image bereitzustellen. Beispielsweise:

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

Beim Testen werden die Änderungen wirksam, jedoch nur für diesen Container. Ich hatte den Eindruck, dass mit einem vollständig privilegierten Container Änderungen an / proc tatsächlich das zugrunde liegende Betriebssystem ändern würden.

$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

Sollen privilegierte Container so funktionieren?

Mache ich nur etwas Dummes?

Was ist der beste Weg, um dauerhafte Veränderungen vorzunehmen?

Versions Information:

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

Beispielbefehl mit mount / 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
quelle
Muss ich etwas Dummes wie mount / proc als Volume machen?
Allingeek
Versuchte Montage / proc: / proc ohne Glück. Nachfolgende Aufrufe von sysctl -a geben die ursprünglichen Werte zurück.
Allingeek
Sieht so aus, als ob es jetzt auf Docker 18.09 funktioniert
Jairo Andres Velasco Romero

Antworten:

8

Diese spezielle Einstellung fällt unter den Einfluss des Netzwerk-Namespace, in dem Docker ausgeführt wird.

In der Regel /procwerden systemweit relevante Einstellungen geändert. Technisch gesehen ändern Sie jedoch Einstellungen, bei /proc/netdenen die Ergebnisse auf Netzwerk-Namespace-Basis zurückgegeben werden.

Beachten Sie, dass dies /proc/nettatsächlich ein Symlink ist, /proc/self/netda er tatsächlich die Einstellungen des Namespace widerspiegelt, in dem Sie die Arbeit ausführen.

Matthew Ife
quelle
Wenn ich diese Änderungen in einem Container mit / proc-Mounted und --net-Host vornehme, kann ich Änderungen am Host vornehmen. Wenn ich Ihre Antwort verstehe, behalten nachfolgende Container die alten Werte (Bootstrap von den persistierten Einstellungen des Hosts) in ihrem eigenen Namespace bei. Ich müsste diesen Container mit so etwas wie CAP_NET_ADMIN ausführen, um zur Laufzeit dieselben Änderungen im Container des Load Balancers vorzunehmen. Hört sich richtig an?
Allingeek
Ja, das Ausführen mit CAP_NET_ADMIN sollte kein Problem darstellen, bei dem Sie einen Namespace dafür instanziiert haben.
Matthew Ife
Matthew_Ife In diesem Fall ist es kein Problem, dass der Container voraussichtlich privilegiert ist. Es scheint mir, dass CAP_NET_ADMIN das Entkommen aus der Docker-Beschränkung ermöglichen könnte (zumindest könnte der Container seine Schnittstelle neu konfigurieren, um sich als ein anderer Container auszugeben)
Ángel
@Angel Das hängt davon ab, welcher Link-Out im Docker eingerichtet ist. Im Allgemeinen sollte die Durchsetzung des Datenverkehrs jedoch in den übergeordneten Namespace gestellt werden. Es wäre nicht möglich, Namespaces an einen anderen Ort zu verschieben, da Sie dafür CAP_SYS_ADMIN benötigen.
Matthew Ife
Also mit --net = Host funktioniert das?
Jairo Andres Velasco Romero
7

Docker 1.12+ bietet native Unterstützung für die Optimierung von Sysctl-Werten in den Containern. Hier ist ein Auszug aus der Dokumentation :

Konfigurieren Sie zur Laufzeit Kernelparameter mit Namespace (sysctls)

Das --sysctl legt Kernelparameter (sysctls) mit Namespace im Container fest. Führen Sie den folgenden Befehl aus, um beispielsweise die IP-Weiterleitung im Containernetzwerk-Namespace zu aktivieren:

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

Anhand Ihres Beispiels wäre der richtige Weg, um zu erhöhen net.core.somaxconn:

docker run ... --sysctl net.core.somaxconn=65535 ...
Hyperknoten
quelle
3

Der privilegierte Container verwendet weiterhin seinen eigenen Prozessnamespace für /proc. Was Sie tun können, ist, den Real /procim Container zu montieren :

docker run --rm --privileged -v /proc:/host-proc ubuntu:latest \
  'echo 65535 > /host-proc/sys/net/core/somaxconn'
Engel
quelle
Ich habe es gerade versucht und es funktioniert nicht.
Allingeek
Von dem kleinen, das ich über Docker weiß; Es soll eine in sich geschlossene Instanz sein, wie ein Gefängnis unter FreeBSD, damit es leicht verschoben, erneut bereitgestellt werden kann usw. Sie sollten das Docklet nicht mit dem Host-Betriebssystem verwechseln.
DutchUncle
2
Es gibt mehrere gültige Fälle für die Verwendung von --privilegierten Containern, und dies scheint der perfekte Fall zu sein. Alle Container verwenden denselben zugrunde liegenden Kernel. Standardcontainer werden als schreibgeschützt bereitgestellt.
Allingeek
@allingeek CAP_NET_ADMIN kann tatsächlich das fehlende Bit sein.
Ángel
1
Versucht mit NET_ADMIN und es funktioniert immer noch nicht - Docker ausführen --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

Dies funktioniert bei mir mit Docker 1.5.0:

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