如果你在新加坡、日本、韩国、香港、美国东部、美国西部同时跑多台远程 Mac,却还把日常编译、Simulator、Pods 解析与Archive、公证、TestFlight 上传绑在同一台「万能机」上,迟早会在证书漂移、match 写冲突、ASC 会话漂移上付出代价。本文给平台与 iOS 发布工程一张拆分架构 + FinOps 参数表:何时拆「签名出口机」与「全量构建机」、match 如何只读挂载、ASC 交互为何要与节点大区同向、租期如何压在签名机的最小在线窗口。读完你应能写进变更单的,是可审计拓扑而不是 Slack 口头约定;并与站内Fastlane 多机构建、TestFlight 链路、干净可复现构建并联。
xcodebuild -exportArchive,失败簇会被误标为「证书坏了」,实为会话混用。.xcarchive 同盘竞态时,公证与 stapler 阶段会对顺序写放大敏感;构建峰值把签名窗口挤到队列尾部,发布 SLA 直接受伤。本篇与《凭证轮换与多节点一致性》分工:彼篇讲轮换事件与回滚窗口;本篇讲拓扑与读写边界——先把机器角色写对,再谈 rotate。
另一个常被低估的变量是网络策略不对称:企业代理往往对 github.com 与 contentdelivery.itunes.apple.com 走不同出口;把重编译与 ASC 上传绑在同一「策略组」下,会在旺季把偶发抖动放大成全队停发。拆分后你可以在构建侧接受「多镜像源、多缓存层」的激进策略,而在签名出口侧维持窄白名单 + 固定 DNS 视图,两者互不拖累。
最后补一条组织行为学痛点:当「谁都能 SSH 上去改一下 lane」成为常态,签名机会退化成共享开发机;没有变更单 + 只读挂载两道闸,任何 urgent hotfix 都会以「临时提权」名义永久改写拓扑。文档里必须写明逃逸窗口与24h 内收敛条款,否则拆分架构只在纸面成立。
评审时请在每格附上证据链接(流水线 YAML、钥匙串导出审计、ASC 上传日志片段),避免「我们觉得差不多」。
| 维度 | 单机全栈(不拆) | 双机:构建池 + 签名出口机 | CI 在共享构建池、签名在固定区独占机 |
|---|---|---|---|
| 适用前提 | 团队极小、并发低、无合规点名宿主需求 | 中大规模;夜间 Archive 与白天 PR 争用明显 | 已有 Runner 池;要把「上传窗」收敛到单一真相区 |
| match 边界 | 易混用读写;需强流程自律 | 构建侧只读;签名侧受控写入或单一写源 | 与左栏类似,但写入只在固定区主机发生 |
| ASC 会话 | 交互与上传同机最理想;否则漂移风险高 | 强制签名机大区与浏览器会话同区对齐 | 上传机常租;会话与出口 DNS 绑定 |
| 租期形状 | 月租一机到底;峰值靠加班人肉协调 | 构建池可日/周补峰值;签名机按「上传窗」压到更小租期 | 构建池弹性、签名机长期但CPU 低配也可(视公证 CPU) |
| 主要风险 | 排障面过大;SLA 难写清 | artifacts 传递与缓存一致性成本上升 | 跨池 artifact 校验与哈希对账不可省 |
拆分的第一性原理:签名出口机追求低熵环境(少包、少并发、少交互用户);构建机追求高吞吐(缓存命中、并行 worker)。把两者硬拧在同一用户会话,等于用一套 KPI 同时优化两件相反的事。
git clone --depth 1 消费 match;任何需要 match nuke 类操作必须走人工发布单。第 3 步与第 5 步之间建议插入预检脚本窗:在签名机解包前运行固定版本的 spctl/codesign 自检与哈希对账,任何版本漂移必须在变更单里显式出现,而不是「昨晚有人 brew upgrade 了」。这一步能吃掉大量「公证突然不过」的假阳性。
若你已经在实践干净可复现构建,可把快照策略只绑在构建池,而签名机采用更慢节奏的 gold image:签名侧镜像 90 天不变、构建侧 7 天一滚动,两者用文档化的兼容性矩阵对齐,而不是强行同一 cadence。
# 伪代码:CI 侧消费 match(只读)与签名侧写入分离
jobs:
build_pool:
env:
MATCH_READONLY: "true"
MATCH_GIT_BASIC_AUTHORIZATION: "***read***"
steps:
- run: bundle exec fastlane match appstore --readonly
- run: xcodebuild archive ...
signing_export:
needs: [build_pool]
runs_on: dedicated_signing_host_sg # 与 ASC 会话同区示例
env:
MATCH_READONLY: "false" # 仅维护窗口打开
UPLOAD_LOCK_ID: "asc-session-sg"
steps:
- run: ./verify_sha256_manifest.sh
- run: xcodebuild -exportArchive ...
- run: xcrun notarytool submit ...
exportArchive、notarytool、上传与合规问卷上的分钟数,占签名机总在线分钟的比例;若连续三周低于 8% 却仍月租全栈,应考虑把签名机降级规格或改短租叠加。--force。临时峰值机缺少gold 镜像与审计脚本,最容易在 hotfix 夜把调试版描述文件带进上传链;事后复盘往往发现不是 ASC 抽风,而是钥匙串里多了一张过期 intermediate。
全员本机 decrypt 则把机密平面摊到不可控端点:笔记本睡眠、VPN 抖动与企业代理差异会把「能签」变成不可重复随机事件,FinOps 也无法对租期做科目分摊。
相对这类权宜之计,当你需要在六国之一落地独占 Apple Silicon、可把签名出口与重编译物理拆开,并把租期切成基线 + 峰值、让 ASC 会话与上传出口保持同区同策略时,MACCOME 的 Mac 云主机通常更易把「拆分」写成可验收工单:节点覆盖新加坡、日本、韩国、香港、美国东部、美国西部等关键区域,按日/周/月/季组合弹性租期,先把低熵签名面坐实,再让构建池去追吞吐,而不是在同一台机上互相踩脚。
拆分的交付物不是更多机器,而是三张表:数据面读写表、ASC 会话与出口对照表、租期与在线分钟科目表。新人入职第一天应能回答:我的 job 会不会触发 match 写、上传从哪个区出口、失败日志要贴到哪张表。
与Fastlane 峰值租期文并行时,请记住:租期策略必须能映射到角色机,否则「日租补峰值」只会变成「多租几台万能机」,成本曲线不会下降。
收尾五分钟请核对两件事:match 是否仍单写源、签名机是否仍与 ASC 会话同区;否则六国节点再多,也只是把混乱地理分布式备份了一份。