当前位置: 首页 > 知识库问答 >
问题:

Docker守护进程/容器实时调度与Ubuntu(Linux)主机

益兴生
2023-03-14

在我开始之前,对于这个问题应该在SuperUser还是Stackoverflow中提出,我有两个想法——如果它位于错误的位置,请提前道歉。

我有一个docker容器(包含C/C可执行代码),它执行音频/视频处理。因此,我想测试使用RT调度约束运行容器的好处。在网上搜索时,我遇到了各种各样的信息,但我很难把所有的信息拼凑在一起。

系统环境:

  • 主机: Ubuntu(股票)Zity 17.04(无RT内核补丁,内核: 4.10.0-35-genric)
  • Docker版本: 17.05.0-ce
  • Docker图像操作系统:Ubuntu的17.04。

在docker映像/容器中嵌套的可执行文件中,执行以下代码以将调度程序从“SCHED_OTHER”更改为“SCHED_FIFO”(参见文档):

    struct sched_param sched = {};

    const int nMin = sched_get_priority_min(SCHED_FIFO);
    const int nMax = sched_get_priority_max(SCHED_FIFO);

    const int nHlf = (nMax - nMin) / 2;
    const int nPriority = nMin + nHlf + 1;

    sched.sched_priority = boost::algorithm::clamp(nPriority, nMin, nMax);

    if (sched_setscheduler(0, SCHED_FIFO, &sched) < 0)
        std::cerr << "SETSCHEDULER failed - err = " << strerror(errno) << std::endl;
    else
        std::cout << "Priority set to \"" << sched.sched_priority << "\"" << std::endl;

我一直在阅读使用实时调度器的Docker留档。有一页很有意思,

通过运行zcat/proc/CONFIG,验证Linux内核中是否启用了CONFIG\u RT\u GROUP\u SCHED。gz| grep CONFIG_RT_GROUP_SCHED或检查文件/sys/fs/cgroup/cpu是否存在。我们。有关配置内核实时调度器的指导,请参阅操作系统的文档。

根据前面提到的建议,股票Ubuntu的17.04操作系统似乎没有通过这些检查。

第一个问题:我不能使用RT调度程序吗?什么是CONFIG_RT_GROUP_SCHED?让我困惑的一件事是,从2010年到2012年,网上有一些关于用RT补丁修补内核的旧帖子。似乎从那时起,Linux内核中就有了一些与软RT相关的工作。

这里的引语引发了我的疑问:

然而,从内核版本2.6.18开始,Linux逐渐配备了实时功能,其中大部分来自Ingo Molnar、Thomas Gleixner、Steven Rostedt和其他人开发的前实时抢占补丁。在补丁完全合并到主线内核之前(预计将在内核版本2.6.30左右),必须安装它们以实现最佳实时性能。这些补丁被命名为:

进行着...

阅读了其他信息后,我注意到设置ulimit非常重要。我更改了/etc/安全性/限制。形态:

#*               soft    core            0
#root            hard    core            100000
#*               hard    rss             10000

# NEW ADDITION
gavin            hard    rtprio          99

第二个问题:大概需要上述内容才能使docker守护进程运行RT?看起来守护进程是通过systemd控制的。

我继续调查,在同一Docker docs页面上看到了以下片段:

要使用realtime scheduler运行容器,请运行Docker守护程序,并将--cpu rt runtime标志设置为每个运行期为实时任务保留的最大微秒数。例如,在默认周期为10000微秒(1秒)的情况下,设置--cpu rt runtime=95000可确保使用实时调度器的容器每10000微秒可以运行95000微秒,从而为非实时任务留出至少5000微秒的可用时间。要使此配置在使用systemd的系统上永久化,请参阅使用systemd控制和配置Docker。

在本页之后,我发现守护进程有两个感兴趣的参数:

  --cpu-rt-period int                     Limit the CPU real-time period in microseconds
  --cpu-rt-runtime int                    Limit the CPU real-time runtime in microseconds

同一页表明可以通过“/etc/docker/daemon”指定docker守护进程参数。所以我试着:

{
    "cpu-rt-period": 92500,
    "cpu-rt-runtime": 100000
}

注意:文档未将上述选项指定为“Linux上允许的配置选项”。尽管如此,我还是想尝试一下。

重新启动时Docker守护程序输出:

-- Logs begin at Wed 2017-10-04 09:58:38 BST, end at Wed 2017-10-04 10:01:32 BST. --
Oct 04 09:58:47 gavin systemd[1]: Starting Docker Application Container Engine...
Oct 04 09:58:47 gavin dockerd[1501]: time="2017-10-04T09:58:47.885882588+01:00" level=info msg="libcontainerd: new containerd process, pid: 1531"
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.053986072+01:00" level=warning msg="failed to rename /var/lib/docker/tmp for background deletion: %!s(<nil>).
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.161303803+01:00" level=info msg="[graphdriver] using prior storage driver: aufs"
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.303409053+01:00" level=info msg="Graph migration to content-addressability took 0.00 seconds"
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.304002725+01:00" level=warning msg="Your kernel does not support swap memory limit"
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.304078792+01:00" level=warning msg="Your kernel does not support cgroup rt period"
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.304201239+01:00" level=warning msg="Your kernel does not support cgroup rt runtime"
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.305534113+01:00" level=info msg="Loading containers: start."
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.730193030+01:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemo
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.784938130+01:00" level=info msg="Loading containers: done."
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.888035017+01:00" level=info msg="Daemon has completed initialization"
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.888104120+01:00" level=info msg="Docker daemon" commit=89658be graphdriver=aufs version=17.05.0-ce
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.903280645+01:00" level=info msg="API listen on /var/run/docker.sock"
Oct 04 09:58:48 gavin systemd[1]: Started Docker Application Container Engine.

特定的兴趣线:

Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.304078792+01:00" level=warning msg="Your kernel does not support cgroup rt period"
Oct 04 09:58:48 gavin dockerd[1501]: time="2017-10-04T09:58:48.304201239+01:00" level=warning msg="Your kernel does not support cgroup rt runtime"

考虑到我以前的发现,这并不奇怪。

最后一个问题:当这最终起作用时,我将如何确定我的容器是否真正使用RT调度运行?像“顶级”这样的东西够了吗?

编辑:我运行了一个内核诊断脚本,它是我在github上通过moby找到的。这是输出:

warning: /proc/config.gz does not exist, searching other paths for kernel config ...
info: reading kernel config from /boot/config-4.10.0-35-generic ...

Generally Necessary:
- cgroup hierarchy: properly mounted [/sys/fs/cgroup]
- apparmor: enabled and tools installed
- CONFIG_NAMESPACES: enabled
- CONFIG_NET_NS: enabled
- CONFIG_PID_NS: enabled
- CONFIG_IPC_NS: enabled
- CONFIG_UTS_NS: enabled
- CONFIG_CGROUPS: enabled
- CONFIG_CGROUP_html" target="_blank">CPUACCT: enabled
- CONFIG_CGROUP_DEVICE: enabled
- CONFIG_CGROUP_FREEZER: enabled
- CONFIG_CGROUP_SCHED: enabled
- CONFIG_CPUSETS: enabled
- CONFIG_MEMCG: enabled
- CONFIG_KEYS: enabled
- CONFIG_VETH: enabled (as module)
- CONFIG_BRIDGE: enabled (as module)
- CONFIG_BRIDGE_NETFILTER: enabled (as module)
- CONFIG_NF_NAT_IPV4: enabled (as module)
- CONFIG_IP_NF_FILTER: enabled (as module)
- CONFIG_IP_NF_TARGET_MASQUERADE: enabled (as module)
- CONFIG_NETFILTER_XT_MATCH_ADDRTYPE: enabled (as module)
- CONFIG_NETFILTER_XT_MATCH_CONNTRACK: enabled (as module)
- CONFIG_NETFILTER_XT_MATCH_IPVS: enabled (as module)
- CONFIG_IP_NF_NAT: enabled (as module)
- CONFIG_NF_NAT: enabled (as module)
- CONFIG_NF_NAT_NEEDED: enabled
- CONFIG_POSIX_MQUEUE: enabled

Optional Features:
- CONFIG_USER_NS: enabled
- CONFIG_SECCOMP: enabled
- CONFIG_CGROUP_PIDS: enabled
- CONFIG_MEMCG_SWAP: enabled
- CONFIG_MEMCG_SWAP_ENABLED: missing
    (cgroup swap accounting is currently not enabled, you can enable it by setting boot option "swapaccount=1")
- CONFIG_LEGACY_VSYSCALL_EMULATE: enabled
- CONFIG_BLK_CGROUP: enabled
- CONFIG_BLK_DEV_THROTTLING: enabled
- CONFIG_IOSCHED_CFQ: enabled
- CONFIG_CFQ_GROUP_IOSCHED: enabled
- CONFIG_CGROUP_PERF: enabled
- CONFIG_CGROUP_HUGETLB: enabled
- CONFIG_NET_CLS_CGROUP: enabled (as module)
- CONFIG_CGROUP_NET_PRIO: enabled
- CONFIG_CFS_BANDWIDTH: enabled
- CONFIG_FAIR_GROUP_SCHED: enabled
- CONFIG_RT_GROUP_SCHED: missing
- CONFIG_IP_VS: enabled (as module)
- CONFIG_IP_VS_NFCT: enabled
- CONFIG_IP_VS_RR: enabled (as module)
- CONFIG_EXT4_FS: enabled
- CONFIG_EXT4_FS_POSIX_ACL: enabled
- CONFIG_EXT4_FS_SECURITY: enabled
- Network Drivers:
  - "overlay":
    - CONFIG_VXLAN: enabled (as module)
      Optional (for encrypted networks):
      - CONFIG_CRYPTO: enabled
      - CONFIG_CRYPTO_AEAD: enabled
      - CONFIG_CRYPTO_GCM: enabled (as module)
      - CONFIG_CRYPTO_SEQIV: enabled
      - CONFIG_CRYPTO_GHASH: enabled (as module)
      - CONFIG_XFRM: enabled
      - CONFIG_XFRM_USER: enabled (as module)
      - CONFIG_XFRM_ALGO: enabled (as module)
      - CONFIG_INET_ESP: enabled (as module)
      - CONFIG_INET_XFRM_MODE_TRANSPORT: enabled (as module)
  - "ipvlan":
    - CONFIG_IPVLAN: enabled (as module)
  - "macvlan":
    - CONFIG_MACVLAN: enabled (as module)
    - CONFIG_DUMMY: enabled (as module)
  - "ftp,tftp client in container":
    - CONFIG_NF_NAT_FTP: enabled (as module)
    - CONFIG_NF_CONNTRACK_FTP: enabled (as module)
    - CONFIG_NF_NAT_TFTP: enabled (as module)
    - CONFIG_NF_CONNTRACK_TFTP: enabled (as module)
- Storage Drivers:
  - "aufs":
    - CONFIG_AUFS_FS: enabled (as module)
  - "btrfs":
    - CONFIG_BTRFS_FS: enabled (as module)
    - CONFIG_BTRFS_FS_POSIX_ACL: enabled
  - "devicemapper":
    - CONFIG_BLK_DEV_DM: enabled
    - CONFIG_DM_THIN_PROVISIONING: enabled (as module)
  - "overlay":
    - CONFIG_OVERLAY_FS: enabled (as module)
  - "zfs":
    - /dev/zfs: missing
    - zfs command: missing
    - zpool command: missing

Limits:
- /proc/sys/kernel/keys/root_maxkeys: 1000000

意义线:

- CONFIG_RT_GROUP_SCHED: missing

共有2个答案

沈琛
2023-03-14

盖伊·德·卡鲁费尔给出的解决方案对我不起作用。我要做的(显然是在编译了支持控制组的内核之后)是首先用以下命令杀死Docker守护进程:

$ sudo systemctl stop docker
$ sudo systemctl stop docker.socket

然后我可以重新打开守护进程,为其控制组分配一个大的时间片(例如950000):

$ sudo dockerd --cpu-rt-runtime=950000

对Docker守护程序的这些更改可以通过按此处和此处所述的配置来永久化。

最后,我可以使用实时调度器启动我的容器,如下所示:

$ sudo docker run -it --cpu-rt-runtime=950000 --ulimit rtprio=99 ubuntu:20.04

在Docker Compose文件中,您可以通过以下设置实现这一点(如以下文档中所指出的:1、2、3):

cpu_rt_runtime: 950000
ulimits:
  rtprio: 99

另外以privilegednet=host的身份启动容器有助于减少开销,正如本文和此处所讨论的。

分配的实时运行时cpu。可以在/sys/fs/cgroup/cpu、cpuacct文件夹中检查每个控制组的rt\u运行时\u us。如果您已经将大部分实时运行时分配给另一个cgroup,这可能会导致错误消息无法将95000写入cpu。rt_runtime_us:write/sys/fs/cgroup/cpu、cpuacct/system。切片//中央处理器。rt_runtime_us:无效参数或类似参数(请参见此处和此处)。有关一般控制组的更多详细信息,请参阅相应的官方文件(4,5)。

对于来自Docker内部的实时进程,我发现了控制组的替代方法,PREEMPT\u RT补丁更有用:您可以从Debian软件包轻松安装它,运行Docker,然后使用privileged选项就足够了,以便为来自Docker内部的进程设置实时优先级。其优点主要是与对照组相比,最大延迟显著降低。我在这篇文章中详细讨论了这一点。

华瀚漠
2023-03-14

在容器中执行RT调度有两个选项:

>

  • 添加SYS_NICE功能

    docker run--cap添加系统很好。。。

    使用特权模式和--特权标志

    docker run--特权。。。

    特权模式被认为是不安全的,所以选项1最好只添加您需要的功能。

    如果您以root用户身份运行(Docker容器的默认设置),您可能还必须在sysctl中启用实时调度:

    sysctl -w kernel.sched_rt_runtime_us=-1
    

    要使其永久化(更新您的图像):

    echo 'kernel.sched_rt_runtime_us=-1' > /etc/sysctl.conf
    

    https://docs.docker.com/engine/reference/run/#runtime-特权和linux功能

  •  类似资料:
    • 问题内容: 我正在编写Linux守护程序。我发现了两种方法。 通过调用和设置守护进程。 使用运行程序。 哪个是正确的方法? 问题答案: 来自http://www.steve.org.uk/Reference/Unix/faq_2.html#SEC16 以下是成为守护程序的步骤: 1. fork(),以便父级可以退出,这会将控制权返回给命令行或shell来调用您的程序。需要执行此步骤,以确保新流程不

    • 本文向大家介绍linux下的守护进程,包括了linux下的守护进程的使用技巧和注意事项,需要的朋友参考一下 Linux下的常驻进程的作用不可忽略,但这里面的问题也不能忽略,怎么启动进程,怎么结束进程,怎么在进程挂掉之后重启进程都要设计的合理。下面看一个shell控制的php常驻进程的例子。 不废话,直接捞干货,上代码,通过代码来讲解更容易理解: 只里面有几个要强调的地方: 我用这个shell去调用

    • 本文向大家介绍python实现守护进程、守护线程、守护非守护并行,包括了python实现守护进程、守护线程、守护非守护并行的使用技巧和注意事项,需要的朋友参考一下 守护进程 1、守护子进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allow

    • Storm 有几个不同的守护进程. 调度 workers 的 Nimbus, 启动和杀死 workers 的 supervisors, 可以访问日志的 log viewer(日志查看器)以及显示集群状态 UI. 当一个 worker 挂掉时会发生什么? 当一个 worker 挂掉时, supervisor 将会重启它. 如果在启动它时继续发生故障并且没有发送 hearbeat(心跳)给 Nimbu

    • 我创建了一个Dockerfile来在Docker中运行Docker: 启动容器并运行docker ps后,我得到:“无法连接到unix:///var/run/docker.sock.docker守护程序是否正在运行?" 我在容器中执行了命令dockerd,结果是: 启动守护程序时出错:初始化网络控制器时出错:获取控制器实例时出错:未能创建NAT链DOCKER:iptables失败:iptables

    • 在Windows上,我总是能够毫无问题地构建Docker图像。 如原始文档https://docs.docker.com/config/daemon/systemd/中所述,键入将导致以下错误: