Buildkite macOS Hosted Agent 的 M4 Medium 形状为 6 vCPU、28 GB 内存,按官方 Pro 计划费率计算为每分钟 0.12 美元。这意味着:标准镜像、短时验证和波动负载优先使用托管 Agent;固定 Xcode、私网依赖、生产签名、主机级控制或长时间任务,则应使用自托管 Mac。对多数企业而言,最稳妥的 Buildkite macOS Agent 选型不是二选一,而是建立托管验证队列与自托管生产队列。(Buildkite macOS Hosted Agents 官方文档)
这篇文章适合三类读者:已经采用 Buildkite、需要补充 iOS 或 macOS 构建资源的平台团队;正在比较托管计算与自托管 Mac 完整 TCO 的企业 IT 和采购负责人;需要隔离生产签名、内部依赖与非可信代码的安全及发布负责人。
00先用任务分流矩阵确定队列边界
Buildkite 的控制面是 SaaS 平台,真正执行任务的是 Agent;Agent 又运行在托管 Mac 或企业管理的真实 Mac 上。不要把这三个层次混为一谈:平台负责调度与日志,托管 Agent 的机器生命周期由 Buildkite 管理,自托管 Agent 的主机、网络和恢复责任则留在企业一侧。(Buildkite Agent 架构说明)
| 工作负载 | 首选队列 | 原因 | 不宜共享的资源 |
|---|---|---|---|
| PR 编译与基础单元测试 | 托管 macOS 队列 | 任务短、环境标准化、负载波动明显 | 生产签名证书、长期有效凭证 |
| 模拟器测试 | 托管或专用自托管队列 | 需要匹配 Xcode、系统和 Simulator 组合 | 生产发布钥匙串 |
| 正式归档与 App Store 发布 | 自托管 Mac | 需要固定工具链、审计边界和更强控制 | 非可信分支和外部贡献代码 |
| 企业内网 API、私有制品库依赖 | 自托管 Mac | 节点可放入受控网络或使用企业代理 | 公共验证任务 |
| 长时间构建、专用工具链任务 | 自托管 Mac | 避免托管 Agent 的任务时长边界和镜像限制 | 通用弹性任务 |
| 发布高峰、临时分支和大规模验证 | 托管 macOS 队列 | 可以按需增加容量,减少长期空闲资源 | 生产凭证与内部网络入口 |
Buildkite 的队列机制支持将任务路由到不同类型的 Agent,队列可以按机器类型、架构、规模和用途拆分;托管队列与自托管队列是两类不同队列,不能把它们当成同一个混合资源池使用。流水线应通过 agents 属性将步骤明确指向目标队列。(Buildkite 队列管理文档)
因此,团队不应只创建一个名为 macos 的通用队列。更可审计的做法是至少拆成 macos-hosted-verify 与 macos-self-hosted-production,再根据是否需要内网、签名和特定 Xcode 版本继续细分。
01再按环境控制能力核查托管边界
托管 Agent 的优势是预置环境和自动生命周期。当前官方 macOS Hosted Agent 文档列出的 M4 Medium 为 6 vCPU、28 GB 内存、182 GB 磁盘,M4 Large 为 12 vCPU、56 GB 内存、294 GB 磁盘;这些规格适合按照任务规模选择队列,而不是把所有任务都压到同一种实例形状上。(Buildkite macOS 实例规格与队列)
托管队列还提供按 macOS 版本固定的队列,例如 macos-14-medium、macos-15-medium、macos-26-medium 和 macos-27-medium,分别对应官方页面列出的 Sonoma、Sequoia、Tahoe 与 Golden Gate 队列。版本化队列解决的是基础系统选择问题,并不等于企业可以永久冻结全部依赖。
需要重点核查以下边界:
- 是否能使用项目要求的 Xcode 与 Simulator 组合;
- 是否依赖自定义基础镜像,而托管 macOS 当前不能像 Linux Hosted Agent 那样提供自定义基础镜像;
- 是否需要 Agent hooks、系统级守护进程、特殊 Homebrew 包或专用证书安装流程;
- 是否要求构建结束后保留特定状态,还是每个任务都必须从干净环境开始;
- 是否需要长期保存 DerivedData、Swift Package 缓存或大型二进制依赖。
Apple 的系统要求显示,Xcode 26 需要 macOS Sequoia 15.6 或更高版本;因此,不能只看“队列支持 macOS”,还要把 Xcode、macOS、SDK 和项目最低部署目标作为一个兼容矩阵维护。(Apple Xcode 26 系统要求)
自托管 Mac 的控制能力更强,但维护责任也完全不同。企业可以固定系统版本、Xcode、Ruby、CocoaPods、Swift Package 缓存和内部工具,但必须自行管理升级验证,否则固定环境会逐渐变成无法修复的旧环境。
⚠️ 注意:能够选择系统版本,不等于能够长期冻结全部依赖。每次 Xcode、macOS、签名工具或插件升级,都应在独立队列完成回归,再变更生产队列的镜像和工具链。
02接着划清代码、签名与网络信任边界
对 iOS CI/CD 来说,真正危险的并不是“构建失败”,而是非可信代码获得了生产签名、内网访问或长期缓存中的敏感材料。PR 验证、外部贡献分支和正式发布任务必须使用不同的权限模型,最好也不要进入同一个队列。
| 信任等级 | 典型任务 | 节点选择 | 凭证与网络要求 |
|---|---|---|---|
| 低信任 | 外部 PR、依赖变更验证 | 托管队列 | 不挂载生产钥匙串,限制出站访问和缓存范围 |
| 中信任 | 内部 PR、模拟器回归 | 托管或专用自托管 | 使用短期凭证,限制私有制品访问 |
| 高信任 | 生产归档、签名、发布 | 隔离自托管 Mac | 专用 Agent token、独立钥匙串、审计日志和人工批准 |
| 内网依赖 | 私有 API、内部包、企业服务测试 | 自托管 Mac | 代理、私有 DNS、出站白名单和网络分区 |
自托管 Agent 需要通过 Agent token 注册到集群和队列;官方文档建议为不同环境创建专用 token,并使用密钥管理系统保存和轮换,而不是把长期 token 直接写入脚本或仓库。(Buildkite 自托管 Agent token 文档)
企业还应把以下动作纳入上线门槛:
- ✅ 为验证、预发布和生产分别建立队列与 token;
- ✅ 对非可信分支强制干净检出,避免复用上一次任务留下的工作区;
- ✅ 通过插件白名单限制可执行的第三方步骤;
- ✅ 对签名证书、API Key、App Store 凭证设置最小权限和短期有效期;
- ✅ 将内网访问限制在必要域名、端口和代理出口;
- ❌ 不让通用验证 Agent 读取生产钥匙串;
- ❌ 不因“节点在线”就默认它已经具备生产签名能力。
托管 Agent 的环境是任务级临时资源,官方说明其任务结束后会销毁;同时,托管 macOS Agent 支持运行中的终端访问,部分组织还可使用浏览器桌面访问进行 UI 测试排查,访问凭证为按需生成的短期 token。
如果自托管 Mac 需要接入企业内网,建议只开放必要的出站路径,而不是把构建节点放入整个办公网络。常见设计是由节点访问内部代理、私有 DNS、制品仓库和必要 API,同时用防火墙规则限制横向访问;生产签名节点与普通验证节点还应使用不同的钥匙串和网络策略。
03然后用排队、时长与恢复能力评估吞吐
单次构建更快,不等于整个团队吞吐更高。企业应同时观察排队时间、Agent 启动时间、缓存命中率、任务失败率、重试次数和发布窗口内的峰值并发。
托管 macOS 实例目前官方说明单个实例可运行最长 4 小时;如果存在超过该边界的任务,应先确认支持条件,不能直接把长时间归档、端到端 UI 测试或大型依赖构建放入托管队列。(Buildkite Hosted Agent 任务限制说明)
托管容量的并发还受到套餐的 M4 Mac vCPU 总量约束。以官方示例为例,若队列可用总量为 24 vCPU,使用 6 vCPU 的 M4 Medium,理论并发就是 4 个 Agent;超过容量的任务会排队。实际排队还会受到启动和短任务计量方式影响,因此不能只用流水线平均耗时推导容量。
自托管 Mac 的验收重点则是故障恢复,而不是单次跑分:
- 断电或系统更新后是否能无人值守启动 Agent;
- Agent 失联后是否能自动告警、远程重启或切换备用节点;
- 节点被占用、磁盘不足、钥匙串锁定时,流水线是否能明确失败;
- 是否存在替代容量,避免一台 Mac 成为发布单点;
- 代理、DNS、证书过期后,是否有可审计的恢复记录。
Buildkite 官方文档还说明,自托管 Agent 默认通过轮询获取任务,较新的 Agent 版本可使用 Streaming Job Dispatch 维持持久连接,以降低接单延迟。若团队把排队时间作为发布 SLO,应将 Agent 版本、网络路径和接单方式写入验收记录,而不是只看构建脚本。(Buildkite Job Dispatch 文档)
04最后按完整 TCO 计算,而不是只看分钟费率
托管方案的月度成本可以先用变量表达:
托管 TCO = Buildkite 平台套餐 + Σ(各 Mac 队列实际 vCPU 分钟 × 对应费率)+ 超出额度的缓存、存储或网络成本
官方 Pro 计划当前列出的 Mac Hosted Agent 费率为 0.02 美元/vCPU 分钟,因此 M4 Medium 的有效费率为 0.12 美元/分钟,M4 Large 为 0.24 美元/分钟。这些是写作核查时的官方价格,采购前仍应以实际账单和套餐页面为准。(Buildkite 官方定价页面)
自托管方案不能只拿 Mac 月租与上述分钟费率比较,应使用:
自托管 TCO = Mac 资源周期 + Buildkite 平台费用 + 存储与网络 + 环境维护 + 升级验证 + 空闲容量 + 故障损失 + 运维人员时间
| 负载类型 | 托管方案的成本特征 | 自托管方案的成本特征 | 边界判断 |
|---|---|---|---|
| 固定、低波动负载 | 按分钟计费,但长期累计 | 主机长期在线,空闲成本较高 | 需要用真实月度分钟数回算 |
| 波动负载 | 峰值时增加使用费和排队风险 | 需要预留容量,否则高峰排队 | 波动越大,弹性价值越高 |
| 长时间任务 | 受任务时长和实例生命周期约束 | 主机可持续运行,但维护责任增加 | 长任务优先验证自托管 |
| 生产签名 | 需要额外核查凭证与隔离能力 | 可建立专用钥匙串和审计边界 | 安全要求通常比价格更优先 |
| 私网依赖 | 需要确认网络接入边界 | 可放入企业代理或受控网络 | 私网任务通常倾向自托管 |
NUKCLOUD 的远程 Mac 更适合被纳入“自托管 Mac 资源池”的预算模型,而不是被误当成托管 Agent。企业应分别核算租赁周期、所需节点数量、远程访问方式、恢复流程和运维时间;如需查看可用的 NUKCLOUD 远程 Mac 方案,建议先按生产基线、备用容量和临时扩容拆分需求,再进行采购比较。
05用双跑试点决定最终架构
建议以同一组真实项目任务完成双跑,而不是拿演示流水线作结论。试点至少包含:
- 选择一个普通 PR 构建、一个模拟器测试、一个正式归档任务。
- 为托管验证队列和自托管生产队列分别配置明确的
queue标签。 - 记录排队时间、Agent 启动时间、构建时长、失败重试和缓存命中。
- 使用不含生产凭证的低信任任务验证托管队列。
- 在隔离的自托管 Mac 上验证签名、私网访问和内部制品下载。
- 模拟节点失联、磁盘不足、Agent token 轮换和远程重启。
- 将真实分钟账单、Mac 租赁或资源成本、运维工时和故障损失放入同一张 TCO 表。
最终可以按以下条件决策:
- 继续使用托管 Agent:任务主要是标准镜像、短时验证和波动负载;Xcode 组合在可用队列内;排队和并发满足发布 SLO;不存在生产签名或私网硬依赖。
- 转向自托管 Mac:需要固定 Xcode 和工具链;任务超过托管时长边界;必须访问企业内网;生产签名要求节点隔离;团队能够承担无人值守启动、升级和恢复责任。
- 采用双队列混合部署:PR 与模拟器任务具有明显峰值,而生产归档、签名和内部依赖需要长期受控基线。这通常是企业在安全、弹性与预算之间最容易审计的平衡点。
06企业决策 FAQ
Buildkite macOS Hosted Agent 与自托管 Agent 的核心差异是什么?
Hosted Agent 由 Buildkite 负责 Mac 主机、镜像、扩容和生命周期,适合标准化、短时和波动任务;自托管 Agent 运行在企业或指定基础设施上,企业需要负责主机、Agent token、网络、升级、清理和故障恢复,但可以固定 Xcode、安装专用工具并接入私有网络。
iOS 项目在 Buildkite 中怎样选择构建节点?
PR 验证、常规模拟器测试和突发构建通常先放入托管队列;正式归档、生产签名、固定 Xcode 版本、内部依赖和长时间任务更适合自托管 Mac。多数企业不应把所有任务放进同一池,而应使用托管验证队列加隔离的自托管生产队列。
自托管 macOS Agent 接入企业私网时要检查哪些项目?
先在 Buildkite 中创建独立的自托管队列和专用 Agent token,再让 Mac 节点通过企业允许的出站路径连接 Buildkite。内网依赖应通过代理、私有 DNS、制品仓库或受控网络出口提供,并用插件白名单、干净检出和凭证隔离限制流水线权限。
如何把托管 Mac 与自托管 Mac 放进同一张 TCO 表?
托管方案应按 Agent 使用分钟、vCPU 形状、平台套餐、缓存和并发额度计算;自托管方案则要加入 Mac 资源周期、Buildkite 平台费用、存储、网络、维护、升级验证、空闲容量、故障损失和人员时间。不要只比较主机月租,应使用真实构建分钟和排队记录回算。
如果当前方案把 PR 验证、模拟器测试和生产签名全部压在同一类 Mac 上,常见问题通常不是某台机器性能不足,而是队列边界、凭证隔离和峰值容量没有拆开:固定节点会产生空闲成本,托管队列又可能受版本、并发和任务时长限制。对于需要长期在线、可远程恢复并承担自托管 Agent 的团队,使用 NUKCLOUD 的远程 Mac 作为受控生产基线,再把弹性验证留给托管 Agent,往往比单纯增加本地采购更容易按月调整容量;可先参考 NUKCLOUD 远程 Mac 的交付与节点方案,再用真实构建记录决定是否扩容。