Ajuste do kernel com contêiner de Docker privilegiado

10

Estou construindo um contêiner para ajustar as configurações do kernel para um balanceador de carga. Eu preferiria implantar essas alterações no host em uma imagem usando um único contêiner privilegiado. Por exemplo:

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

No teste, as alterações entram em vigor, mas apenas para esse contêiner. Fiquei com a impressão de que, com um contêiner totalmente privilegiado, as alterações em / proc realmente alterariam o SO subjacente.

$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

É assim que os recipientes privilegiados devem funcionar?

Estou apenas fazendo algo bobo?

Qual é a melhor maneira de fazer mudanças duradouras?

Informação da versão:

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

Exemplo de comando com / proc montado:

$ 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
fonte
Preciso fazer algo bobo como mount / proc como um volume?
allingeek
Tentei montar / proc: / proc sem sorte. Chamadas subsequentes para sysctl -a retornam os valores originais.
31515 allingeek
Parece que agora funciona no Docker 18.09
Jairo Andres Velasco Romero

Respostas:

8

Essa configuração específica está sob a influência do namespace de rede em que o docker é executado.

Como regra geral /proc, as configurações são relevantes para todo o sistema; tecnicamente, porém, você está alterando as configurações nas /proc/netquais retorna resultados com base no namespace da rede.

Observe que, /proc/netna verdade, é um link simbólico /proc/self/net, pois realmente reflete as configurações do espaço para nome em que você está realizando o trabalho.

Matthew Ife
fonte
Portanto, se eu fizer essas alterações em um contêiner com o / proc montado e o host --net, posso fazer alterações no host. Mas se eu entender sua resposta, os contêineres subseqüentes manterão os valores antigos (inicializados nas configurações persistentes do host) em seu próprio espaço para nome. Eu precisaria executar esse contêiner com algo como CAP_NET_ADMIN para fazer as mesmas alterações em tempo de execução no contêiner do balanceador de carga. Soa certo?
allingeek
Sim, a execução com CAP_NET_ADMIN não deve representar um problema em que você instancia um espaço para nome para ele.
Matthew Ife
Matthew_Ife Neste caso, não é um problema que se espera que o contêiner seja privilegiado. Parece-me que CAP_NET_ADMIN poderia permitir escapar da confination janela de encaixe (pelo menos o recipiente pode reconfigurar sua interface para representar outro recipiente)
Ángel
@ Angel Isso dependeria de qual link out está configurado dentro da janela de encaixe. Geralmente, deve-se colocar a imposição de tráfego no namespace pai. Não seria possível alternar namespaces para outro lugar, pois você precisa de CAP_SYS_ADMIN para isso.
Matthew Ife
SO usando --net = host funcionará?
Jairo Andres Velasco Romero
7

O Docker 1.12+ tem suporte nativo para ajustar valores sysctl dentro dos contêineres. Aqui está um trecho da documentação :

Configurar parâmetros do kernel no espaço de nomes (sysctls) em tempo de execução

O --sysctl define parâmetros do kernel com espaçamento de nomes (sysctls) no contêiner. Por exemplo, para ativar o encaminhamento de IP no espaço para nome da rede de contêineres, execute este comando:

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

Usando seu exemplo, a maneira correta de aumentar net.core.somaxconnseria:

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

O contêiner privilegiado ainda está usando seu próprio espaço para nome de processo /proc. O que você pode fazer é montar o real /procdentro do contêiner:

docker run --rm --privileged -v /proc:/host-proc ubuntu:latest \
  'echo 65535 > /host-proc/sys/net/core/somaxconn'
Anjo
fonte
Apenas tentei isso e não funciona.
31515 allingeek
Pelo pouco que sei sobre estivador; é suposto ser uma instância independente, como uma prisão no FreeBSD, para que possa ser facilmente movida, reimplantada, etc ... Você não deve misturar o docklet com o sistema operacional host.
DutchUncle
2
Existem vários casos válidos para o uso de contêineres --privileged e este parece ser o caso perfeito. Todos os contêineres usam o mesmo kernel subjacente. Os contêineres padrão são montados / proc como somente leitura.
allingeek
@allingeek CAP_NET_ADMIN pode realmente ser o bit que falta.
Ángel
1
Tentei com o NET_ADMIN e ainda não 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 01/04/2015
2

Isso funciona para mim com o Docker 1.5.0:

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