docker 容器中的 tcp_keepalive_time

kwe*_*wek 9 docker docker-swarm

我有一个将net.ipv4.tcp_keepalive_time内核参数设置为 600的 docker 主机。但是当容器运行时,它使用不同的值:

$ sysctl net.ipv4.tcp_keepalive_time
net.ipv4.tcp_keepalive_time = 600

$ docker run --rm ubuntu:latest sysctl net.ipv4.tcp_keepalive_time
net.ipv4.tcp_keepalive_time = 7200
Run Code Online (Sandbox Code Playgroud)

这是为什么,我该如何更改此值而不必传递--sysctl选项?

--sysctl在我的情况下,我无法通过的原因是该主机是一个 docker swarm 容器,目前swarm不支持此选项。

但是容器不应该只从主机获取这些内核参数吗?我已经重新启动了 docker 服务(及其容器)。

编辑:一些额外的主机信息:

$ uname -r
4.15.0-38-generic
$ docker --version
Docker version 18.06.1-ce, build e68fc7a
Run Code Online (Sandbox Code Playgroud)

Dan*_*ver 16

这就是网络命名空间(Docker 使用的 Linux 工具)的工作方式。

但是容器不应该只从主机获取这些内核参数吗?

不。当创建网络命名空间时(在您的情况下 - 当 Docker 容器启动时),它不会从初始(您的术语中的“主机”)网络命名空间继承大部分网络内核参数,相反,这些参数是设置为默认值,其被用于在编译时内核中定义

此外,更改特定网络命名空间(包括初始名称)中特定网络参数的值不会更改其他网络命名空间中的此参数,因此,更改“主机”net.ipv4.tcp_keepalive_time参数的值不会影响任何容器(已经运行或随后推出)。

如何更改此值而不必传递 --sysctl 选项?

考虑到上面的解释,从内核的默认值更改容器的此内核参数的唯一方法是从容器的网络名称空间修改此参数。这--sysctl就是提供选项时 Docker 在容器启动期间所做的事情。

如果 Swarm 不支持使用此选项启动容器,恐怕您唯一的方法就是从容器的入口点修改此参数,除非您将容器作为--privileged. 显然,这是一个错误的决定,因为它本质上是一个安全漏洞,允许容器以多种方式影响主机系统。

  • 另一种解决方法可能是(在 swarm 外部手动)在 swarm 容器网络命名空间中运行特权容器,并使用它来调整 sysctls: `$ docker run --rm --privileged --network container:<CONTAINER ID> alpine sysctl net.ipv4.tcp_keepalive_time = 600`不太漂亮,但限制了对特权容器的暴露 (2认同)