使用特权Docker容器进行内核调整


10

我正在建立一个容器来调整负载均衡器的内核设置。我宁愿使用单个特权容器将这些更改部署到映像中的主机。例如:

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

在测试中,更改仅对那个容器生效。我的印象是,使用具有完全特权的容器时,对/ proc的更改实际上会更改底层的OS。

$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

这是特权容器应该如何工作的吗?

我只是在做傻事吗?

进行持久更改的最佳方法是什么?

版本信息:

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

安装了/ 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

我是否需要做一些愚蠢的事情,例如将mount / proc作为卷?
allingeek

尝试安装/ proc:/ proc没有运气。对sysctl -a的后续调用将返回原始值。
allingeek

现在看起来喜欢它适用于泊坞18.09
海罗安德烈斯·贝拉斯科·罗梅罗

Answers:


8

此特定设置受docker运行所在的网络名称空间的影响。

一般来说/proc,更改系统范围内的设置是一个普遍的规则,但是从技术上来讲,您正在更改设置,/proc/net以每个网络名称空间为基础返回结果。

请注意,/proc/net实际上这是一个符号链接,/proc/self/net因为它确实反映了您在其中进行工作的名称空间的设置。


因此,如果在装有/ proc且具有--net host的容器中进行此更改,则可以对主机进行更改。但是,如果我理解您的回答,那么后续容器将在其自己的名称空间中保留旧值(从主机的持久设置引导)。我需要使用类似于CAP_NET_ADMIN的容器来运行该容器,以便在运行时在负载均衡器的容器中进行相同的更改。听起来对吗?
2015年

是的,使用CAP_NET_ADMIN运行应该不会对您为其实例化名称空间造成任何问题。
马修·伊夫,2015年

Matthew_Ife在这种情况下,应该对容器进行特权设置不是问题。在我看来,那CAP_NET_ADMIN可能允许从泊坞窗confination逃逸(至少容器可以重新配置它的界面模仿另一个容器)
安赫尔

@Angel这取决于docker内部设置的链接。通常,应该将流量的强制执行放在父名称空间中。由于您需要CAP_SYS_ADMIN,因此无法将名称空间切换到其他位置。
马修·伊夫

所以使用--net = host可以工作吗?
加罗·安德烈斯·贝拉斯科·罗梅罗,

7

Docker 1.12+具有对容器内sysctl值进行调整的本地支持。以下是文档摘录:

在运行时配置命名空间的内核参数(sysctls)

--sysctl在容器中设置命名空间的内核参数(sysctls)。例如,要在容器网络名称空间中打开IP转发,请运行以下命令:

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

使用您的示例,正​​确的筹集方法net.core.somaxconn将是:

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

3

特权容器仍在使用其自己的进程名称空间/proc。您可以做的是将real /proc安装在容器中:

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

只是尝试了一下,这是行不通的。
allingeek

从我对docker的了解不多;它应该是一个独立的实例,就像FreeBSD上的监狱一样,因此可以轻松地移动,重新部署等。您不应该将Docklet与主机OS混淆。
DutchUncle 2015年

2
有几种使用--privileged容器的有效案例,这似乎是完美的案例。所有容器都使用相同的基础内核。标准容器将/ proc安装为只读。
allingeek

@allingeek CAP_NET_ADMIN确实可能是缺少的位。
安赫尔

1
尝试使用NET_ADMIN仍然无法正常工作-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 2015年

2

这适用于Docker 1.5.0:

docker run --privileged --net=host --rm ubuntu:latest /bin/sh -c \
   'echo 65535 > /proc/sys/net/core/somaxconn'   
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.