虽然付费云手机服务比较多,但是开源项目非常少,本文将分享搭建openvmi过程,资源太少,希望有所帮助。
为了过程完整性,文章与openvmi文档会有所重复,着重讲解踩过的坑,特别是对于android开发者而言有所难度的k8s搭建过程。流程分为两部分:android镜像编译、k8s环境搭建/调试
Android镜像编译
aosp的网络要求很高,笔者在这上面宰了很多跟头,mac m1、mac x86、ubuntu,最后在腾讯云买了8核32G、100m带宽的香港服务器(ubuntu18.04 x86 50G)10分钟搞定aosp拉取(竞价模式,谁用谁知道)。
安装依赖软件
sudo apt install -y build-essential cmake cmake-data debhelper dbus google-mock \
libboost-dev libboost-filesystem-dev libboost-log-dev libboost-iostreams-dev \
libboost-program-options-dev libboost-system-dev libboost-test-dev \
libboost-thread-dev libcap-dev libsystemd-dev libegl1-mesa-dev \
libgles2-mesa-dev libglm-dev libgtest-dev liblxc1 \
libproperties-cpp-dev libprotobuf-dev libsdl2-dev libsdl2-image-dev lxc-dev \
pkg-config protobuf-compiler python-minimal linux-headers-`uname -r`
编译openvmi
// 下载源码
cd ~
git clone https://github.com/DockDroid/openvmi.git
// 编译与安装内核模块
sudo mkdir -p /opt/openvmi/driver/
cd ~/openvmi/kernel/binder/
make
sudo cp binder_linux.ko /opt/openvmi/driver/
cd ../ashmem/
make
sudo cp ashmem_linux.ko /opt/openvmi/driver/
// 编译与安装openvmi
cd ~/openvmi
mkdir build
cd build
cmake ..
make -j8 install
sudo mkdir -p /opt/openvmi/bin/ /opt/openvmi/libs/libswiftshader
sudo cp bin/openvmi /opt/openvmi/bin/
sudo cp ../libs/* /opt/openvmi/libs/libswiftshader/
搭建Android镜像编译环境
// 安装JDK
sudo apt-get update
sudo apt-get install openjdk-8-jdk
// 编译依赖库
sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib
sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386
sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386
sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev
sudo apt-get install git-core gnupg flex bison gperf build-essential
sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib
sudo apt-get install libc6-dev-i386
sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev
sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
sudo apt-get install lib32z-dev ccache
// 独立输出目录易于提高IO
export OUT_DIR_COMMON_BASE=~/out
//ccache有需要的可以选择,本人未安装
编译Android镜像
此处注意 --depth=1 -c 与官方的不同,笔者在使用repo拉取源码的时候,拉到500G都不够用,这里要指定clone深度,不需要git协作的历史记录;只同步指定分支,不拉去其他分支。
// 安装repo
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
//拉取源码
mkdir $HOME/openvmi-work
cd $HOME/openvmi-work
repo init -u https://github.com/DockDroid/platform_manifests.git -b openvmi --depth=1
repo sync -c -j32
//100m/s,10分钟搞定,✿✿ヽ(°▽°)ノ✿
编译Android源码
并非单纯的aosp,还加入了openvmi二进制文件,即上面编译的openvmi
// 拷贝openvmi
mkdir vendor
mv ~/openvmi ~/openvmi-work/vendor/openvmi
// 初始化环境(这里输出两条日志,如没有,应该是sync不完全)
source build/envsetup.sh
// 构建lunch
lunch openvmi_arm64-userdebug
// 开整
export LC_ALL=C
make -j32
//如遇到Jack server failed to ,SSL error when connecting to the Jack server. Try 'jack-diagnose'
在 /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/java.security 中删除jdk.tls.disabledAlgorithms配置中的"TLSv1,TLSv1.1"。
注意要重启终端,不然修改没配置到jack server。
// 增加openvmi支持
cd $HOME/openvmi-work/vendor/openvmi
scripts/create-package.sh \
/root/openvmi-work/out/target/product/arm64/ramdisk.img \
/root/openvmi-work/out/target/product/arm64/system.img
至此,镜像编译完毕。
k8s平台搭建
官方文档记录的很清晰,但由于网络环境的问题,导致Kube-flannel一直有问题,dns pod拉不起来,笔者在kube-flannel.yml文件找到image,一次单独pull后解决。由于资源有限,以单机k8s的形式搭建,若想搭建集群,按文档加入woker节点即可。
相关工具安装
// 工具拉取
cd ~
git clone https://github.com/DockDroid/cloud-platform.git
// docker安装
// docker配置文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
//添加阿里源
sudo add-apt-repository "deb [arch=arm64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
//安装docker
sudo apt-get install docker-ce=5:18.09.9~3-0~ubuntu-bionic
//k8s运行环境安装
//关闭swap分区交换
sudo swapoff -a
sudo vi /etc/fstab #以“#”注释swapfile打头的那一行
//添加k8s相关命令行工具安装源
curl https://mirrors.huaweicloud.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat << EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.huaweicloud.com/kubernetes/apt kubernetes-xenial main
EOF
sudo apt-get update
// 安装k8s命令行工具
sudo apt-get install kubelet=1.14.2-00 kubeadm=1.14.2-00 kubectl=1.14.2-00 kubernetes-cni=0.7.5-00
//手动拉取k8s Master运行组件的docker镜像
docker pull docker.io/mirrorgooglecontainers/kube-apiserver-arm64:v1.14.2
docker pull docker.io/mirrorgooglecontainers/kube-controller-manager-arm64:v1.14.2
docker pull docker.io/mirrorgooglecontainers/kube-scheduler-arm64:v1.14.2
docker pull docker.io/mirrorgooglecontainers/kube-proxy-arm64:v1.14.2
docker pull docker.io/mirrorgooglecontainers/pause-arm64:3.1
docker pull docker.io/mirrorgooglecontainers/etcd-arm64:3.3.10
docker pull docker.io/coredns/coredns:1.3.1
//修改tag
docker tag docker.io/mirrorgooglecontainers/kube-apiserver-arm64:v1.14.2 k8s.gcr.io/kube-apiserver:v1.14.2
docker tag docker.io/mirrorgooglecontainers/kube-controller-manager-arm64:v1.14.2 k8s.gcr.io/kube-controller-manager:v1.14.2
docker tag docker.io/mirrorgooglecontainers/kube-scheduler-arm64:v1.14.2 k8s.gcr.io/kube-scheduler:v1.14.2
docker tag docker.io/mirrorgooglecontainers/kube-proxy-arm64:v1.14.2 k8s.gcr.io/kube-proxy:v1.14.2
docker tag docker.io/mirrorgooglecontainers/pause-arm64:3.1 k8s.gcr.io/pause:3.1
docker tag docker.io/mirrorgooglecontainers/etcd-arm64:3.3.10 k8s.gcr.io/etcd:3.3.10
docker tag docker.io/coredns/coredns:1.3.1 k8s.gcr.io/coredns:1.3.1
//删除原tag
docker rmi docker.io/mirrorgooglecontainers/kube-apiserver-arm64:v1.14.2
docker rmi docker.io/mirrorgooglecontainers/kube-controller-manager-arm64:v1.14.2
docker rmi docker.io/mirrorgooglecontainers/kube-scheduler-arm64:v1.14.2
docker rmi docker.io/mirrorgooglecontainers/kube-proxy-arm64:v1.14.2
docker rmi docker.io/mirrorgooglecontainers/pause-arm64:3.1
docker rmi docker.io/mirrorgooglecontainers/etcd-arm64:3.3.10
docker rmi docker.io/coredns/coredns:1.3.1
k8s安装
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --kubernetes-version=v1.14.2 --image-repository registry.aliyuncs.com/google_containers
//kubectl执行权限
sudo mkdir $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
k8s网络插件安装
笔者使用kube-flannel 0.15.1版本,找到kube-flannel 中image配置,并提前pull镜像来规避网络环境造成dns,flannel-ads拉不起来的问题,步骤如下:
docker pull rancher/mirrored-flannelcni-flannel-cni-plugin:v1.0.0-arm64
docker pull quay.io/coreos/flannel:v0.15.1
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.15.1/Documentation/kube-flannel.yml
k8s状态查询
这里提供一些好用的命令,用以查看K8s搭建情况,在实际搭建过程中,要注意如下命令的使用,如发现pod处于pending或者说非Running状态,大概率是镜像拉取失败,需考虑上面步骤是否执行成功
//查看本地镜像下载情况
docker images
//查看当前镜像运行情况
docker ps -a
//查看pod状态,非Running状态说明部署有问题
kubectl get pods -A
//查看node状态,需要Ready状态
kubectl get node
//查看指定pod,node详细状况
kubectl describe node master-01
kubectl describe pod coredns-000010-01 -n kube-system
//查看相关服务状态及日志
systemctl status kubelet
openvmi服务配置
编译openvmi镜像
mkdir mount_dir
sudo mount android.img ./mount_dir
cd ./mount_dir
sudo tar --numeric-owner -cf- . | docker import - android:openvmi
openvmi插件,运行环境管理服务安装
cd cloud-platform/services/k8s-dev-plugin-service
sudo ./install.sh
cd cloud-platform/services/android-env-service
sudo ./install.sh
dashboard配置
//拉取dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc6/aio/deploy/recommended.yaml
//修改端口类型,将type: ClusterIP改为NodePort
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
//查看dashboard端口,这里需要修改安全组配置,开放该端口
kubectl get svc -A
之后通过https://<集群公网ip>:<上述端口>,如使用chrome出现的非私密链接提示,在当前页面静默输入"thisisunsafe"即可规避。
配置token
touch dashboard.yaml
vim dashboard.yaml
//键入如下内容
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
// 创建账号
kubectl apply -f dashboard.yaml
// 生成token
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')\
之后便可公网访问集群仪表盘,查看集群运行情况。
鲲鹏920服务器架构导致create失败
目前华为云服务器均为鲲鹏920纯armv8架构,只支持64位App,需要修改如下配置后再编译系统镜像(device/openvmi/arm64):
// 修改BoardConfig.mk:
#TARGET_2ND_ARCH := arm
#TARGET_2ND_ARCH_VARIANT := armv7-a-neon
#TARGET_2ND_CPU_VARIANT := cortex-a15
#TARGET_2ND_CPU_ABI := armeabi-v7a
#TARGET_2ND_CPU_ABI2 := armeabi
// 修改device.mk:
PRODUCT_COPY_FILES += system/core/rootdir/init.zygote64.rc:root/init.zygote64.rc
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote64
TARGET_SUPPORTS_32_BIT_APPS := false
TARGET_SUPPORTS_64_BIT_APPS := true
使用
相关脚本位于cloud-platform/tools/android-vm-manage.sh中,android虚拟机相关配置可自定义,根据服务器状况填写,默认是4核4G、720*1280,针对单机启动命令如下:
// 在当前服务器创建一台编号为1的虚拟机,create成功后会自动开机,不需要执行startup操作
./android-vm-manage create - 1
//其他命令自行查找
以上基本能完成openvmi搭建,读者可以在云手机使用指导中学习如何远端使用云手机,并效验成果。