首页 > 解决方案 > 在 ubuntu 内核中启用 cgroup cpu 实时运行时

问题描述

我正在尝试在 Ubuntu 18.04 上运行的 docker 容器中使用实时调度。

我已经按照此处给出的方法安装了实时内核。我选择了内核版本 5.2.9 及其相关的 rt 补丁。

的输出uname -a确认实时内核已安装并运行良好:

Linux myLaptop 5.2.9-rt3 #1 SMP PREEMPT RT ...

要运行我的容器,我发出以下命令:

docker run --cpu-rt-runtime=95000 \
    --ulimit rtprio=99 \
    --ulimit memlock=102400 \
    --cap-add=sys_nice \
    --privileged \
    -it \
    myimage:latest

但是,我得到的输出是:

docker: Error response from daemon: Your kernel does not support cgroup cpu real-time runtime.

我已经看到,这可能与问题中所详述的缺失CONFIG_RT_GROUP_SCHED有关。事实上,如果我运行此页面提供的脚本来检查内核与 Docker 的兼容性,我会得到:

- CONFIG_RT_GROUP_SCHED: missing

这似乎证实了 Docker 正在使用它进行实时调度,但内核中并未提供,尽管已修补为实时。

从那里,我试图徒劳地寻找解决方案。我不精通内核配置,不知道是否需要使用特定选项编译它,以及选择哪个选项来添加缺少的CONFIG_RT_GROUP_SCHED.

非常感谢您的建议和帮助。

标签: dockerlinux-kernelreal-time

解决方案


在谈论实时 Linux 时,有不同的方法,从单内核方法(如PREEMPT_RT)到双内核方法(如Xenomai)。您可以将具有实时功能的 Docker 与所有这些(显然您的主机内核必须匹配)结合使用来生成具有实时功能的系统,但方法不同。在您的情况下,您混合了两种不同的方法:您安装时遵循与不兼容的控制组PREEMPT_RT的指南。PREEMPT_RT


默认情况下,Linux 内核可以使用不同级别的抢占能力进行编译(参见例如Reghenzani 等人 - “实时 Linux 内核:关于 PREEMPT_RT 的调查”):

  • PREEMPT_NONE没有办法强制抢占
  • PREEMPT_VOLUNTARY在某些位置可以进行抢占以减少延迟
  • PREEMPT抢占可以发生在内核的任何部分(不包括自旋锁和其他关键部分)

这些可以通过在内核编译期间设置来与控制组(cgroups简称)的特性相结合,为某个(用户定义的)组的进程保留一定比例的CPU时间。CONFIG_RT_GROUP_SCHED=y

PREEMPT_RT开发自PREEMPT并且是一组旨在使内核完全可抢占的补丁,即使在关键部分(PREEMPT_RT_FULL)。为此,例如自旋锁在很大程度上被互斥锁所取代。截至 2021 年,它正在慢慢合并到主线中,并且无需修补内核即可供公众使用。正如此处 PREEMPT_RT所述,当前无法使用 编译,CONFIG_RT_GROUP_SCHED因此无法与对照组一起使用(请参阅此处进行比较)。从我读到的内容来看,这是由于高延迟峰值,我已经通过cyclicytests在对照组中观察到了这一点。

这意味着您可以编译内核(有关详细信息,请参阅Ubuntu 手册

  • 没有PREEMPT_RT但有CONFIG_RT_GROUP_SCHED(有关详细信息,请参阅这篇文章)并遵循Docker 实时控制组指南以及我在此处的帖子。根据我的经验,这虽然有相当高的延迟峰值,但对于最坏情况延迟比平均延迟更重要的实时系统来说,这是不可取的。

  • PREEMPT_RT不带CONFIG_RT_GROUP_SCHED(也可以从 Debian 软件包安装,例如这个)。--privileged --net=host在这种情况下,使用 options或 Docker-compose 等效项执行 Docker 就足够了privileged: true network_mode: host。然后,来自 Docker 内部的任何进程都可以设置实时优先级rtprio(例如,通过从代码内部调用::pthread_setschedparam或通过chrt从命令行使用)。

    如果您没有在 Docker中使用rootas 用户,您还必须为自己指定一个用户名,该用户名属于在您的主机上具有实时权限的组(请参阅 参考资料$ ulimit -r)。这可以通过复制用户组的部分并创建一个新组(例如)或直接添加用户(例如)来相应地配置PAM 限制/etc/security/limits.conf文件)(如此处所述):@realtime@some_groupsome_user

    @some_group     soft    rtprio          99
    @some_group     soft    priority        99
    @some_group     hard    rtprio          99
    @some_group     hard    priority        99
    

    在这种情况下rtprio,非特权进程允许的最大实时优先级。限制是可以设置限制的hard实际限制。soft限制由hard超级用户设置并由内核强制执行。用户不能提高他的代码以比hard限制更高的优先级运行。soft另一方面,limit 是受限于limit 的默认值hard。有关更多信息,请参见此处

我将后一个选项用于具有实时能力的机器人应用程序,并且无法观察到使用和不使用 Docker 之间的延迟差异。


推荐阅读