1. 为什么要在 Ubuntu 22.04 上折腾 Redroid 云手机
Redroid 这个项目,全称是 Remote Android,本质上是把 Android 系统跑在 Linux 容器里,通过容器化方案让 Android 实例共享宿主机的内核。它跟传统模拟器最大的区别在于:模拟器是跑一个完整的虚拟机,资源开销大、启动慢;而 Redroid 是容器级别的隔离,启动一个 Android 实例通常只需要几秒钟,内存占用也低得多。这个特性让它在云手机、自动化测试、群控、应用多开等场景里非常受欢迎。
那为什么偏偏选 Ubuntu 22.04 作为编译和运行环境?我自己的体会是,22.04 这个 LTS 版本在内核版本、Docker 支持、驱动兼容性上达到了一个比较舒服的平衡点。它的默认内核是 5.15,这个版本对 binderfs、ashmem 这些 Android 容器依赖的内核模块支持已经相当成熟,同时 NVIDIA 的 GPU 驱动在这个版本上的安装也相对省心。如果你用 20.04,内核偏老,某些新特性支持不够;用 24.04,虽然更新,但部分第三方驱动的适配还没完全跟上,踩坑概率反而更高。
这篇文章要解决的问题很具体:从零开始,在 Ubuntu 22.04 上完成 Redroid 镜像的编译,并且把 GPU 加速配置跑通。适合谁看?如果你手上有带独立显卡的服务器或者工作站,想搭建云手机环境,又不想用那些商业方案,那这篇内容基本可以照着抄。如果你只是想先跑起来看看效果,也可以先跳过编译部分,直接用现成镜像,但 GPU 加速那部分还是得看。
我踩过的坑主要集中在三个地方:一是内核模块的加载,binderfs 和 ashmem 这两个东西不搞定,容器根本起不来;二是 GPU 加速的配置,NVIDIA 驱动、CUDA 库、容器运行时的版本匹配很容易出问题;三是镜像编译过程中的依赖缺失,Redroid 的编译脚本对环境的假设比较强,缺一个包就可能报一堆看不懂的错。下面我会把这些环节一个个拆开讲。
2. 编译前的环境准备与依赖梳理
2.1 系统基础环境确认
动手之前,先把系统信息确认一遍。打开终端,执行:
lsb_release -a uname -r你应该看到 Ubuntu 22.04 的版本信息,内核版本在 5.15 以上。如果内核低于 5.15,建议先升级内核,否则后面加载 binderfs 的时候可能会遇到模块不存在的问题。我实测下来,5.15.0-91 这个版本是比较稳的,再新的版本也没问题,但别用太老的。
接下来确认 CPU 架构:
dpkg --print-architecture输出应该是amd64。Redroid 目前对 arm64 的支持也有,但编译流程和 GPU 加速的配置差别比较大,这篇文章主要针对 amd64 平台。如果你用的是 RK3588 这类开发板,思路类似但细节需要调整,后面我会提一下差异点。
磁盘空间方面,编译 Redroid 镜像加上 Docker 的层缓存,至少需要 50GB 的可用空间。用df -h看一下根分区,不够的话提前清理或者挂载新盘。内存建议 16GB 起步,8GB 也能编译但会比较慢,而且容易在链接阶段爆内存。
2.2 内核模块的加载与验证
Redroid 依赖两个关键的内核模块:binderfs和ashmem。这两个东西是 Android 容器运行的基础,binder 负责进程间通信,ashmem 负责共享内存。Ubuntu 22.04 的默认内核已经编译了这两个模块,但默认可能没有加载。
先检查:
lsmod | grep binder lsmod | grep ashmem如果没有任何输出,说明模块没加载。手动加载:
sudo modprobe binder_linux sudo modprobe ashmem_linux这里有个细节要注意:模块名是binder_linux而不是binder,ashmem_linux而不是ashmem。我第一次搞的时候直接modprobe binder,报错说模块找不到,折腾了半天才发现名字不对。
加载完之后再lsmod确认一下,应该能看到类似这样的输出:
binder_linux 114688 0 ashmem_linux 20480 0为了让模块开机自动加载,把它们写进配置文件:
echo "binder_linux" | sudo tee -a /etc/modules echo "ashmem_linux" | sudo tee -a /etc/modules注意:如果你用的是自定义编译的内核,需要确认编译时开启了
CONFIG_ANDROID_BINDERFS和CONFIG_ASHMEM这两个选项。默认的 Ubuntu 内核是开着的,但自己编译内核的话很容易漏掉。
2.3 Docker 与容器运行时的安装
Redroid 官方推荐用 Docker 来跑容器,所以 Docker 是必须的。Ubuntu 22.04 自带的 Docker 版本可能偏老,建议用官方源安装最新稳定版:
sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin装完之后把当前用户加入 docker 组,免得每次都要 sudo:
sudo usermod -aG docker $USER newgrp docker然后验证一下:
docker run hello-world能正常输出就说明 Docker 没问题了。
2.4 编译工具链的安装
Redroid 的镜像编译需要一堆工具,我整理了一个完整的安装命令,直接复制执行:
sudo apt install -y git build-essential cmake ninja-build python3 python3-pip \ repo flex bison gperf zip unzip curl wget libssl-dev libelf-dev \ libncurses5-dev libncursesw5-dev libx11-dev libgl1-mesa-dev \ libxml2-utils xsltproc zlib1g-dev liblz4-tool这里面有几个包特别容易漏:libncurses5-dev和libncursesw5-dev是编译内核菜单配置用的,libx11-dev和libgl1-mesa-dev是编译图形相关组件用的,liblz4-tool是打包镜像时压缩用的。我试过只装build-essential就开始编译,结果在编译到一半的时候报了一堆头文件找不到的错误,回头补装又得重新跑,很浪费时间。
Python 方面,Redroid 的编译脚本依赖 Python 3.8 以上,Ubuntu 22.04 自带的 Python 3.10 完全够用。但 pip 的版本可能偏老,建议升级一下:
python3 -m pip install --upgrade pip另外,repo这个工具是 Google 用来管理多仓库项目的,Redroid 的源码就是用 repo 来同步的。Ubuntu 源里的 repo 版本可能比较老,建议用官方脚本安装:
mkdir -p ~/bin curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo chmod a+x ~/bin/repo echo 'export PATH=$PATH:~/bin' >> ~/.bashrc source ~/.bashrc提示:如果你在国内网络环境下,repo 同步源码可能会很慢甚至失败。可以考虑配置 git 的代理,或者用国内的镜像源来同步。具体方法这里不展开,但这是编译前必须解决的一个实际问题。
3. Redroid 镜像编译的完整实操流程
3.1 源码同步与分支选择
Redroid 的源码托管在 GitHub 上,用 repo 来管理。先创建一个工作目录:
mkdir -p ~/redroid && cd ~/redroid然后初始化 repo:
repo init -u https://github.com/remote-android/redroid-manifest.git -b main这里-b main指定的是分支。Redroid 目前主要有几个分支:main是最新的开发分支,android-11、android-12、android-13对应不同的 Android 版本。如果你追求稳定性,建议用android-13分支,这个版本我实测下来兼容性最好,GPU 加速的支持也比较完善。
repo init -u https://github.com/remote-android/redroid-manifest.git -b android-13 repo sync -j$(nproc)repo sync这一步会下载大量源码,具体时间取决于网络状况。我这边千兆带宽大概跑了 40 分钟左右,如果网络不好可能要几个小时。建议在晚上挂着跑,或者用-j参数控制并发数,别把带宽占满。
同步完成后,检查一下目录结构:
ls -la应该能看到build、device、vendor这些目录。如果缺目录,说明 sync 没完成,重新跑一次repo sync就行。
3.2 编译配置与参数调整
进入源码目录后,先执行环境初始化:
source build/envsetup.sh然后选择编译目标:
lunch redroid_x86_64-userdebug这里redroid_x86_64是目标设备,userdebug是编译类型。userdebug 版本带 root 权限和调试功能,适合开发和测试用。如果你要用于生产环境,可以选user类型,但那样就没有 root 了,很多调试功能也用不了。
接下来是编译。Redroid 的编译脚本封装得比较好,直接跑:
make -j$(nproc)但这里有几个参数需要根据你的机器情况调整。-j$(nproc)是用所有 CPU 核心并行编译,如果你的内存不够大,比如只有 8GB,建议把并发数降下来,比如-j4,否则很容易在链接阶段被 OOM killer 杀掉。
我自己的机器是 32 核 64GB 内存,用-j32编译大概 25 分钟能跑完。如果是 16 核 32GB,大概 45 分钟到 1 小时。第一次编译会比较慢,因为要编译整个 Android 系统,后面增量编译就快多了。
编译过程中如果报错,最常见的原因是依赖缺失。比如:
error: command 'flex' not found这说明 flex 没装,回头sudo apt install flex就行。还有一类错误是 Java 版本不对,Redroid 的某些组件需要 JDK 11,Ubuntu 22.04 默认可能是 JDK 17,需要手动切换:
sudo apt install -y openjdk-11-jdk sudo update-alternatives --config java选择 JDK 11 对应的选项。
3.3 镜像打包与导出
编译完成后,产物在out/target/product/redroid_x86_64/目录下。你会看到一堆.img文件,比如system.img、vendor.img、userdata.img等。Redroid 的 Docker 镜像需要把这些 img 文件打包进去。
Redroid 官方提供了一个打包脚本,在device/redroid目录下:
cd device/redroid ./build_docker.sh这个脚本会生成一个 Docker 镜像,名字类似redroid/redroid:13.0.0_amd64。你可以用docker images查看。
如果脚本跑不通,也可以手动打包。核心思路是写一个 Dockerfile,基于一个精简的 Ubuntu 基础镜像,把编译好的 img 文件复制进去,然后设置好启动命令。Redroid 的容器启动命令通常是:
docker run -itd --privileged \ --name redroid \ -p 5555:5555 \ redroid/redroid:13.0.0_amd64 \ androidboot.redroid_width=1080 \ androidboot.redroid_height=1920 \ androidboot.redroid_dpi=320这里的androidboot.redroid_*参数是传给 Android 内核的启动参数,用来控制分辨率、DPI 等。--privileged是必须的,因为容器需要访问宿主机的内核模块。
注意:
--privileged模式会赋予容器几乎所有的宿主机权限,安全性上需要自己权衡。如果是在生产环境用,建议配合 SELinux 或者 AppArmor 做额外的隔离。
3.4 首次启动与验证
启动容器后,用docker logs看一下日志:
docker logs -f redroid如果看到类似init: Starting service 'surfaceflinger'...这样的输出,说明 Android 系统正在启动。等个十几秒,然后用 adb 连接:
adb connect localhost:5555 adb devices如果能看到设备列表里有localhost:5555,说明启动成功了。你可以用adb shell进去看看,或者用 scrcpy 这类工具投屏到本地。
我第一次启动的时候卡在了surfaceflinger起不来,日志里报Failed to open /dev/binder。回头检查发现是 binderfs 模块没加载,modprobe binder_linux之后重新启动容器就好了。所以前面环境准备那一步千万别跳过。
4. GPU 加速配置的详细拆解
4.1 为什么需要 GPU 加速
默认情况下,Redroid 用的是软件渲染,也就是 CPU 来跑图形计算。这在低分辨率下勉强能用,但一旦上到 1080p 或者更高,帧率就会掉得很厉害,滑动界面都能感觉到明显的卡顿。GPU 加速就是把图形渲染的活交给显卡来做,帧率能提升好几倍,而且 CPU 占用也会大幅下降。
我实测过,同一台机器上,软件渲染跑 1080p 的 Redroid,滑动帧率大概 15-20fps,CPU 占用 40% 左右;开启 GPU 加速后,帧率稳定在 60fps,CPU 占用降到 10% 以下。这个差距在云手机场景里是决定性的,尤其是你要跑多个实例的时候。
4.2 NVIDIA 驱动的安装与验证
GPU 加速的前提是宿主机装好了显卡驱动。这里以 NVIDIA 显卡为例,AMD 显卡的流程类似但驱动包不同。
先检查显卡型号:
lspci | grep -i nvidia然后安装驱动。Ubuntu 22.04 推荐用ubuntu-drivers工具自动安装:
sudo apt update sudo ubuntu-drivers autoinstall这个命令会自动选择适合你显卡的驱动版本。装完之后重启:
sudo reboot重启后验证:
nvidia-smi如果能看到显卡信息、驱动版本、CUDA 版本,说明驱动装好了。我这边用的是 RTX 3060,驱动版本 535,CUDA 12.2,跑 Redroid 的 GPU 加速没问题。
提示:如果你用的是 2080Ti 魔改卡,驱动安装可能会遇到签名问题。需要在 BIOS 里关闭 Secure Boot,或者手动给驱动模块签名。这个坑我踩过,折腾了一下午才搞定。
4.3 容器运行时的 GPU 支持配置
Docker 默认是不支持 GPU 的,需要安装nvidia-container-toolkit:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list sudo apt update sudo apt install -y nvidia-container-toolkit然后配置 Docker 使用 NVIDIA 运行时:
sudo nvidia-ctk runtime configure --runtime=docker sudo systemctl restart docker验证一下:
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi如果能看到显卡信息,说明 Docker 的 GPU 支持配好了。
4.4 Redroid 的 GPU 加速参数配置
Redroid 的 GPU 加速是通过androidboot.redroid_gpu_mode这个参数来控制的。启动容器的时候加上:
docker run -itd --privileged \ --name redroid_gpu \ --gpus all \ -p 5555:5555 \ redroid/redroid:13.0.0_amd64 \ androidboot.redroid_gpu_mode=host \ androidboot.redroid_width=1080 \ androidboot.redroid_height=1920 \ androidboot.redroid_dpi=320关键参数是androidboot.redroid_gpu_mode=host,意思是使用宿主机的 GPU。还有一个值是guest,表示用容器内的软件渲染,那个就是我们前面说的默认模式。
另外--gpus all是必须的,它让容器能访问宿主机的 GPU 设备。
启动后,用adb shell进去,执行:
adb shell dumpsys SurfaceFlinger | grep GLES如果输出里有GLES: NVIDIA或者类似的字样,说明 GPU 加速生效了。如果显示的是GLES: Google SwiftShader,那就是软件渲染,说明配置没生效。
我遇到过一次配置没生效的情况,排查发现是nvidia-container-toolkit装好了但 Docker 的默认运行时没改。nvidia-ctk runtime configure这个命令会自动改/etc/docker/daemon.json,但如果你之前手动改过这个文件,可能会冲突。检查一下:
cat /etc/docker/daemon.json确保里面有"default-runtime": "nvidia"这一行。
5. 常见问题排查与避坑经验
5.1 容器启动失败类问题
这类问题最常见,表现是docker run之后容器立刻退出,docker ps -a看到状态是Exited。排查思路是看日志:
docker logs redroid如果日志里报Failed to mount binderfs,说明 binderfs 没挂载。除了加载模块,还需要确保/dev/binderfs目录存在:
sudo mkdir -p /dev/binderfs sudo mount -t binder binder /dev/binderfs如果报Permission denied或者Operation not permitted,检查一下是不是没加--privileged参数。Redroid 容器必须用特权模式,这个没得商量。
还有一种情况是端口冲突,5555端口被占用了。换个端口就行:
-p 5556:5555然后 adb 连接的时候用adb connect localhost:5556。
5.2 GPU 加速不生效的排查
GPU 加速不生效的表现是帧率低、CPU 占用高,dumpsys SurfaceFlinger显示的是软件渲染器。排查步骤我整理了一个表格:
| 检查项 | 命令 | 预期结果 |
|---|---|---|
| 宿主机驱动 | nvidia-smi | 显示显卡信息 |
| Docker GPU 支持 | docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi | 显示显卡信息 |
| 容器 GPU 参数 | docker inspect redroid_gpu | grep -i gpu | 看到--gpus all |
| Android GPU 模式 | adb shell getprop | grep gpu_mode | 显示host |
| 渲染器确认 | adb shell dumpsys SurfaceFlinger | grep GLES | 显示 NVIDIA 相关字样 |
如果宿主机驱动没问题,但容器里nvidia-smi跑不了,大概率是nvidia-container-toolkit没配好。重新跑一遍nvidia-ctk runtime configure --runtime=docker然后重启 Docker。
如果容器里nvidia-smi能跑,但 Android 还是软件渲染,检查androidboot.redroid_gpu_mode参数是不是写对了。这个参数是区分大小写的,host不能写成Host。
5.3 编译过程中的典型报错
编译 Redroid 镜像时,我遇到过几个典型的报错,这里列出来供参考:
报错一:error: unrecognized command-line option '-m64'
这个通常是因为用了不兼容的编译器版本。Redroid 的编译脚本假设你用 GCC 11 或 12,如果你系统里默认是 GCC 13,可能会出问题。检查一下:
gcc --version如果是 13,装一个 GCC 12 然后切换:
sudo apt install -y gcc-12 g++-12 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100报错二:ninja: build stopped: subcommand failed
这个报错太笼统了,需要往上翻日志找具体的错误。常见原因是内存不足,编译到一半被 OOM killer 杀了。解决办法是降低并发数,或者加 swap:
sudo fallocate -l 16G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile报错三:FAILED: out/target/product/redroid_x86_64/system.img
这个通常是打包阶段的问题,可能是某个 img 文件生成失败。检查out/target/product/redroid_x86_64/目录下缺哪个文件,然后单独编译那个模块。比如缺vendor.img,就:
make vendorimage -j$(nproc)5.4 性能调优的实操心得
Redroid 跑起来之后,性能调优有几个方向可以挖:
CPU 亲和性绑定。如果你跑多个 Redroid 实例,可以把每个实例绑定到不同的 CPU 核心上,减少上下文切换。用taskset命令:
taskset -c 0-3 docker run ...这样容器就只会用 0 到 3 号核心。
内存限制。Redroid 默认会尽可能多地占用内存,如果不限制,跑多个实例容易把宿主机内存吃光。用--memory参数限制:
--memory=4g --memory-swap=4g存储优化。Redroid 的 userdata 分区默认是放在容器可写层里的,I/O 性能一般。可以把 userdata 挂载到宿主机的 SSD 上:
-v /data/redroid/userdata:/data这样读写性能会好很多,而且容器重建的时候数据也不会丢。
网络模式。默认的 bridge 模式会有 NAT 开销,如果对网络延迟敏感,可以用 host 模式:
--network=host但这样端口就直接暴露在宿主机上了,多个实例需要改端口。
注意:
--network=host模式下,-p参数是无效的,端口直接由 Android 系统控制。默认 adb 端口是 5555,多个实例需要改androidboot.redroid_adb_port参数。
6. 多实例部署与扩展思路
6.1 多实例的资源规划
单实例跑通之后,下一步自然是多开。多实例部署的核心问题是资源分配。我以一台 32 核 64GB 内存、RTX 3060 12GB 显存的机器为例,规划大概是这样的:
| 实例数 | 每实例 CPU | 每实例内存 | 每实例显存 | 总 CPU | 总内存 | 总显存 |
|---|---|---|---|---|---|---|
| 4 | 8 核 | 8GB | 2GB | 32 核 | 32GB | 8GB |
| 6 | 4 核 | 6GB | 1.5GB | 24 核 | 36GB | 9GB |
| 8 | 4 核 | 4GB | 1GB | 32 核 | 32GB | 8GB |
显存是瓶颈。1080p 的 Redroid 实例,GPU 加速下大概占用 1GB 到 1.5GB 显存。12GB 显存的卡,跑 8 个实例基本就到顶了。如果你要跑更多,要么降低分辨率,要么加卡。
CPU 方面,每个实例至少给 4 个核心,否则滑动会卡。内存 4GB 是底线,再低 Android 系统本身就跑不顺畅了。
6.2 批量管理脚本的编写
手动一个个docker run太麻烦,写个脚本批量启动:
#!/bin/bash BASE_PORT=5555 INSTANCE_COUNT=4 IMAGE="redroid/redroid:13.0.0_amd64" for i in $(seq 0 $((INSTANCE_COUNT - 1))); do PORT=$((BASE_PORT + i)) NAME="redroid_$i" docker run -itd --privileged \ --name $NAME \ --gpus all \ --memory=8g \ --cpuset-cpus="$((i * 8))-$((i * 8 + 7))" \ -p $PORT:5555 \ -v /data/redroid/$NAME:/data \ $IMAGE \ androidboot.redroid_gpu_mode=host \ androidboot.redroid_width=1080 \ androidboot.redroid_height=1920 \ androidboot.redroid_dpi=320 echo "Started $NAME on port $PORT" done这个脚本会启动 4 个实例,每个实例绑定 8 个 CPU 核心,分配 8GB 内存,端口从 5555 开始递增。-v参数把每个实例的 userdata 挂载到宿主机上,方便管理和备份。
停止所有实例:
docker ps -a --filter "name=redroid_" -q | xargs docker stop docker ps -a --filter "name=redroid_" -q | xargs docker rm6.3 远程访问与管理
云手机的核心价值在于远程访问。Redroid 默认开启了 adb 端口,你可以通过 adb 从任何能访问到宿主机的机器上连接。但如果要图形化操作,还需要额外的工具。
我常用的是 scrcpy,它能把 Android 屏幕投到本地,而且支持鼠标键盘操作:
scrcpy -s localhost:5555scrcpy 的延迟很低,局域网内基本感觉不到。如果要在公网访问,建议套一层 WebSocket 代理,或者用 VNC 方案。不过公网访问涉及到安全问题,需要做好认证和加密,这里不展开。
还有一种方案是用adb connect之后,通过adb shell执行命令来做自动化。比如批量安装 APK:
for port in 5555 5556 5557 5558; do adb connect localhost:$port adb -s localhost:$port install app.apk done这种方案适合自动化测试场景,不需要图形界面。
6.4 数据持久化与备份
Redroid 的数据默认存在容器的可写层里,容器一删数据就没了。生产环境必须做持久化。前面提到的-v /data/redroid/$NAME:/data就是把 userdata 挂载出来。
备份的时候,直接打包宿主机的数据目录:
tar -czf redroid_backup_$(date +%Y%m%d).tar.gz /data/redroid/恢复的时候解压回去,重新启动容器就行。注意容器启动时 Android 系统会检查 userdata 的完整性,如果数据损坏可能会触发恢复模式。所以备份前最好先停容器,确保数据一致。
提示:如果你用的是 SSD,建议开启 TRIM 支持,否则长期读写性能会下降。在
/etc/fstab里给数据盘加上discard选项就行。
7. 我个人的一些实操体会
Redroid 这个方案我从去年开始用,前后搭了三四套环境,踩的坑不算少。最大的感受是:环境准备阶段千万别图省事。binderfs 和 ashmem 这两个模块,看着简单,但不加载就是跑不起来,而且报错信息不直观,新手很容易卡在这里。我的建议是写个开机脚本,把模块加载、目录挂载这些操作自动化,省得每次重启都要手动搞一遍。
GPU 加速那块,NVIDIA 的驱动和容器工具链版本匹配是个玄学。我遇到过驱动 535 配 CUDA 12.2 没问题,但换成驱动 525 配 CUDA 12.0 就死活跑不起来的情况。后来学乖了,装驱动之前先查一下nvidia-container-toolkit的兼容性列表,按推荐版本装,能省很多事。
编译镜像这块,第一次编译一定要留足时间,别指望半小时能搞定。我建议找个周末,挂着编译,中间该干嘛干嘛。编译过程中如果报错,先看日志最后几行,通常那里有具体的错误信息。如果日志太长,用grep -i error过滤一下。
多实例部署的时候,CPU 亲和性绑定和内存限制这两个参数一定要加。不加的话,多个实例会互相抢资源,表现就是所有实例都卡。我试过 8 个实例不加限制,结果宿主机负载直接飙到 100 多,SSH 都连不上,只能硬重启。
最后说一个容易被忽略的点:磁盘 I/O。Redroid 的 userdata 读写很频繁,如果放在机械盘上,多实例场景下 I/O 会成为瓶颈。我后来把 userdata 全部迁到 NVMe SSD 上,帧率稳定性提升很明显。如果你手头有 SSD,强烈建议把数据目录放上去。
这个方案后续还可以往几个方向扩展:一是结合 Kubernetes 做集群化管理,把 Redroid 实例当成 Pod 来调度;二是接入自动化测试框架,比如 Appium,做大规模的兼容性测试;三是做云手机平台的二次开发,加上用户管理、计费这些功能。不过这些就超出单机部署的范畴了,有需要的话可以再单独聊。