结论|适合:先用团队 CI 记录估算 Mac 打包机数量,再用代表性负载验证;不要按开发者人数直接换算。负载持续且稳定时配置固定容量,短时峰值再评估弹性补充。
正在从零规划 iOS CI/CD 容量的技术负责人,可用本文建立估算流程。
现有 runner 经常排队的 IT 管理者,可用队列与构建记录判断是否真的需要扩容。
比较固定采购与弹性算力的采购决策者,可据此整理成本核算所需数据。
先从 CI 运行记录还原真实负载
先别急着数团队有多少开发者。开发者人数不能说明每个人触发构建的频率,也不能反映任务是否集中在代码合并、发布窗口或特定测试矩阵;相同人数的团队,可能因此出现完全不同的排队压力。
容量规划也不等于估算每日构建总数。你需要知道任务何时进入队列、何时开始和结束,以及任务为何重试:只看平均时长,会掩盖高峰时段多个任务同时到达的情况;只看总运行时长,则分不清 runner 忙碌与任务在等候。
Apple 对 Xcode CI 工作流的说明包含构建、测试、分析和归档等动作;其 CI 文档也提到可在既有流水线中使用 xcodebuild。因此,整理记录时要把不同类型的任务分开,而不是把每次 workflow 都当成同一种构建。Apple 的 Xcode 工作流动作说明和在 CI 工作流中构建 Swift 包或相关应用提供了工作流环节的依据。
| 记录字段 | 要区分或保留什么 | 对容量判断的用途 |
|---|---|---|
| 触发时间与任务类型 | PR 检查、主分支构建、测试、归档 | 找出高峰时段与耗时较长的任务类别 |
| 入队、开始、结束时间 | 队列等待时长与实际执行时长分别记录 | 判断瓶颈发生在等 runner,还是 runner 执行 |
| 结果与重试信息 | 成功、失败、取消、重试及重试触发原因 | 识别重试是否制造额外任务、放大高峰 |
| 项目与运行配置 | 仓库、分支、Xcode 版本、测试目标或矩阵 | 避免把不同负载混在一起比较 |
注意,执行时间不等于机器繁忙时间的完整解释。依赖解析、脚本和归档都会进入工作流;缓存冷启动、外部依赖等待或失败重试也可能改变耗时。Apple 的 Xcode Cloud 文档列出了工作流中的准备与执行环节,但这是该平台的说明,不能直接当作你当前 CI 环境的耗时估计。Xcode Cloud 工作流参考可帮助你核对动作范围;实际负载仍应以自己的运行日志为准。
需求估算:按峰值并发和可接受排队时间判断
iOS 团队怎么估算需要几台 Mac 打包机?
把问题拆成三项:任务在高峰期的到达节奏、各类任务的实际执行时长,以及业务能够接受的排队等待。再按日常工作日、发布窗口和其他明显不同的运行时段分别看记录;不要用一个全时段平均值替代峰值观察。
实操时,先选定团队自己的观察窗口,并确认日志完整覆盖了具有代表性的开发和发布活动。按任务类型分组后,统计每个时段有多少任务等待、正在执行、完成或失败;再结合排队等待的变化,判断现有 runner 是否跟得上到达节奏。观察窗口怎么选取决于团队发布安排和日志质量,不存在适用于所有 iOS 团队的固定长度。
接着由业务方明确反馈等待的可接受范围,而不是从所谓通用行业阈值抄一个数字。例如,PR 检查和非紧急的定时任务,未必应采用相同的等待目标;但具体目标应由你的团队协作约定确定。若高峰队列持续超过这项目标,才把容量不足列为待验证的假设,同时排查慢任务、重复触发和不必要的串行限制。
打包机数量应该按开发者人数还是构建并发估算?
应根据构建并发和可接受排队时间估算,再用代表性运行验证;开发者人数只能作为理解团队规模的背景信息,不能直接换算成 runner 数量。若任务到达时间错开、执行时间短,即使人数增加,峰值占用也未必同步增加;反过来,测试矩阵或发布任务集中触发,也可能让较小团队在短时间内出现队列。
这里要避免把一次观测到的峰值直接当成长期固定需求。分别记录持续存在的占用和短时尖峰:前者用于评估常驻容量,后者用于考虑任务调度、错峰或弹性扩容。若失败重试占据不少执行资源,应先确认失败原因;盲目增加 runner 可能只是让更多重复任务同时运行。
映射与验证:Mac runner 是否真能承接任务
估算出的并行任务数,不能机械地等同于 Mac 主机数量。映射时要核查 CI 平台的 runner 调度方式、并发限制、标签或分组匹配、仓库访问权限,以及单台 Mac 是否确实按你预期只承接相应工作负载。一个任务被限制在某个并发组,或因标签、权限无法匹配 runner,即使增加机器也可能不会消除排队。
若你使用 GitHub Actions,可参考其关于自托管 runner 的管理说明:runner 可按仓库、组织或企业层级使用,平台也提醒自托管 runner 的系统与软件维护由使用方负责。工作流并发规则同样需要单独检查;例如,该平台的 concurrency 设置可以对同一并发组的任务进行排队或取消处理,不能把这种平台调度行为误判为 Mac 算力不足。GitHub Actions 工作流语法文档是这里的配置依据。其他 CI 平台可能采用不同的调度与并发规则,不能直接照搬。
这些文档还给出几个平台限制示例,但它们不是 Mac 容量建议:GitHub Actions 的并发组使用 queue: max 时,最多允许 100 个任务处于等待状态;工作流矩阵最多生成 256 个任务。这些数字描述平台行为,不代表你应该配置相应数量的 Mac runner。
验证前,先把需求假设和团队服务目标写清楚,再选一组有代表性的 PR 检查、测试或归档任务做小规模试运行:
- 确认 runner 标签、分组和仓库访问权限,让目标任务确实能被预期的 Mac 接收。
- 选择能代表日常负载与发布峰值的工作流;记录任务开始排队、runner 开始执行和任务结束的时间。
- 同时收集失败率、重试原因和资源争用迹象,避免把任务本身不稳定误判成容量不足。
- 将队列等待与执行时间分别对照团队预设目标,不只比较一次运行的总耗时。
- 根据结果调整调度、增加稳定常驻容量,或测试弹性补充;改变配置后重复相同类型的验证。
GitHub Actions 的 runner 分组和并发设置只能作为该平台的例子。若你用其他 CI 平台,应按它自己的官方文档确认队列、分组和权限配置。你也可以参考 Apple 对 Xcode CI 环境变量与动作标识的说明,明确日志中哪些信息来自 Xcode 工作流,哪些字段由自家脚本或 CI 平台记录。
第二张表用于对比容量策略,不提供未经核实的机器数量、价格或性能承诺:
| 容量策略 | 更适用的负载 | 需要核算与验证的项目 | 主要风险 |
|---|---|---|---|
| 固定常驻容量 | 日常持续占用、任务到达较稳定 | Mac 采购或租赁成本、维护工时、闲置时段、环境更新 | 峰值超出基线时仍可能排队 |
| 固定容量加弹性补充 | 基线稳定但发布窗口偶有尖峰 | 基线支出、弹性租用单价与时长、交付周期、接入和回收成本 | 临时容量未必能及时匹配任务或配置 |
| 只靠弹性容量 | 负载间歇、常驻需求低且任务可等待 | 实际使用量、启动等待、环境准备、凭证配置与数据处理要求 | 冷启动、可用性或权限条件可能影响工作流 |
判断 runner 是否可接入,也要确认团队的权限和隔离要求。自托管 runner 的管理责任、软件更新与可访问仓库范围,都会影响运维成本;若构建过程涉及签名凭证或敏感代码,先核对凭证保管与环境隔离,再把容量方案提交采购评审。你可以结合数据隐私与信息处理说明及安全与可靠性页面核对相关事项,但仍应以企业自身合规要求和实际服务条款为准。
持续复核与容量选择:固定还是弹性补充
Mac 打包服务器的规划应随实际负载变化复核,而不是采购后长期沿用最初估算。版本发布节奏改变、测试矩阵扩大、项目数量增加、Xcode 或构建脚本升级,都可能延长任务执行时间或改变任务到达峰值。
复核时保留相同口径:按任务类别和时段查看队列等待、执行时长、失败与重试;同时记录平台并发配置是否调整、runner 是否离线,以及构建是否迁移了资源消耗较大的步骤。若队列问题集中在特定任务或触发策略,先优化调度或拆分工作流,再判断是否需要增加常驻机器。
你还要核实构建产物与日志的保存方式,不能假设所有 CI 服务都会按同一规则保留记录。举例而言,Apple 的 Xcode Cloud 文档说明构建产物可访问 30 天;这只适用于该服务的说明,不能推定你使用的其他 CI 平台也采用相同保留期限。Apple 的 Xcode Cloud 首次工作流文档注明了这一期限。
到采购评审时,把实际报价和使用量填入对比表的成本项,再决定固定还是弹性。自购 Mac 更适合有长期、稳定占用并需要直接管理硬件的团队;但闲置折旧、维护与扩容采购周期也要计入。自有 runner 能由团队掌控环境,却需要自行维护系统、软件和权限;GitHub 对自托管 runner 的文档也明确列出维护责任,不能只看平台接入是否免费。
如果现有方案是自购机器或仅靠内部共享 runner,它可能面临闲置成本、硬件维护,以及高峰时难以迅速补充容量等问题。完成负载估算后,若你只缺少短期或峰值算力,可先核对 SDKMac 可用节点中的配置与租赁周期,再判断是否适合补充远程 Mac;持续高占用、必须接入特定物理设备或需要自行控制硬件的场景,则应优先评估自购。租赁前把权限、环境准备和实际接入条件逐项核实,比单凭开发者人数直接加机器更稳妥。
按真实并发规划 Mac 打包容量
把队列压力转化为可用算力:SDKMac 提供独享物理 Mac 节点,适合为 CI/CD 构建与测试配置专用 Runner。
