如何在无root权限的Gitlab SaaS或GCP自动化CI/CD流水线中模拟armhf(arm32v7)架构
我完全懂你的痛点——之前在自己的物理CI runner上,靠底层QEMU配合binfmt配置,就能无缝跑armhf容器,全程用原生构建配置,根本不用折腾交叉编译那一套。现在要迁到Gitlab SaaS或者GCP,没法碰系统级的root配置,确实有点棘手。下面给你分两种场景说可行的解决方案:
Gitlab SaaS 方案(优先选项)
Gitlab的共享Runner其实已经预装了qemu-arm-static静态二进制文件,咱们不用root权限去配置binfmt,直接把这个静态文件复制到工作容器里,就能直接运行armhf的容器或者二进制了。
举个实际的CI配置例子,用Docker-in-Docker(DIND)来跑armhf构建:
armhf-build-job: image: docker:24.0.6 services: - docker:dind script: # 先从Runner宿主机复制qemu-arm-static到当前容器的/usr/bin目录 - cp /usr/bin/qemu-arm-static /usr/bin/ # 直接拉取arm32v7的Ubuntu镜像,运行你的构建命令 - docker run --rm arm32v7/ubuntu:20.04 /bin/bash -c " apt update && apt install -y build-essential && # 这里替换成你实际的构建、测试命令 make && make test "
这种方式不需要任何root权限操作,完全利用Gitlab共享Runner自带的资源,就能模拟出armhf的原生运行环境。
GCP 方案(两种子场景)
场景1:自己在GCP上部署Gitlab Runner
如果是自己搭建Gitlab Runner,那你可以自定义Runner的镜像,提前把QEMU和binfmt配置好,这样Runner启动后就自带armhf模拟能力了。
比如写一个自定义Runner的Dockerfile:
FROM gitlab/gitlab-runner:alpine-v16.0.0 # 安装qemu-arm-static RUN apk add --no-cache qemu-arm-static # 添加启动脚本,在Runner启动时配置binfmt COPY runner-start.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/runner-start.sh ENTRYPOINT ["/usr/local/bin/runner-start.sh"]
然后写runner-start.sh脚本:
#!/bin/sh # 重置并注册qemu-arm的binfmt规则 echo -1 > /proc/sys/fs/binfmt_misc/qemu-arm 2>/dev/null || true echo ':qemu-arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:OCF' > /proc/sys/fs/binfmt_misc/register # 启动Gitlab Runner原有的入口命令 exec /usr/bin/dumb-init /entrypoint run "$@"
构建这个镜像后,在GCP上用特权模式(需要特权才能修改/proc下的binfmt)部署Runner,之后你的CI任务就能和原来物理机上一样,直接运行armhf容器了。
场景2:使用GCP Cloud Build
和Gitlab SaaS的思路类似,你可以在构建步骤中引入qemu-arm-static。比如在Cloud Build的cloudbuild.yaml里:
steps: - name: 'docker:24.0.6' entrypoint: 'bash' args: - '-c' - | cp /usr/bin/qemu-arm-static /usr/bin/ docker run --rm arm32v7/debian:11 /bin/bash -c " apt-get update && apt-get install -y build-essential && # 执行你的构建命令 make all "
Cloud Build的默认镜像里也预装了qemu静态二进制,直接复制使用即可。
小提醒
模拟架构的性能肯定不如原生arm实例,如果你的构建任务量很大,也可以考虑直接在GCP上创建arm32v7的实例作为Runner,这样完全不用模拟,性能更优——不过这就需要调整你的基础设施配置了,看你需求权衡。
备注:内容来源于stack exchange,提问作者Claudio

