【问题标题】:Refresh net.core.somaxcomm (or any sysctl property) for docker containers刷新 docker 容器的 net.core.somaxcomm(或任何 sysctl 属性)
【发布时间】:2014-11-28 09:36:49
【问题描述】:

我正在尝试更改 net.core.somaxconn 以使 docker 容器能够为我的 Web 应用程序提供更大的请求队列。

在OS上,在docker之外,我先修改属性成功:

$ cat /proc/sys/net/core/somaxconn
128
$ sudo sysctl -w net.core.somaxconn=1024
net.core.somaxconn = 1024
$ cat /proc/sys/net/core/somaxconn
1024

但是我不知道如何将该更改传播到 docker。我试过了:

  • 同时编辑 /etc/sysctl.conf(希望 docker 在容器启动时读取该文件)
  • 再次重启容器sudo docker stopsudo docker run
  • sudo service docker restart 重启整个 docker 服务

但在容器内,cat /proc/sys/net/core/somaxconn 总是显示128

我正在运行 docker 1.2(因此默认情况下,我无法修改容器内的 /proc 属性)和 Elastic Beanstalk(因此没有--privileged 模式,这将允许我修改/proc)。

如何将 sysctl 更改传播到 docker?

【问题讨论】:

    标签: linux docker amazon-elastic-beanstalk sysctl


    【解决方案1】:

    “网络/核心”子系统是registered per network namespace。 somaxconn 的初始值设置为 128。

    当您在主机系统上执行 sysctl 时,它会为 网络命名空间设置核心参数,该命名空间属于 init。 (基本上这是默认命名空间)。这不会影响其他网络命名空间。

    当一个 Docker 容器启动时,该容器的虚拟网络接口(在主机上显示为 vethXXXis attached to its own namespace,它的初始 somaxconn 值仍然是 128。所以从技术上讲,你不能传播这个值到容器中,因为两个网络命名空间不共享它。

    但是,除了以特权模式运行容器之外,还有两种方法可以调整此值。

    1. 在运行容器时使用“--net host”,因此它使用主机的网络接口,因此共享相同的网络命名空间。

    2. 您可以使用 Docker 的卷映射支持将 proc 文件系统挂载为读写。诀窍是将它映射到一个未命名为“/proc”的卷,因为 Docker 将remount /proc/sys, among others, as read-only for non-privileged containers。这需要主机将 /proc 挂载为 rw,这是大多数系统的情况。

      docker run -it --rm -v /proc:/writable-proc ubuntu:14.04 /bin/bash
      root@edbee3de0761:/# echo 1024 > /writable-proc/sys/net/core/somaxconn
      root@edbee3de0761:/# sysctl net.core.somaxconn
      net.core.somaxconn = 1024
      

    方法 2 应该可以通过 Dockerrun.aws.json 中的卷映射支持在 Elastic Beanstalk 上运行。它还应该适用于每个命名空间的 /proc 下的其他可调参数。但这很可能是 Docker 的疏忽,所以他们可能会在卷映射上添加额外的验证,然后这个技巧就行不通了。

    【讨论】:

    • 这是一个非常聪明的答案,你真的很了解 docker :) 听起来没有必要与之抗争——如果故意使 /proc 仅在特权模式下可写,我想这是面向未来的解决方案是要求 AWS 工程师在 EB 中启用/允许它。由于底层 EC2 机器已经由我们“拥有”,因此没有任何理由禁止特权模式......在此之前,我明天会尝试您的解决方法并报告!
    • 好吧,正如您所建议的,第二种解决方法在 EB 上运行良好,所以我们现在将坚持使用它。我不确定我是否完全理解如何从容器内部修改/proc(通过/writable-proc)实际上会修改容器的命名空间,而不是从它安装的父操作系统接口的命名空间,但你已经为我节省了很多小时,非常感谢。我还在 Beanstalk 论坛上打开了一个关于使用特权模式的问题 forums.aws.amazon.com/thread.jspa?threadID=162290
    • 据报道此技巧不再有效:serverfault.com/a/664589/60525
    • 为什么这会起作用?之后,有两个 proc 挂载,只读在 /proc 和可写在 /writable-proc(或其他)。为什么仅仅挂载默认命名空间的 /proc 会覆盖容器 /proc/ 中值的使用?
    【解决方案2】:

    docker 1.12 添加了对使用 --sysctl 设置 sysctls 的支持。

    docker run --name some-redis --sysctl=net.core.somaxconn=511 -d redis
    

    文档:https://docs.docker.com/engine/reference/commandline/run/#/configure-namespaced-kernel-parameters-sysctls-at-runtime

    【讨论】:

      【解决方案3】:

      我找到了解决办法:

      {
          "AWSEBDockerrunVersion": "1",
          "Command": "run COMMAND",
          "Image": {
              "Name": "crystalnix/omaha-server",
              "Update": "true"
          },
          "Ports": [
              {
                  "ContainerPort": "80"
              }
          ]
      }
      

      更多细节在这里:/opt/elasticbeanstalk/hooks/appdeploy/pre/04run.sh

      更新:

      添加文件.ebextensions/02-commands.config

      container_commands:
          00001-docker-privileged:
              command: 'sed -i "s/docker run -d/docker run --privileged -d/" /opt/elasticbeanstalk/hooks/appdeploy/pre/04run.sh'
      

      【讨论】:

      • 所以您发现了一个未记录的Command 功能?那很好!我将很快对其进行测试(ish)并报告它对我的工作方式。
      • 问题是 04run.sh 不可信。有什么方法可以将正在运行的 docker 更改为 privileged 模式。
      • 路径已更改:sed -i "s/docker run -d/docker run --privileged -d/" /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh
      【解决方案4】:

      更新:此答案已过时,因为 Docker 现在支持 docker run --sysctl 选项!

      我用于我的 OpenVPN 容器的解决方案是使用 nsenter 进入具有完整功能的容器命名空间,临时重新安装 /proc/sys 读写,设置内容并再次以只读方式重新安装。

      这里是一个例子,在容器中启用 IPv6 转发:

      CONTAINER_NAME=openvpn
      
      # enable ipv6 forwarding via nsenter
      container_pid=`docker inspect -f '{{.State.Pid}}' $CONTAINER_NAME`
      nsenter --target $container_pid --mount --uts --ipc --net --pid \
         /bin/sh -c '/usr/bin/mount /proc/sys -o remount,rw;
                     /usr/sbin/sysctl -q net.ipv6.conf.all.forwarding=1;
                     /usr/bin/mount /proc/sys -o remount,ro;
                     /usr/bin/mount /proc -o remount,rw # restore rw on /proc'
      

      这样容器就不需要特权运行了。

      【讨论】:

      • 这真是太棒了。非常感谢分享!
      • 这个解决方案是这个问题上唯一一个在最新的 Docker 中工作的环境(Amazon ECS),它不暴露来自docker run--sysctl 选项。
      【解决方案5】:

      刚刚知道如何解决这个问题,现在Elastic Beanstalk supports running a privileged containers,您只需将"privileged": "true" 添加到您的Dockerrun.aws.json,如下示例(请查看container-1):

      {
        "AWSEBDockerrunVersion": 2,
        "containerDefinitions": [{
          "name": "container-0",
          "essential": "false",
          "image": "ubuntu",
          "memory": "512"
        }, {
          "name": "container-1",
          "essential": "false",
          "image": "ubuntu",
          "memory": "512",
          "privileged": "true"
        }]
      }
      

      请注意duplicated this answer来自另一个线程。

      【讨论】:

      • 所以他们终于添加了对它的支持......知道什么时候吗?
      【解决方案6】:

      在 docker 3.1 中支持指定 sysctl。 注意
      sysctls:
      - net.core.somaxconn=1024

      我的示例 docker-compose 文件

      version: '3.1'                                                                   
      services:                                                                        
        my_redis_master:                                                             
          image: redis                                                                 
          restart: always                                                              
          command: redis-server /etc/redis/redis.conf                                  
          volumes:                                                                     
            - /data/my_dir/redis:/data                                         
            - /data/my_dir/logs/redis:/var/tmp/                                
            - ./redis/redis-master.conf:/etc/redis/redis.conf                          
          sysctls:                                                                     
            - net.core.somaxconn=1024                                                  
          ports:                                                                       
            - "18379:6379"                                   
      

      【讨论】:

      • 那么为什么我会得到“忽略不支持的选项:sysctls”?
      • 您使用的是哪个版本的 docker-compose?
      • @OrGal 您可能使用 Swarm 吗?它不支持 sysctl 和其他选项
      【解决方案7】:

      正如@nazim.sp 回答 Docker compose 将支持 sysctls, 我遇到了与@Or Gal“忽略不支持的选项:”相同的问题,但是使用不同的语法它被接受 来自 docker-compose.yaml 的示例节

      redis:
        image: redis
        container_name: redis
        sysctls: 
          net.core.somaxconn: "1024"
      

      来源:https://rollout.io/blog/adjusting-linux-kernel-parameters-with-docker-compose/

      我意识到这应该是适当答案中的评论,但是没有代表添加评论的新手,你必须跳进去并“回答”

      【讨论】:

        猜你喜欢
        • 2018-12-25
        • 2017-10-16
        • 1970-01-01
        • 1970-01-01
        • 2021-01-19
        • 2018-01-14
        • 2020-12-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多