docker_sysctl

Sysctl 用于配置运行时的内核参数,正常情况下修改 /etc/sysctl.conf . 然后执行 sysctl -p 就能够设置成功。

当使用 Docker 启动服务时,使用 sysctl -p 来配置 docker 的参数时会出现问题。比如

1
2
3
sysctl: cannot stat /proc/sys/net/core/rmem_max: No such file or directory
sysctl: cannot stat /proc/sys/net/core/wmem_max: No such file or directory

由于是配置的内核参数,如果容器修改了内核的参数,还是需要宿主机支持才行,直接修改是不支持的。 Docker的base image做的很精简,甚至都没有init进程,原本在OS启动时执行生效系统变量的过程(sysctl -p)也给省略了,导致这些系统变量依旧保留着kernel默认值。

在 Docker 中对 sysctl 做了一些支持。 但是也只是有限的支持。在 Docker 启动容器时,指定 –sysctl 参数可以设置 sysctl 的参数 。 在 docker-compose.yml 文件中也提供了 sysctls 的参数 。

1
2
3
4
sysctls:
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0

但是,Docker 中 sysctl 的可调参数要比宿主机少得多。

  1. 未被 docker 限制的参数Docker通过一个 ValidateSysctl函数来限制 sysctl参数可以传入的项。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // docker/opts/opts.go
    func ValidateSysctl(val string) (string, error) {
    validSysctlMap := map[string]bool{
    "kernel.msgmax": true,
    "kernel.msgmnb": true,
    "kernel.msgmni": true,
    "kernel.sem": true,
    "kernel.shmall": true,
    "kernel.shmmax": true,
    "kernel.shmmni": true,
    "kernel.shm_rmid_forced": true,
    }
    validSysctlPrefixes := []string{
    "net.",
    "fs.mqueue.",
    }

  2. 容器中可以看见该配置项可以使用 sysctl -a 看到

  3. 配置项可以 namespace 化配置项无法 namespace化,指的是该配置项是全局的,无法为每个 namespace生成独立的配置。一般来说,宿主机和容器是一对多的关系,一个无法 namespace化的配置项,调整之后会影响所有其他容器以及宿主机本身,这是我们无法接受的。

以上内容参考https://segmentfault.com/a/1190000009225126

  1. 在设置 socket 的一些网络参数时 。对内核参数进行修改
1
2
3
4
5
6
7
8
9
10
net.core.wmem_max=12582912
net.core.rmem_max=12582912
net.ipv4.tcp_rmem= 10240 87380 12582912
net.ipv4.tcp_wmem= 10240 87380 12582912
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_no_metrics_save = 1
net.core.netdev_max_backlog = 5000

直接修改 docker 的 sysctl 是不能成功的。 在 docker-compose 中可以通过使用 network_mode: “host” ,修改宿主机的参数来实现。 缺点时集群模式无法使用,并且容器和宿主机共享网络空间,无法做到隔离。

  1. 使用 –privileged默认情况下 docker 容器是无特权的。容器不允许访问任何的设备。授予 –privileged 后,Docker 启动对宿主机的所有设备的访问。以允许容器对主机的访问几乎与在主机上容器外部运行的进程相同。
作者

张巍

发布于

2019-12-12

更新于

2019-12-12

许可协议

评论