在 Ubuntu 18.04 旧系统上部署新版 GitHub Actions Runner 的终极方案

实战记录:在 Ubuntu 18.04 旧系统上部署新版 GitHub Actions Runner 的终极方案

1. 背景与痛点

最近在为公司的嵌入式项目配置 CI/CD,遇到了一个极其棘手的"死锁"问题:

  1. 编译环境锁死 :项目依赖 Qt 5.10 和特定的交叉编译链 (aarch64-linux-gnu-g++),必须运行在 Ubuntu 18.04 (GLIBC 2.27) 环境下。
  2. Runner 强制更新 :GitHub Actions Runner 强制要求更新到 v2.330+ 版本,而新版 Runner 底层依赖 Node.js 20,必须要求 GLIBC 2.28+ (即 Ubuntu 20.04+)

矛盾点

  • 在宿主机直接装 Runner -> 报错 GLIBC_2.28 not found,无限重启。
  • 升级宿主机系统 -> 编译环境崩坏,项目跑不起来。
  • 在 Docker 里跑编译 -> 迁移复杂的交叉编译环境成本太高。

2. 最终架构设计:Docker + SSH "遥控"模式

为了同时满足"Runner 不崩"和"编译环境不变",我采用了一套分离式架构

  • 指挥官 (Runner) :运行在 Docker 容器 (Ubuntu 20.04) 中。负责与 GitHub 通信,满足 GLIBC 要求。
  • 执行者 (Host) :原本的 Ubuntu 18.04 宿主机。负责执行核心编译任务。
  • 通信:Runner 通过 SSH 免密登录连接宿主机,发送指令。

3. 踩坑与解决方案全记录

3.1 网络"第一难":解决连接被墙

现象
curl 下载报错 OpenSSL SSL_connect: SSL_ERROR_SYSCALLgit clone 报错 Connection closed

原因

公司防火墙/运营商阻断了 SSH (22端口) 和部分 GitHub IP。

解决方案

  1. 清理 DNS :检查 /etc/hosts,删除陈旧的 GitHub IP 绑定。

  2. SSH 走 HTTPS 通道 :修改 ~/.ssh/config,强制 SSH 走 443 端口:

    text 复制代码
    Host github.com
        Hostname ssh.github.com
        Port 443
        User git

3.2 启动 Runner:Docker 容器化

使用 myoung34/github-runner 镜像,彻底解决 GLIBC 版本问题。

关键配置

  • 使用 --net host 模式,方便连接宿主机。
  • 使用 --restart always 确保服务器重启后自动恢复。
  • 注意环境变量名:此镜像使用 REPO_URLRUNNER_TOKEN
bash 复制代码
sudo docker run -d --restart always --name cicd-runner \
  --net host \
  -e RUNNER_TOKEN="<GitHub_Registration_Token>" \
  -e REPO_URL="https://github.com/organization/repository" \
  -e RUNNER_LABELS="cicd-runner" \
  myoung34/github-runner:latest

3.3 打通任督二脉:配置 SSH 免密登录

为了让 Docker 容器能控制宿主机:

  1. 进入容器:docker exec -it cicd-runner bash
  2. 生成密钥:ssh-keygen -t rsa
  3. 授权 :将容器内的 id_rsa.pub 内容,追加到宿主机~/.ssh/authorized_keys 文件中。
  4. 测试:在容器内执行 ssh user@127.0.0.1 无需密码即可登录。

3.4 脚本化管理:告别臃肿的 YAML

为了避免在 YAML 的 ssh << EOF 块中写几十行复杂的逻辑,我将编译逻辑封装为 build.sh 脚本放入代码仓库。

流程优化

  1. YAML :负责 checkout 代码,将 build.sh 通过 scp 传送到宿主机的 /tmp 目录。
  2. SSH :远程执行 /tmp/build.sh,并透传 GitHub Secrets。
  3. Host :在宿主机执行实际的 qmakemake、AWS 上传等操作。

YAML 示例

yaml 复制代码
- name: Execute build.sh on Host
  run: |
    # 传送脚本
    scp -o StrictHostKeyChecking=no .github/scripts/build.sh user@127.0.0.1:/tmp/build.sh
    # 远程执行
    ssh -o StrictHostKeyChecking=no user@127.0.0.1 \
      "export AWS_KEY='${{ secrets.AWS_KEY }}' && /bin/bash /tmp/build.sh"

3.5 性能优化:解决内存溢出

现象

编译 QML 资源文件时报错:virtual memory exhausted: Cannot allocate memory

原因

宿主机内存仅 2GB,且 Swap 空间不足,多线程编译 (make -j) 瞬间撑爆内存。

解决方案

  1. 增加 Swap :创建 4GB 的 Swap 文件。

    bash 复制代码
    sudo fallocate -l 4G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    # 写入 /etc/fstab 实现开机挂载
  2. 限制并发 :在脚本中将 make -j$(nproc) 改为 make -j2(视情况而定)。


4. 总结

通过这套方案,我们达成以下目标:

  1. 兼容性:完美保留了 Ubuntu 18.04 的旧编译环境,无需重构项目。
  2. 稳定性:Runner 运行在官方推荐的 Ubuntu 20.04+ 容器中,永不因升级而崩溃。
  3. 自动化:利用 Docker 的自启特性,服务器重启后 CI/CD 自动恢复上线。
  4. 低成本:无需升级硬件,通过 Swap 优化解决了内存瓶颈。

这可能是目前解决 "旧系统开发环境 vs 新版 GitHub Actions" 冲突最优雅的解法。


Tags : DevOps, GitHub Actions, Docker, Ubuntu 18.04, CI/CD, Embedded Systems
Author: Tuo

相关推荐
杨云龙UP1 天前
Linux LVM 在线扩容标准操作流程_20260102
linux·运维·服务器·centos·ux
阿里嘎多学长1 天前
2026-01-02 GitHub 热点项目精选
开发语言·程序员·github·代码托管
warton881 天前
ubuntu24.04 安装mysql8.0.36
linux·运维·mysql
范纹杉想快点毕业1 天前
嵌入式通信核心架构:从状态机、环形队列到多协议融合
linux·运维·c语言·算法·设计模式
白驹过隙^^1 天前
VitrualBox及ubuntu系统安装
linux·运维·ubuntu
可爱又迷人的反派角色“yang”1 天前
k8s(一)
linux·运维·网络·云原生·容器·kubernetes
PoppyBu1 天前
Ubuntu20.04版本上安装最新版本的scrcpy工具
android·ubuntu
开源之眼1 天前
GitHub star和github Vue3 响应式选择指南:ref 与 reactive 加星该怎么用?
算法·github
可爱又迷人的反派角色“yang”1 天前
CICD持续集成Ruo-Yi项目
linux·运维·网络·ci/cd·docker·容器