
Perfetto CI 架构解析基于 GCE 自托管 Runner 与 GitHub Actions 的弹性持续集成系统【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto导读本文基于 Perfetto 仓库的 continuous-integration.md 设计文档深入解析 Perfetto 项目用于补充 Android TreeHugger 的持续集成体系它以 GitHub Actions 为调度入口在 Google CloudGCE GAE上运行自托管 Runner通过VM → worker 容器 → sandbox 容器三级分层实现无状态、可弹性伸缩、安全隔离的构建与测试。读完本文你将掌握这套 CI 的整体架构、启动链路、核心配置参数、日常运维 Playbook 及其安全模型并可在自己的项目中复用其设计思路。Perfetto 的 CI 定位十分明确它叠加在 Android TreeHugger 之上而非替代目的是为 TreeHugger 不支持的其它操作系统和较老 Android 设备提供早期测试信号与覆盖。整套 CI 基于 GitHub Actions入口工作流为 .github/workflows/analyze.yml。一、CI 整体架构GitHub Actions GCE 自托管 RunnerPerfetto CI 由两个主要部分构成调度层GitHub Actions 工作流位于 .github/workflows/负责根据变更文件类型决定触发哪些测试执行层注册在 GitHub 项目上的自托管 Runner托管于名为perfetto-ci的 Google Cloud 项目中源码位于 infra/ci。与直接使用 GitHub 托管的 runner 不同自托管方案让 Perfetto 能够完全掌控 runner 的运行环境Docker 镜像、临时磁盘、网络隔离、服务账号权限并借助 GCE 的自动扩缩容能力按需拉起计算资源同时将成本函数与待处理任务队列长度绑定。从仓库结构看infra/ci 下包含三类核心组件frontend/基于 AppEngine 的控制器ci.perfetto.dev负责编排队列与推送扩缩容指标worker/运行在每台 GCE VM 上的特权容器与相关脚本sandbox/真正执行 GitHub Action Runner 的隔离容器。下图展示了这套 CI 的整体结构图片来源为仓库内的 CI 架构图二、入口工作流 analyze.yml按变更类型扇出的作业调度.github/workflows/analyze.yml 是整个 CI 的入口。它负责在 pushpostsubmitmain分支和 pull_requestpresubmitmain与dev/**/*分支类型为opened与synchronize时被触发并设置了concurrency组以在新提交推送时取消同一 PR/分支上的旧任务。该工作流中的analyzejob 特意运行在GitHub 的ubuntu-latest公共池上而非自托管 sandbox。注释给出了两点刻意设计的原因analyze不需要 sandbox 容器提供的任何特殊能力公共池更快当 CI 自动扩缩容降到 0 时等待自托管资源就绪会很久从而延迟子任务的排队、进而延迟扩容——把analyze放在公共池能尽快扇出子任务。analyzejob 通过git diff --name-only对比上游分支产出三个关键输出outputs用于驱动下游作业的条件执行输出判定逻辑仓库内egrep正则含义TRIVIAL_CHANGE变更文件全部落在^(docs\|infra\|tools\|test/data\|[.]github)/内纯文档/基建变更跳过全部构建测试UI_ONLY_CHANGE变更文件全部落在^(ui\|test/data/ui-screenshots)/内仅 UI 变更跳过 linux/android 等重型测试BIGTRACE_CHANGE存在^ui/src/bigtrace/下的变更额外触发 bigtrace 测试随后analyze按条件扇出以下子工作流均为needs: analyze的可复用工作流linux-tests.yml非 UI-only 且非 trivial 时触发android-tests.yml同上ui-tests.yml非 trivial 时触发bazel-tests.yml 与 fuzzer-tests.yml非 UI-only 且非 trivial 时触发bigtrace-tests.yml仅BIGTRACE_CHANGE 1时触发repo-checks.yml 与 rust-sdk-tests.yml分别无条件/条件触发。工作流末尾的ensure-ci-is-greenjob 汇总所有可能被跳过的子工作流结果success与skipped视为通过cancelled会取消整个 run其余视为失败——该 job 供仓库的 require CI to pass ruleset 使用是合入门禁的最终裁决点。三、自托管 Runner 的三级分层VM → worker → sandboxPerfetto CI 的执行资源按三级容器/进程组织职责逐级收窄、权限逐级收缩。3.1 GCE VM 层无状态、只读系统盘Worker GCE VM 的数量可变由GCE_VM_TYPE等参数驱动见 infra/ci/config.py由 Google Cloud Autoscaler 动态拉起上限为MAX_VMS_PER_REGION。每台 VM 的整机系统镜像是只读的VM 本身完全无状态除上传到 Google Cloud Storage 的 UI 产物与 GitHub 缓存外不持久化任何状态SSD 仅作为 scratch 盘用于 tmpfs/swap每次重启即清空。VM 的动态伸缩以ci.perfetto.devAppEngine 推送的 Stackdriver 自定义指标为成本函数该指标即排队中 运行中的 pull-request 数量。3.2 worker 容器层VM 的管家每台 GCE VM 上运行一个特权 Docker 容器worker。它负责 VM 的基础设置除此之外不做任何事——只通过 supervisord 确保始终有 N 个 sandbox 在运行。worker 容器是特权容器但注释明确说明它不是用于隔离的隔离是 sandbox 的职责只是便于部署。3.3 sandbox 容器层真正执行 GitHub Action Runner每个 sandbox 容器运行一个 GitHub Action Runner 实例构建与测试都在 Action Runner 内完成。sandbox 运行在受限网络与受限服务账号下是安全边界所在详见第六节。3.4 服务账号划分账号使用方权限gce-ci-workerperfetto-ci.iam.gserviceaccount.comGCE VM 与特权 worker 容器云平台基础权限见GCE_SCOPESgce-ci-sandboxperfetto-ci.iam.gserviceaccount.comsandbox 容器仅允许创建不可删除/覆盖gs://perfetto-ci-artifacts中的产物这一设计确保即使 sandbox 被攻破攻击者也无法覆盖或删除已有 CI 产物。四、从开机到测试运行的完整链路Sequence Diagram原文档给出的启动序列如下左侧为层次右侧为实际执行的脚本/工作流make -C /infra/ci start-workers ┗━ gcloud start ... [GCE] # From /infra/ci/worker/gce-startup-script.sh docker run worker ... [worker] # From /infra/ci/worker/Dockerfile ┗━ /infra/ci/worker/worker_entrypoint.sh ┗━ supervisord ┗━ [N] /infra/ci/worker/sandbox_runner.py ┗━ docker run sandbox-N ... [sandbox-X] # From /infra/ci/sandbox/Dockerfile ┗━ /infra/ci/sandbox/sandbox_entrypoint.sh ┗━ github-action-runner/run.sh ┗━ .github/workflows/analyze.yml ┣━ .github/workflows/linux-tests.yml ┣━ .github/workflows/ui-tests.yml ... ┗━ .github/workflows/android-tests.yml结合源码可将每一层的关键实现展开如下1.make -C infra/ci start-workersMakefileMakefile 先通过include $(shell python3 config.py makefile)从 config.py 生成配置这就是所有变量只存一处的设计再依次执行构建 GCE 实例模板instance-templates create注入startup-script-url、num-workers、sandbox-img、worker-img等 metadata机器类型为c2d-standard-32配 2 块 NVMe local SSD 与 100GB PD-SSD 启动盘、创建托管实例组并配置 autoscaling。2. GCE 启动脚本gce-startup-script.sh从 metadata server 拉取worker-img镜像名将 NVMe 盘组 RAID0 并格式化为无日志 ext4注释说明这是最快配置-E nodiscard避免 TRIM 开销挂载为/tmp作为构建/检出/缓存的 scratch 空间关闭内核地址空间随机化kernel.randomize_va_space0因为新版内核会阻止 sandbox 内调用personality(ADDR_NO_RANDOMIZE)若不关闭则需把 sandbox 改为--privileged从而破坏隔离初衷最后以--privileged --nethost挂载 docker.sock 拉起 worker 容器。3. worker 入口worker_entrypoint.sh从 metadata 读取num-workers与sandbox-imgdocker pull最新 sandbox 镜像创建名为sandbox的受限 bridge 网络并用 iptables拒绝该网络访问169.254.0.0/16GCE metadata server 网段防止 sandbox 窃取 metadata 或模拟服务账号随后生成 supervisord 配置以numprocs${NUM_WORKERS}启动 N 个sandbox_runner.py进程并设置autorestarttrue保证常驻。4. sandbox 运行器sandbox_runner.py为每个 sandbox 分配GCE_HostName-N名称通过gcloud auth application-default print-access-token --impersonate-service-account为沙箱生成1 小时短时效的降权令牌create_sandbox_token且每 50 分钟刷新一次向 GitHub 申请注册令牌后docker run启动嵌套 sandbox 容器--cap-add SYS_PTRACE供调试工具使用、--network sandbox --dns 8.8.8.8、将/tmp/sandbox-N以 tmpfs 方式挂载为容器内/tmp并通过环境变量注入GITHUB_TOKEN_PATH与SVC_TOKEN_PATH。脚本同时用/tmp/perfetto_ci_lastrun的 mtime 记录最近活动供闲置关机决策使用。5. sandbox 入口sandbox_entrypoint.sh将github-action-runner复制到 tmpfs因为 Action Runner 会在_work子目录检出仓库以--unattended --ephemeral --replace模式注册一次性 Runner--ephemeral表示跑完一个 job 即退出配置 gcloud 使用降权令牌文件注册 SIGTERM 清理钩子cleanup()中执行config.sh remove优雅摘除 Runner最后后台运行./run.sh等待 job。6. 作业执行Runner 被 GitHub 分配任务后执行 analyze.yml再按变更分类扇出上节列出的各测试工作流。五、核心配置参数一览infra/ci/config.py所有 CI 相关变量集中定义在 infra/ci/config.py既被 Python 脚本 import也可用python3 config.py makefile生成 Makefile 片段config.mk或python3 config.py js生成前端使用的 JSON。关键参数如下参数值说明GITHUB_REPOgoogle/perfetto关联的 GitHub 仓库GITHUB_APP_ID/GITHUB_APP_INSTALLATION_ID1184402/62928975用于以 GitHub App 身份申请 Runner 注册令牌PROJECTperfetto-ciGoogle Cloud 项目 IDSANDBOX_IMG/WORKER_IMGus-docker.pkg.dev/perfetto-ci/containers/gh-sandbox/gh-worker容器镜像仓库地址CI_SITEhttps://ci.perfetto.dev前端控制台GCS_ARTIFACTSperfetto-ci-artifacts产物桶名JOB_TIMEOUT_SEC/CL_TIMEOUT_SEC45 * 60/3h单 job / 单 change-list 超时LOGS_TTL_DAYS15日志保留时长TRUSTED_EMAILS^.*google.com$可信提交者邮箱正则GCE_REGIONSus-west1部署区域GCE_VM_TYPEc2d-standard-32VM 机器类型32 vCPU 计算优化型MAX_VMS_PER_REGION8每区域 VM 上限NUM_WORKERS_PER_VM4每台 VM 上的 sandbox 数量AUTOSCALER_MIN0可缩容至零闲置成本为零SANDBOX_SVC_ACCOUNTgce-ci-sandboxperfetto-ci.iam.gserviceaccount.comsandbox 降权账号Makefile 中的 autoscaling 配置同样值得注意实例组以 Stackdriver 自定义指标custom.googleapis.com/perfetto-ci/ci_job_queue_len为利用率信号目标值为 0.1gauge 类型冷却期 60 秒——队列越长扩的 VM 越多。六、日常运维 Playbook6.1 前端JS/HTML/CSS/py变更本地测试make -C infra/ci/frontend test部署make -C infra/ci/frontend deploy前端位于 infra/ci/frontend/内含 AppEngine 配置app.yaml、cron.yaml、index.yaml、main.py、stackdriver_metrics.py推送扩缩容指标等。6.2 Worker / Sandbox 变更构建并推送新的 Docker 容器make -C infra/ci build pushbuild依次构建 worker 与 sandbox 镜像构建前会把config.py、common_utils.py复制进构建上下文push推送至us-docker.pkg.dev若推送失败Makefile 提示先执行gcloud auth configure-docker us-docker.pkg.dev。重启 GCE 实例组手动或执行make -C infra/ci restart-workers该目标等价于stop-workers start-workers先删除托管实例组再重新创建并配置自动扩缩容。其余辅助目标start-workers含gce-template依赖重建实例模板并创建实例组、stop-workers、autoscaler-debug查看当前扩容状态、start-worker-for-testing/stop-worker-for-testing测试用单 VM、cli交互式调试客户端。七、安全设计考量原文档明确列出并逐一论证了这套 CI 的安全模型核心要点如下gs://perfetto-ci-artifacts桶全局可读但仅 GAE 与 GCE 服务账号可写sandbox 账号只可创建、不可删除或覆盖。该项目中没有任何账号拥有值得一提的特权worker 与 sandbox 服务账号在 CI 项目之外无任何特殊能力即便被攻破能做的事情也不会超过自己另开一个 GCP 项目。该 CI只做功能与性能测试不涉及任何形式的持续部署GitHub Actions 仅对perfetto-team与perfetto-contributors自动触发。sandbox 并不难逃逸Docker 是唯一边界因此 pre-submit 与 post-submit 的构建产物均不被视为可信只用于功能正确性与性能回归判定。CI 构建出的二进制不会在 CI 项目之外的任何机器上运行也刻意不推送至 GCS。唯一被保留最长 30 天并上传至 GCS 桶的构建产物是UI 产物目的仅为获得 HTML 变更的可视化预览且这些 UI 产物通过 GCS per-bucket API 从与生产 UI 不同的源提供服务避免与生产环境共享 origin。从代码实现上看这些设计均有落地sandbox 网络被 iptables 阻断 metadata serverworker_entrypoint.sh、沙箱令牌为 1 小时降权短令牌且定期刷新sandbox_runner.py、GCE 启动脚本关闭 ASLR 以免被迫给 sandbox 提权gce-startup-script.sh。八、总结与延伸阅读Perfetto CI 的核心设计哲学可以概括为调度与执行分离、执行资源完全无状态、权限按层收敛、成本随队列弹性伸缩。GitHub Actions 负责按变更分类扇出任务GCE 自托管 Runner 以VM 只读无状态 worker 管家 一次性 sandbox的三层结构承载构建测试而 AppEngine 前端则以任务队列长度驱动 Autoscaler 在 08 台 VM 之间伸缩。如需进一步了解 Perfetto 的测试策略与相关实现可继续阅读仓库内的以下资源测试策略总览docs/contributing/testing.md原文档指定入口CI 入口工作流.github/workflows/analyze.yml各测试工作流.github/workflows/linux-tests、ui-tests、android-tests、bazel-tests、fuzzer-tests、rust-sdk-tests、bigtrace-tests 等CI 源码infra/ci含 config.py、Makefile、worker/sandbox 容器源码GCS 缓存 Action.github/actions/cache-on-google-cloud-storage/自托管 runner 无法使用 GitHub 自带 cache 时的 GCS 缓存方案【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考