docker - 在 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
.
非常感谢您的建议和帮助。
解决方案
在谈论实时 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
因此无法与对照组一起使用(请参阅此处进行比较)。从我读到的内容来看,这是由于高延迟峰值,我已经通过cyclicytest
s在对照组中观察到了这一点。
这意味着您可以编译内核(有关详细信息,请参阅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中使用
root
as 用户,您还必须为自己指定一个用户名,该用户名属于在您的主机上具有实时权限的组(请参阅 参考资料$ ulimit -r
)。这可以通过复制用户组的部分并创建一个新组(例如)或直接添加用户(例如)来相应地配置PAM 限制(/etc/security/limits.conf
文件)(如此处所述):@realtime
@some_group
some_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 之间的延迟差异。
推荐阅读
- python - 如何在线程内使用 QWebEngineView 而不会崩溃?
- node.js - 让 gulp-imagemin 工作的问题
- sql - 具有全局用户定义类型的 Oracle SQL TABLE 运算符显示“表达式类型错误”
- java - JAXB 自定义绑定 - 前缀必须解析为命名空间
- python - 如何从字符串中提取90%以上的字母和数字?
- objective-c - Apple PTP - withCompleteContentCatalog not firing (Rust + Obj-C)
- encryption - Filecoin Lotus PrivateKey 转换为长度为 32 的常规私钥
- kubernetes - Airflow - KubernetesPodOperator - 绑定服务帐户的角色
- visual-studio-code - 如何向 VSCode 添加自定义参数提示?
- r - 如果字符向量中的任何字符串值在数据框的列中,则在新列中返回匹配的字符串