2026 年六国远程 Mac:Jenkins 与 Buildkite Agent 凭证拓扑(机器用户、OIDC、PAT)与 GitHub Actions/GitLab Runner 并存的互斥与租期 FinOps 检查表

约 17 分钟阅读 · MACCOME

如果你在新加坡、日本、韩国、香港、美国东部、美国西部独占远程 Mac上既要跑 JenkinsBuildkite 的 macOS Agent,又已经接了 GitHub ActionsGitLab 自托管 Runner,真正拖垮审计与预算的往往不是 CPU,而是第二套调度器带来的凭证爆炸:谁持有长期 PAT、match 解密钥匙串与 ASC 会话落在哪个用户上下文、短租机重建后密钥是否「顺手复制进镜像」。本文给你凭证拓扑 + 互斥 + 租期科目三张表,并与站内《Jenkins/Buildkite 错峰常驻》《Runner 标签与密钥隔离》分工阅读:前者管队列与错峰,本文只管身份、OIDC 与 revoke 路径

六国独占机上「第二 CI 控制器」最常见的六类凭证事故

  1. 三套 agent 共用同一 macOS 用户主目录:Jenkins 的 ~/.ssh、Buildkite 的 buildkite-agent 与 Runner 的 actions-runner 若混在同一交互账户下,一次 git credential-osxkeychain 弹窗就能把无人值守打成「随机绿」。
  2. 把 90 天轮换的 PAT 写进短租镜像:日租冲刺机每周销毁,镜像里却冻着组织级 PAT,泄露半径覆盖整个 org,而不是单台构建机。
  3. 互斥锁缺失导致 match 解密与 notary 并发:两条流水线同时触碰同一 match 仓库或同一 ASC API Key 会话,表现为偶发 401/403,复盘时被误归为「苹果侧抖动」。
  4. OIDC audience 配错在云控制面:Buildkite 或 GitHub 的 OIDC trust policy 若未收窄到具体 repo/environment,agent 能换到「比 job 所需更大」的令牌面。
  5. 钥匙串分区与 LaunchAgent 启动顺序未文档化:重启后 Jenkins 先起、Runner 后起,导致读取到空钥匙串分区,首条流水线失败被人工点「重试」掩盖。
  6. FinOps 只盯 vCPU 不盯「凭据寿命 × 租期」:长寿命密钥绑在短租机上,财务看到的是便宜日租,安全团队看到的是不可接受的撤销窗口。

六国节点的物理价值是区位与独占 IO 可预期;若凭证拓扑写不清,只是把「笔记本上的混乱」升级成「云上可并发的混乱」。与《Xcode Cloud 混合 CI》并行时,还要额外回答:哪条身份能触达 ASC、哪条只能触达内网 Registry——否则混合矩阵会变成混合事故。

组织治理上建议引入凭据 RACI:平台工程维护机器用户与 OIDC 绑定,业务仓库维护 workflow 级权限,安全团队验收 revoke 演练频率;任何一方缺位都会在第二套控制器上线后指数放大。

维度 优先长寿命 PAT / 部署密钥 优先 OIDC / 短期令牌
租期 仅允许落在月租及以上基线机,并配镜像外密钥注入 可落到日/周租峰值机,前提是控制面 trust 收窄
审计粒度 需额外记录「谁把 PAT 写进哪台机」;旋转窗口常与财务季对齐 云侧可绑定 repo、environment、agent 池;更易做按 job 归因
与 Jenkins 插件生态 大量经典插件默认假设静态凭据文件 需显式改造 pipeline 或 wrapper;一次性成本高
与 Buildkite agent 钩子脚本易偷偷 export 秘密 推荐 hooks 只做装配,秘密来自 OIDC 交换的短时 token
与 GHA/GitLab Runner 自托管 runner 常见 .credentials 长期文件 GitHub/GitLab OIDC 换云厂商 STS 已是主流路径,应优先对齐
warning

红线:不要在短租峰值机上生成组织级长期 PAT 或根级部署密钥;若业务坚持,应把密钥寿命与租期上限写进同一张审批表,否则 FinOps 与安全永远对不上账。

六步 Runbook:从「能跑」到「能 revoke、能分摊科目」

  1. 盘点三套调度器实际触碰的秘密面:列出 Jenkinsfile / Pipeline、Buildkite pipeline、GitHub workflow 各自读取的环境变量与文件路径;标记哪些是 org 级、哪些是 repo 级。
  2. 为每套 agent 分配独立机器用户与主目录:例如 jenkinsbuildkiterunner 三分账户;禁止共用登录会话做 CI。
  3. 为独占资源加互斥:match 解密、notary upload、ASC 浏览器会话类步骤必须串行;锁名写入 ROUTING.md 与流水线注释。
  4. 把 OIDC trust 条件写成可评审文本:audience、repository、ref 前缀、environment 名;与云 IAM 或内网 STS 策略交叉对照。
  5. 做季度 revoke 演练:随机作废一类令牌,验证三台 agent 是否按预期降级而非静默继续。
  6. 把凭据寿命写进租期 FinOps 表:长寿命只绑基线机;峰值机只出现短时 STS;科目与错峰租期表同页展示。
bash
# 示例:互斥锁占位(按你们协调后端替换 flock 实现)
exec 9>/var/lock/match-decrypt.lock
flock -n 9 || { echo "match decrypt busy"; exit 42; }

# 示例:机器用户分轨(LaunchDaemon / plist 片段思路,勿照抄路径)
# UserName=buildkite vs UserName=runner —— 各自 HOME 下只放自己的 git 凭据助手配置

三条应写进评审纪要或 Grafana 注解的量化口径(阈值按组织基线替换)

  • 长寿命秘密绑定短租机的 job 占比:目标为 0%;若一周内采样发现 >3% job 仍从日租机读取 30 天以上 PAT,触发安全例外审批。
  • 互斥锁等待 P95(秒):对 match / notary 类步骤单独打点;若 P95 持续 >600s 且队列深度上升,优先扩容串行出口机而非加并行编译机(示例阈值可按现网调整)。
  • OIDC 换票失败率:按控制面与 region 拆分;若某六国节点所在大区对 STS 端点 RTT 上升,应先查网络拓扑再调 runner 并发。

为什么「全员 SSH 上去手动配一把钥匙串」或「镜像里冻一份万能 .env」在 2026 年比不加第二控制器更危险

手动配钥匙串不可审计:谁最后一次解锁、是否把交互式会话留在机房里,都无法写进 SOC2 证据包。镜像万能 .env 则把泄露面从「单个 repo」扩大到「任何能启动容器的人」——与 OIDC 的「按 job 最小权限」哲学完全相反。

当你需要把 Jenkins/Buildkite 与 Runner 稳定并存独占 Apple Silicon、固定大区出口、可把基线租期与峰值租期拆科目的环境里,MACCOME 的 Mac 云主机更适合作为长寿命凭据的锚点机短时 OIDC 峰值机的物理承载:节点覆盖新加坡、日本、韩国、香港、美国东部、美国西部,按日/周/月/季组合弹性租期,先把「谁能在哪台机上活多久」写清,再让编译并发去追吞吐,而不是在同一台日租机上同时冻 PAT、跑五个 Simulator、再开三条 notary 上传。

收束:凭证拓扑应成为 CLONE_POLICY 的姊妹篇 CREDENTIAL_ROUTING.md

交付物建议三张表:机器用户与 HOME 映射互斥资源与锁名OIDC trust 条件与 STS 作用域。新人第一天应能回答:我的 job 用哪张身份、失败时该 revoke 哪一类令牌、短租机上为何没有任何 90 天 PAT。

Runner 密钥清单并联时,请把「GitHub 侧 OIDC」与「macOS 钥匙串分区」写进同一变更单,否则你会在云端看到漂亮的 trust policy,在机上看到空的 keychain partition。

常见问题

同一台六国独占机上可以同时跑 Jenkins、Buildkite 与 GitHub Actions Runner 吗?

可以,但必须分用户、分钥匙串分区、互斥独占步骤,并避免三套流程共用长期 PAT。错峰与队列细节见错峰常驻 Runbook;公开租期与档位可先对照租赁价格说明

为什么要把长寿命凭据绑在月租基线机?

日租机重建频繁,静态秘密容易进镜像或备份链;基线机提供稳定审计锚点。运维说明也可查阅帮助中心 · 云 Mac