Runner 在 CircleCI 控制台里显示在线,但生产任务仍然没有安全切换,甚至旧节点已经停止接单、新服务却没有成功启动。
最快解法:仍使用旧版 launch agent 的 macOS 构建节点应迁移到 Machine Runner 3,但必须先隔离试点、并行验证,再分批切换生产节点,并提前保留可执行的回滚路径。
00谁应该看这份验收清单
这篇文章适合维护 CircleCI macOS 自托管节点、准备淘汰旧版 launch agent 的平台工程负责人,也适合担心代码签名、私有网络访问和发布稳定性的企业 IT 负责人。
如果技术总监正在决定继续使用现有 Mac、增加隔离节点,还是采用可按需扩容的远程 Mac,这份清单可以作为迁移评审和生产准入的基础材料。
更新提醒: 本文最后更新于 2026 年 8 月 21 日,资料核实自 CircleCI 官方迁移指南、macOS 安装文档、配置参考、配置策略文档与 Runner changelog。正式执行前仍应重新核对官方页面,因为安装包、服务启动方式和配置行为可能继续变化。
01先划清迁移边界:配置兼容不等于生产行为兼容
CircleCI 官方迁移说明明确表示,Machine Runner 3 可以替代旧版 launch agent,macOS 迁移的基本路径是先卸载旧服务,再安装新 Runner;官方还说明原有配置文件具备 1:1 兼容性。具体步骤应以官方 macOS 迁移指南当前版本为准。
但“配置文件能被读取”只回答了语法和字段层面的问题,不能证明以下行为完全一致:
- 服务是否在正确的 LaunchAgent 域中启动;
- 执行用户是否仍然拥有 Xcode、钥匙串和私有网络访问权限;
- 任务是否被路由到预期的 resource class;
- 任务结束后代码、缓存和签名材料是否真正清理;
- Mac 重启、网络短暂中断或 Runner 进程退出后能否恢复接单;
- 回滚时是恢复旧服务,还是切换到备用节点。
因此,迁移对象不能只记录“Runner 名称”和“在线状态”。至少要建立以下最小盘点表:
| 盘点对象 | 必须记录的内容 | 不记录的后果 |
|---|---|---|
| 迁移节点 | Mac 型号、芯片架构、macOS、执行账号、节点用途 | 无法判断签名与工具链是否一致 |
| 依赖流水线 | iOS CI/CD、发布、测试、私有网络任务 | 切换后才发现关键流水线无法运行 |
| 任务路由 | namespace、resource class、允许项目 | 普通项目可能进入生产签名节点 |
| 凭证范围 | SSH key、临时 Keychain、Provisioning Profile | 无法证明跨任务隔离 |
| 回滚责任 | 负责人、备用节点、恢复命令、验证任务 | 故障时在生产机上临时拼接方案 |
企业应把迁移拆成“隔离试点节点”和“生产节点”两类,而不是在唯一的 Mac 打包服务器上直接覆盖安装。
02按服务残留排查启动冲突
旧版 launch agent 的服务文件、安装目录和运行进程如果没有完整清理,新旧 Runner 可能分别读取不同配置,或者同时尝试向同一个 resource class 领取任务。官方 macOS 迁移步骤包含停止服务、删除 plist 和移除旧安装目录的动作;实际命令应根据节点当前的安装路径和服务域调整。
迁移前应在维护窗口内完成以下核验:
- ✅ 检查
/Library/LaunchDaemons、/Library/LaunchAgents与用户目录下是否存在旧 Runner plist; - ✅ 检查是否仍有旧的
circleci-launch-agent或同类进程; - ✅ 记录旧安装目录、配置文件路径和日志路径;
- ✅ 停止旧服务后再次确认进程已经退出;
- ✅ 不在同一节点上临时保留两套自动启动方式;
- ✅ 失败时明确是恢复旧服务,还是把流水线切到备用 Mac。
安装新 Runner 时,官方 macOS 安装文档采用 Homebrew 方式,并要求配置 Runner 名称与认证令牌。安装包来源、安装日志和二进制校验结果应纳入变更记录,而不是只保留一条“brew install 成功”的终端输出。安装完成后,可按官方 macOS 安装指南核对二进制签名、notarization 和 launchctl 服务状态。
| 验收项目 | 通过条件 | 失败时的处理 |
|---|---|---|
| 旧 plist | 已停止并删除,且没有重复副本 | 暂停安装,先清理旧服务 |
| 旧进程 | 迁移后不存在旧 Runner 进程 | 终止进程并重新检查启动项 |
| 新二进制 | 来源、版本、安装日志可追溯 | 禁止使用临时下载文件覆盖 |
| 签名状态 | spctl 显示已接受并通过 notarization |
按官方安装说明处理系统授权 |
| 服务启动 | 运行域、执行用户和配置路径明确 | 不要只依赖控制台在线状态 |
官方安装说明提供了 spctl -a -vvv -t install 用于检查签名与 notarization 状态。这个检查只能证明二进制获得系统认可,不能证明任务运行权限、钥匙串访问或项目路由正确。
03逐项验证配置语义,而不是只复制 config.yaml
旧配置文件可以作为 Machine Runner 3 的迁移输入,但迁移验收仍应逐项对照Machine Runner 3 配置参考。重点不是把字段重新抄一遍,而是确认每个字段在企业节点上的实际后果。
需要重点检查的字段和假设包括:
working_directory是否位于专用磁盘或专用用户目录,权限是否只授予 Runner 执行账号;cleanup_working_directory是否启用,并在任务成功、失败、取消三种状态下都执行;command_prefix是否改变了任务执行用户,尤其要确认它是否影响钥匙串、Xcode 工具链和私有网络客户端;- 任务最长运行时间是否设置,超时后是否会留下子进程、临时文件或锁;
task-agent缓存是否可能保留旧平台或旧版本行为;- 配置中的绝对路径、环境变量和日志路径是否仍适用于新安装方式;
- 认证令牌是否只存在于配置文件或受控密钥存储中。
Machine Runner 3 的任务配置至少要明确 machine: true 和目标 resource_class,否则任务可能不会进入预期的自托管 Mac 节点。
基准任务应避免直接使用生产凭证,建议只验证以下链路:
- checkout 私有测试仓库;
- 打印 macOS、芯片架构和 Xcode 版本;
- 执行一个不会发布的构建或单元测试;
- 检查日志是否完整回传;
- 检查退出码是否准确;
- 上传一个无敏感信息的测试产物;
- 结束后检查工作目录是否清空。
这一步可以尽早发现“服务在线但任务无法运行”的问题,例如执行账号不同、路径不存在、Xcode 许可未接受、钥匙串不可访问,或任务实际被发送到了错误的 resource class。
04收紧任务路由与 Runner 权限
CircleCI 的 resource class 既用于识别自托管 Runner 池,也用于把任务路由到对应节点。迁移试点时,建议为新节点创建独立的 resource class,而不是直接复用生产节点的标签。这样可以把验证任务限制在试点 Mac 上,避免新旧节点同时处理同一类发布任务。
CircleCI 的配置参考说明,如果没有显式设置 resource_class,平台可能使用默认值,而默认值可能发生变化。因此,迁移验收应把资源类写入项目配置并纳入代码审查,而不是依赖隐含默认行为。
路由验收至少应包括三组结果:
| 测试类型 | 期望结果 | 证据 |
|---|---|---|
| 允许项目 | 可信 iOS CI/CD 项目能领取任务 | 项目 ID、resource class、任务日志 |
| 拒绝项目 | 未授权项目无法调用该 Mac resource class | 配置策略结果或拒绝记录 |
| 错误标签 | 使用错误 resource class 的任务不进入试点节点 | 任务路由和 Runner 日志 |
如果组织使用配置策略,应限制哪些项目可以调用指定的自托管 resource class。可参考CircleCI 自托管 Runner 配置策略文档按项目 ID 区分生产发布流水线与普通测试任务,避免非可信项目进入承载签名凭证的 Mac。
认证令牌不能进入代码仓库、共享脚本、构建日志或可被普通项目读取的环境变量。令牌只用于 Runner 领取与执行任务,权限边界仍取决于节点执行用户本身;执行账号拥有过宽的本地权限时,单独保护令牌并不能完成隔离。
05用交叉测试证明工作区和签名材料能清理
对于 iOS CI/CD 节点,最容易被低估的风险不是构建失败,而是上一个任务留下的代码、环境变量或签名文件被下一个任务读取。
cleanup_working_directory: true 是必要条件,但不能单独作为隔离证明。企业还应检查:
- Git checkout 目录与隐藏文件;
- Swift Package、CocoaPods 或其他依赖缓存;
- SSH checkout key;
- 临时 Keychain 及其解锁状态;
- Provisioning Profile、证书和导出的构建产物;
TMPDIR、用户目录和脚本自行创建的临时目录;- 任务失败或被取消后仍在运行的子进程。
建议准备两个互不信任的测试项目。项目 A 在任务中写入唯一标记、环境变量、临时签名材料和测试代码;任务完成后,项目 B 尝试扫描工作目录、缓存、钥匙串和常见临时路径。如果项目 B 能读取项目 A 的任何敏感内容,节点不能进入生产发布池。
生产签名节点应优先采用专用运行账号和专用 resource class,不要把普通测试项目与生产签名任务放在同一个信任域。若必须共享 Mac,应至少在组织策略、项目白名单、执行用户和任务结束清理四个层面同时设限。
06通过重启、故障和回滚测试后再放量
macOS 节点在控制台显示在线,只能说明某个时间点的 Runner 注册状态正常。真正的生产验收要证明节点经历重启、进程异常退出、网络短时中断和任务超时后,仍然能够恢复接单,并且不会触发重复发布。
macOS 安装文档区分了 GUI 和非 GUI 会话的服务启动方式,并使用 launchctl bootstrap、enable、kickstart 和 print 检查服务状态。远程或无图形界面的构建机应特别验证 user 域服务,不能只在人工登录的 GUI 会话里测试。
建议按以下顺序执行最小故障测试:
- 远程重启 Mac,确认系统恢复后 Runner 自动启动;
- 检查服务是否进入正确的 user 或 GUI 域;
- 运行一条无发布动作的基准流水线;
- 手动终止 Runner 进程,确认服务能否拉起;
- 短暂阻断网络,再恢复网络并观察接单状态;
- 让测试任务超时,检查子进程、工作目录和签名材料;
- 在任务执行期间重启或切换备用节点,确认不会产生重复发布;
- 执行回滚,验证旧服务或备用节点确实能够接管任务。
截至 2026 年 8 月 21 日,CircleCI 官方 changelog 显示 Runner 3.1.11 于 2026 年 7 月 29 日发布,3.1.10 曾修复缓存 task-agent 可能导致任务出现“不支持平台”错误、需要重启进程才能恢复的问题。版本信息和已知修复应在迁移变更单中留档,不能只写“安装最新版”。相关版本变更应以CircleCI Runner 官方 changelog为最终核对依据。
| 故障场景 | 需要观察的指标 | 放量判断 |
|---|---|---|
| Mac 重启 | 服务自动启动、Runner 重新注册、任务可领取 | 任一环节失败则限制放量 |
| Runner 进程退出 | 自动恢复、无重复任务、日志连续 | 无恢复机制则保留备用节点 |
| 网络短断 | 恢复接单、任务状态明确 | 状态不确定时禁止承载发布 |
| 任务超时 | 子进程退出、工作区清理、凭证失效 | 有残留则退回整改 |
| 回滚 | 旧服务或备用节点可独立接管 | 回滚依赖人工临时操作则不准入 |
迁移验收决策条件
- 若服务残留已清理、试点 resource class 路由正确、两个测试项目无法交叉读取代码和签名材料,且重启后能自动接单,则进入小批量生产切换。
- 若任务能够成功构建,但凭证清理、执行用户或重启恢复仍没有证据,则只保留在隔离试点,不得承载生产发布。
- 若新 Runner 无法稳定启动,或回滚必须在唯一生产 Mac 上临时修改多套启动方式,则立即停止迁移,切回备用节点或恢复旧服务。
- 若生产节点队列持续积压,但单节点构建结果稳定,则优先增加隔离的 Mac Runner 容量,而不是提高同一节点的权限范围或并发风险。
- 若团队无法提供专用签名账号、项目白名单和任务清理证据,则不应把通用共享 Mac 作为生产签名节点。
对于需要先建立隔离试点的团队,可先了解 NUKCLOUD 的远程 Mac 使用方式,再根据团队所在区域查看远程 Mac 节点选项。这里的重点不是替代现有生产架构,而是为迁移提供一台不影响主流水线的验证节点。
07用一张验收卡决定“通过、限量或回退”
最终验收记录不应只有“Runner Online”截图,而应保存以下证据:
- [ ] 旧 launch agent 服务、plist、进程和安装目录已核查;
- [ ] 新二进制来源、版本、安装日志和签名状态可追溯;
- [ ]
config.yaml的路径、执行用户、清理策略和任务超时已逐项复核; - [ ] 试点 resource class 只允许指定项目调用;
- [ ] 认证令牌没有出现在仓库、脚本和构建日志;
- [ ] 两个隔离项目交叉读取测试未发现代码或凭证残留;
- [ ] checkout、构建、日志、退出码和产物回传全部通过;
- [ ] Mac 重启后 Runner 自动恢复;
- [ ] Runner 进程退出、网络短断和任务超时均有处理结果;
- [ ] 回滚责任人、备用节点和恢复命令已经演练;
- [ ] 真实基准流水线的排队、成功率、失败原因和人工恢复动作已记录。
结论可以分为三档:
| 验收结论 | 适用条件 | 后续动作 |
|---|---|---|
| 通过 | 核心功能、隔离、恢复和回滚证据齐全 | 分批切换生产节点 |
| 限制放量 | 构建可用,但容量或恢复证据不足 | 仅承载非关键任务并补测 |
| 退回整改 | 服务冲突、凭证残留、错误路由或回滚失败 | 停止迁移,恢复备用路径 |
企业不应为了追求一次性完成而牺牲回滚能力。固定生产节点适合稳定、低变化的发布流水线;当团队需要同时验证多个 Xcode 工具链、临时增加 iOS CI/CD 容量,或不希望改造唯一的 Mac 打包机时,隔离的远程 Mac 可以作为迁移试点和弹性补充,而不是直接替代所有长期基础设施。
08常见问题
CircleCI launch agent 迁移到 Machine Runner 3,最小操作路径是什么?
最小路径是:盘点旧节点与依赖流水线,停止并删除旧 launch agent 服务,安装 Machine Runner 3,迁移配置文件,核验签名与 notarization,使用独立 resource class 运行无生产凭证的基准任务,最后执行重启、清理和回滚测试。官方迁移页给出了 macOS 的服务卸载路径,但企业仍需补充权限和安全验收。
为什么 Machine Runner 3 重启后没有自动接单?
常见原因包括 plist 放置位置与运行域不匹配、服务只在人工登录的 GUI 会话中启动、执行用户无法读取配置文件,或启动后无法访问工作目录和网络。应使用 launchctl print 检查实际服务域,再验证配置路径、执行账号和网络访问,而不是只刷新控制台页面。
原有 config.yaml 直接复制后,为什么任务仍可能失败?
配置文件 1:1 兼容主要表示字段可以作为迁移输入,并不保证路径、用户、权限、日志行为和钥匙串环境一致。旧配置中的工作目录可能指向已删除路径,旧的 logging 配置也可能不适用于新 Runner;因此必须用基准任务验证 checkout、构建、日志、退出码和产物回传。
怎样验证自托管 Mac Runner 没有残留代码和签名凭证?
不能只检查任务结束时的工作目录。应使用两个隔离测试项目交叉验证代码目录、缓存、SSH checkout key、临时 Keychain、Provisioning Profile、环境变量和构建产物,并覆盖成功、失败、取消和超时场景。对生产签名节点,还应限制项目白名单并采用专用运行账号。
09验收通过后,如何选择长期节点方案
如果现有方案是把唯一的物理 Mac 直接改造成 Machine Runner 3,它的真实缺点通常是:迁移期间没有隔离试点,重启和回滚依赖人工操作;固定设备容量无法快速应对发布高峰;硬件故障、系统升级和签名环境维护会直接影响团队流水线;普通测试项目与生产签名任务也容易被放进同一信任域。
因此,更稳妥的做法是先租赁一台与生产节点隔离的远程 Mac,完成真实流水线、重启恢复、凭证清理和任务路由验证;通过验收后,再依据队列长度、发布 SLA 和签名隔离要求决定长期节点数量。对于需要临时算力、迁移试点或弹性补充的团队,NUKCLOUD 的远程 Mac 可以作为不改动唯一生产构建机的验证入口;如果团队需要长期满负载运行、物理接口或完全自主管理硬件,自购 Mac 仍可能更合适。