Android运行Docker:如何启用cgroupv2的CPU、内存、IO等控制器
解决cgroupv2控制器缺失及Docker运行错误的方案
一、补充必要的内核配置项
你当前的内核配置仅覆盖了cgroupv1的部分功能,cgroupv2需要额外启用以下配置:
# 启用cgroupv2核心支持 CONFIG_CGROUP_V2=y # cgroupv2各控制器支持 CONFIG_CGROUP_CPU=y # CPU控制器(替代v1的CGROUP_CPUACCT) CONFIG_CGROUP_MEMCG=y # 内存控制器 CONFIG_CGROUP_IO=y # IO控制器 CONFIG_CGROUP_CPUSET=y # cpuset控制器(需确保与v2兼容) # BPF相关配置(解决bpf_prog_query错误) CONFIG_BPF=y CONFIG_BPF_SYSCALL=y CONFIG_CGROUP_BPF=y CONFIG_BPF_JIT=y CONFIG_BPF_JIT_ALWAYS_ON=y # 可选,提升BPF性能 # 可选但建议的配置 CONFIG_MEMCG_SWAP=y # 内存控制器支持swap限制 CONFIG_MEMCG_KMEM=y # 内存控制器支持内核内存限制 CONFIG_CGROUP_SCHED=y # 调度器集成
编译内核时确保这些选项都被勾选,重新生成Image.lz4-dtb并刷入设备。
二、切换到cgroupv2并激活控制器
1. 确认当前cgroup版本
执行以下命令检查当前挂载的cgroup版本:
mount | grep cgroup
如果输出包含cgroup2说明已挂载v2;若大量出现无v2后缀的cgroup条目,则当前为v1,需要切换。
2. 切换到cgroupv2(Android系统)
- 临时切换(重启后失效):
先卸载所有cgroupv1挂载点,再挂载cgroupv2:# 卸载所有cgroupv1挂载 for mount in $(mount | grep cgroup | grep -v cgroup2 | awk '{print $3}'); do umount $mount; done # 挂载cgroupv2 mount -t cgroup2 none /sys/fs/cgroup - 永久切换:
修改设备启动参数(需修改boot.img的cmdline),添加以下内容:
可使用cgroup_no_v1=all systemd.unified_cgroup_hierarchy=1magiskboot工具修改boot.img的cmdline,刷入修改后的boot.img即可。
3. 激活所需控制器
挂载cgroupv2后,将控制器添加到根cgroup的子树控制中:
cd /sys/fs/cgroup echo "+cpu +cpuset +memory +io +pids" > cgroup.subtree_control
执行后再次检查控制器状态:
cat /sys/fs/cgroup/cgroup.controllers
正常应返回cpu cpuset memory io pids。
三、Android init系统适配
部分原生ROM的init脚本可能会重新挂载cgroupv1,需修改init.rc或相关启动脚本:
- 移除所有挂载cgroupv1的指令
- 添加cgroupv2挂载指令:
mount cgroup2 none /sys/fs/cgroup - 在挂载后添加激活控制器的指令:
write /sys/fs/cgroup/cgroup.subtree_control "+cpu +cpuset +memory +io +pids"
修改后重新打包ROM或刷入包含修改后init.rc的boot.img。
四、验证Docker运行
完成上述操作后重启设备,重新启动Docker服务并测试:
dockerd & docker run --rm alpine echo "Hello Docker"
内容的提问来源于stack exchange,提问作者Paul P
相关产品推荐
相关产品推荐

