Ajuste de kernel con contenedor Docker privilegiado


10

Estoy construyendo un contenedor para ajustar la configuración del kernel para un equilibrador de carga. Prefiero implementar esos cambios en el host en una imagen usando un solo contenedor privilegiado. Por ejemplo:

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

En la prueba, los cambios surten efecto pero solo para ese contenedor. Tenía la impresión de que con un contenedor totalmente privilegiado, los cambios en / proc cambiarían el SO subyacente.

$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

¿Es así como se supone que funcionan los contenedores privilegiados?

¿Estoy haciendo algo tonto?

¿Cuál es la mejor manera de hacer cambios duraderos?

Información de la versión:

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

Comando de ejemplo con montado / 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

¿Necesito hacer algo tonto como mount / proc como volumen?
allingeek

Intenté montar / proc: / proc sin suerte. Las llamadas posteriores a sysctl -a devuelven los valores originales.
allingeek

Parece que ahora funciona en Docker 18.09
Jairo Andres Velasco Romero

Respuestas:


8

Esta configuración particular cae bajo la influencia del espacio de nombres de red en el que se ejecuta Docker.

Como regla general /proc, altera la configuración que es relevante en todo el sistema, técnicamente hablando, sin embargo, está alterando la configuración en la /proc/netque se obtienen resultados en función del espacio de nombres por red.

Tenga en cuenta que en /proc/netrealidad es un enlace simbólico, /proc/self/netya que realmente refleja la configuración del espacio de nombres en el que está haciendo el trabajo.


Entonces, si hago estos cambios en un contenedor con / proc montado y --net host, puedo hacer cambios en el host. Pero si entiendo su respuesta, los contenedores posteriores mantendrán los valores antiguos (arrancados de la configuración persistente del host) en su propio espacio de nombres. Necesitaría ejecutar ese contenedor con algo como CAP_NET_ADMIN para hacer los mismos cambios en tiempo de ejecución en el contenedor del equilibrador de carga. ¿Suena bien?
allingeek

Sí, ejecutar con CAP_NET_ADMIN no debería plantear un problema en el que haya instanciado un espacio de nombres para él.
Matthew Ife

Matthew_Ife No es un problema en este caso que se espere que el contenedor tenga privilegios. Me parece que CAP_NET_ADMIN podría permitir escapar del confinamiento de la ventana acoplable (al menos el contenedor podría reconfigurar su interfaz para hacerse pasar por otro contenedor)
Ángel

@Angel Eso dependería de qué enlace esté configurado dentro de la ventana acoplable. Sin embargo, en general, se debe poner la aplicación del tráfico en el espacio de nombres principal. No sería posible cambiar los espacios de nombres a otro lugar ya que necesita CAP_SYS_ADMIN para eso.
Matthew Ife

¿SO usando --net = host funcionará?
Jairo Andres Velasco Romero

7

Docker 1.12+ tiene soporte nativo para ajustar los valores de sysctl dentro de los contenedores. Aquí hay un extracto de la documentación :

Configurar parámetros de kernel con espacio de nombres (sysctls) en tiempo de ejecución

--Sysctl establece los parámetros del núcleo con espacio de nombres (sysctls) en el contenedor. Por ejemplo, para activar el reenvío de IP en el espacio de nombres de la red de contenedores, ejecute este comando:

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

Usando su ejemplo, la forma correcta de subir net.core.somaxconnsería:

docker run ... --sysctl net.core.somaxconn=65535 ...

3

El contenedor privilegiado todavía está utilizando su propio espacio de nombres de proceso /proc. Lo que puedes hacer es montar lo real /procdentro del contenedor:

docker run --rm --privileged -v /proc:/host-proc ubuntu:latest \
  'echo 65535 > /host-proc/sys/net/core/somaxconn'

Acabo de probar esto y no funciona.
allingeek

Por lo poco que sé sobre docker; se supone que es una instancia autónoma, como una cárcel en FreeBSD, por lo que se puede mover fácilmente, volver a implementar, etc. No debe mezclar el docklet con el sistema operativo host.
DutchUncle

2
Hay varios casos válidos para usar contenedores privilegiados y este parece ser el caso perfecto. Todos los contenedores usan el mismo núcleo subyacente. Los contenedores estándar se montan / procesan como de solo lectura.
allingeek

@allingeek CAP_NET_ADMIN puede ser el bit faltante.
Ángel

1
Intenté con NET_ADMIN y todavía no funciona - 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

Esto funciona para mí con Docker 1.5.0:

docker run --privileged --net=host --rm ubuntu:latest /bin/sh -c \
   'echo 65535 > /proc/sys/net/core/somaxconn'   
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.