资讯动态

oh-my-pi 预加载 Runner 镜像:为 Kata 微虚拟机 CI 构建、导入与滚动发布

发布时间:2026/9/10 7:14:59 来源:尧图企业网站定制
oh-my-pi 预加载 Runner 镜像为 Kata 微虚拟机 CI 构建、导入与滚动发布【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi导读本文基于 oh-my-pi 仓库infra/docs/运维文档体系中的《03 - Preloaded runner image》完整讲解该项目自托管 CI 的核心一环把 GitHub Actions runner 镜像从每次任务现场安装依赖改造成把全部依赖在构建期烘焙进镜像的预加载preloaded镜像。你将掌握它的 Dockerfile 逐层设计、与仓库内setup-system-deps复合动作的同步机制、在 k3s 单节点上构建 → 冒烟验证 → 导入 containerd → 指向 ARC → 校验上线的完整流水线以及镜像标签约定、版本升级与 Kata 微虚拟机内的真实验证方法。本文对应的部署环境由 infra/docs/02-kata-runtime.mdKata containerd RuntimeClass与 infra/docs/04-arc-and-caching.mdARC runner、共享缓存、出口策略组成这里构建的镜像正是 ARC runner Pod 模板中template.spec.containers[0].image所引用的镜像配合imagePullPolicy: IfNotPresent使用而模板上的runtimeClassName: kata-qemu则来自 02 号文档注册的 Kata 运行时。1. 为什么要做预加载镜像1.1 冷启动的痛每个任务都在重复装依赖ghcr.io/actions/actions-runner:latest是一个干净的 Ubuntu 24.04 runner。在常规类似 GitHub 托管式runner 上CI 工作流会在每一个任务开始时现场安装系统依赖canvas 构建所需的 cairo/pango 原生栈、fd/ripgrep/imagemagick、bun、sccache、Zig、cargo 原生辅助 CLIcargo-nextest、cargo-zigbuild、cargo-xwin、带预热 Bazel 的bazelisk以及带交叉编译 target/组件的固定 Rust nightly 工具链。在 Kata 微虚拟机场景里这个成本被放大了每个临时任务都会启动一个全新的 Kata 微虚拟机任务结束后虚拟机即被销毁。如果依赖安装发生在任务运行时那么 apt/bun/rustup/工具下载这一整套开销会在每一个任务上重复支付——微虚拟机每次都是冷启动的这部分纯粹是延迟。1.2 预加载把安装成本从每次任务搬到构建期预加载镜像的核心思路是把安装工作移到镜像构建期。每个临时 runner 启动时工具链已经就位apt 依赖不再重复抓取bun、cargo/rustc、sccache、zig、bazelisk/bazel以及 cargo 辅助 CLI 已经在PATH上固定的 Rust 工具链已经是 rustup 默认工具链CI 里的 target/component 安装步骤退化为空操作no-op。这正是微虚拟机冷启动、但依赖是热的warm dependencies的关键虚拟机的创建成本约一两秒无法消除但真正昂贵的依赖安装成本被彻底移出任务关键路径。1.3 与setup-system-deps保持同步防止漂移镜像里烘焙的 apt 依赖集合必须与仓库内的.github/actions/setup-system-deps复合动作保持严格一致实现见 .github/actions/setup-system-deps/action.yml。该动作是自愈的互补角色在预加载镜像上它探测到工具已存在直接跳过 apt 安装在普通 runner上它安装完全相同的依赖集合保证 CI 在任何环境都能工作。其探测逻辑为command -v fd command -v rg command -v magick \ pkg-config --exists cairo pango实际复合动作中的判定还额外校验了magick即fd、rg、magick三个命令 pkg-config能解析cairo/pango头文件全部命中才判定已预加载# .github/actions/setup-system-deps/action.yml if command -v fd /dev/null 21 \ command -v rg /dev/null 21 \ command -v magick /dev/null 21 \ pkg-config --exists cairo pango 2/dev/null; then echo System deps already present (preloaded runner image); skipping apt. exit 0 fi同步规则如果你新增了一个被该动作探测的依赖必须在两处同时添加——Dockerfile 的 apt 行和setup-system-deps。一旦二者漂移要么动作在镜像已有该依赖时重新安装变慢要么 CI 因为镜像漏烘焙了某个工具而直接失败。2. Dockerfile 全解2.1 镜像定义的权威来源文档中复刻的 Dockerfile 来自部署主机的/root/omp-kata-runner-image/而权威版本受版本控制于 infra/runner.Dockerfile由仓库驱动的 reload 脚本覆盖写入主机副本见第 3 节。当前仓库内的权威版本在文档原始快照的基础上又新增了zstd、cmake、ninja、bazelisk 预热 Bazel 等层次以下以其为准。# syntaxdocker/dockerfile:1 # Preloaded omp-kata runner image. # # Stock GitHub Actions runner (Ubuntu 24.04) with the dependencies CI installs # on every job baked in, so each ephemeral Kata microVM boots with them already # present instead of re-fetching them per job: # - APT system deps (canvas/cairo stack fd/ripgrep/imagemagick) fd/magick shims # - GitHub CLI (gh) — present on GitHub-hosted runners; the coding-agent github # tool and release workflows expect it # - C/build toolchain the native canvas builds need # - bun (system-wide, on PATH) # - sccache Zig cmake/ninja cargo-nextest/cargo-zigbuild/cargo-xwin for native builds # - bazelisk ( pre-warmed bazel 9.2.0) for the Bazel native pipeline # - rust nightly (pinned) clippy/rustfmt/rust-analyzer linux-arm64/windows-msvc targets # # Rebuild reimport (see /root/omp-kata-runner.md) after bumping the ARGs below # or the apt set. Keep the apt set in sync with .github/actions/setup-system-deps. FROM ghcr.io/actions/actions-runner:latest ARG RUST_NIGHTLYnightly-2026-04-29 ARG BUN_VERSION1.4.0 ARG SCCACHE_VERSION0.15.0 ARG ZIG_VERSION0.16.0 ARG CMAKE_VERSION4.1.2 ARG NINJA_VERSION1.13.1 ARG BAZELISK_VERSION1.29.0 ARG BAZEL_VERSION9.2.0 USER root ENV DEBIAN_FRONTENDnoninteractive # Mirrors the Install system deps block in .github/workflows/ci.yml plus the # native/cross toolchain (clang/lld/llvm), the baked cache/tooling binaries, and # the GitHub CLI. The gh apt repo is added first so gh installs in the same apt # transaction. RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg -o /usr/share/keyrings/githubcli-archive-keyring.gpg \ chmod gor /usr/share/keyrings/githubcli-archive-keyring.gpg \ echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main /etc/apt/sources.list.d/github-cli.list \ apt-get update \ apt-get install -y \ build-essential pkg-config curl ca-certificates git unzip xz-utils zstd gh \ clang lld llvm \ libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev \ fd-find ripgrep imagemagick \ ln -sf $(command -v fdfind) /usr/local/bin/fd \ ln -sf /usr/bin/convert /usr/local/bin/magick \ rm -rf /var/lib/apt/lists/* # bun, system-wide (BUN_INSTALL/bin /usr/local/bin, already on PATH). ENV BUN_INSTALL/usr/local RUN curl -fsSL https://bun.sh/install | bash -s bun-v${BUN_VERSION} \ bun --version # Pinned native-build helpers, system-wide. RUN curl -fsSL https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz \ | tar -xz -C /tmp \ install -m755 /tmp/sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl/sccache /usr/local/bin/sccache \ rm -rf /tmp/sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl RUN curl -fsSL https://ziglang.org/download/${ZIG_VERSION}/zig-x86_64-linux-${ZIG_VERSION}.tar.xz -o /tmp/zig.tar.xz \ tar -xJf /tmp/zig.tar.xz -C /opt \ ln -sf /opt/zig-x86_64-linux-${ZIG_VERSION}/zig /usr/local/bin/zig \ rm -f /tmp/zig.tar.xz # cmake ninja for native C deps (audiopus_sys builds bundled libopus via # CMake; MSVC cross builds generate with Ninja). Pinned to the same versions as # .github/actions/ensure-cmake, which no-ops when these are present. RUN curl -fsSL https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-linux-x86_64.tar.gz -o /tmp/cmake.tar.gz \ tar -xzf /tmp/cmake.tar.gz -C /opt \ ln -sf /opt/cmake-${CMAKE_VERSION}-linux-x86_64/bin/cmake /usr/local/bin/cmake \ ln -sf /opt/cmake-${CMAKE_VERSION}-linux-x86_64/bin/ctest /usr/local/bin/ctest \ rm -f /tmp/cmake.tar.gz RUN curl -fsSL https://github.com/ninja-build/ninja/releases/download/v${NINJA_VERSION}/ninja-linux.zip -o /tmp/ninja.zip \ unzip -o /tmp/ninja.zip -d /usr/local/bin \ chmod x /usr/local/bin/ninja \ rm -f /tmp/ninja.zip # bazelisk pre-warmed bazel for the Bazel native pipeline. The prewarm run # downloads the pinned bazel into BAZELISK_HOME at build time so runner jobs # never fetch it; /opt/bazelisk is world-readable so the runner user reuses it. ENV BAZELISK_HOME/opt/bazelisk RUN arch$(dpkg --print-architecture) \ curl -fsSL https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VERSION}/bazelisk-linux-${arch} \ -o /usr/local/bin/bazelisk \ chmod x /usr/local/bin/bazelisk \ ln -sf /usr/local/bin/bazelisk /usr/local/bin/bazel \ mkdir -p $BAZELISK_HOME \ USE_BAZEL_VERSION${BAZEL_VERSION} bazelisk version RUN chmod -R arX $BAZELISK_HOME \ rm -rf /root/.cache/bazel /root/.bazelrc # Pre-own ~/.cache for the runner user: kubelet otherwise creates it root-owned # as the parent of the omp-bazel-repo subPath mountpoint, breaking sibling dirs # like bazels default output_user_root. RUN install -d -o 1001 -g 1001 -m 0755 /home/runner/.cache # rust toolchain cargo helpers for the runner user; rustup default pinned # nightly so Rust setup becomes a no-op on the preloaded image. USER runner ENV RUSTUP_HOME/home/runner/.rustup \ CARGO_HOME/home/runner/.cargo \ PATH/home/runner/.cargo/bin:/usr/local/bin:${PATH} RUN curl --proto https --tlsv1.2 -fsSL https://sh.rustup.rs \ | sh -s -- -y --default-toolchain ${RUST_NIGHTLY} --profile minimal \ rustup component add clippy rustfmt rust-analyzer \ rustup target add aarch64-unknown-linux-gnu x86_64-pc-windows-msvc \ cargo install --locked cargo-nextest cargo-zigbuild cargo-xwin \ cargo --version \ rustc --version \ sccache --version \ zig version \ cargo-nextest --version \ cargo-zigbuild --help /dev/null \ cargo-xwin --help /dev/null2.2 逐层注解# syntaxdocker/dockerfile:1FROM ghcr.io/actions/actions-runner:latest。BuildKit 前端版本锁定然后是官方 Actions runner 基础镜像Ubuntu 24.04。基础镜像自带 runner agent 及其/home/runner/run.sh入口、非 root 的runner用户和sudo。下面所有层次都叠加在该基础之上runner agent 本身从不被修改。ARG版本旋钮。RUST_NIGHTLY、BUN_VERSION、SCCACHE_VERSION、ZIG_VERSION、CMAKE_VERSION、NINJA_VERSION、BAZELISK_VERSION、BAZEL_VERSION是需要升级时动的主要旋钮。作为构建参数你也可以不改文件地临时覆盖docker build --build-arg RUST_NIGHTLY... --build-arg BUN_VERSION... .其中RUST_NIGHTLY必须与仓库 CI 中dtolnay/rust-toolchainnightly步骤解析出的版本一致这样 CI 里的工具链安装才是 no-op见第 6 节。USER rootENV DEBIAN_FRONTENDnoninteractive。切换到 root 执行 apt 与 bun 的系统级安装noninteractive抑制apt-get install期间的 debconf/tzdata 交互提示。aptRUN块——这是必须镜像setup-system-deps的集合顺序如下前三行先把GitHub CLI apt 仓库加进来keyring 签名源列表再执行apt-get update这样gh能在同一次 apt 事务里与其他包一起安装。gh存在于 GitHub 托管 runner 上发布工作流和 coding-agent 的github工具都依赖它apt-get install拉取三组包构建工具链/工具build-essential pkg-config curl ca-certificates git unzip xz-utils zstd gh clang lld llvm。build-essentialpkg-config是原生构建与 canvas 构建的必需项gh供发布流程与 GitHub 工具使用clang lld llvm是过去每个任务都要 apt 安装的 MSVC 交叉编译前置zstd服务于压缩相关流水线canvas/cairo 原生栈libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev——canvas/rsvg 原生模块编译要用的-dev头文件CLI 工具fd-find ripgrep imagemagick供 agent 与测试使用。**两个符号链接垫片shim**统一 Debian 二进制命名与调用方的预期Debian 把fd包成fdfind所以ln -sf $(command -v fdfind) /usr/local/bin/fd把它暴露为fdImageMagick 安装的是convert所以ln -sf /usr/bin/convert /usr/local/bin/magick暴露 v7 风格的magick名称。这两个垫片正是setup-system-deps在普通 runner 上会重建的东西rm -rf /var/lib/apt/lists/*删除 apt 索引以缩小镜像层。bunENV BUN_INSTALL/usr/local 安装RUN。设置BUN_INSTALL/usr/local后官方安装脚本会把二进制放到/usr/local/bin/bun——这个目录本就在所有用户的PATH上所以 bun 是系统级的无需任何 per-user shell 初始化。版本通过bun-v${BUN_VERSION}锁定bun --version在安装损坏时会让构建直接失败。仓库的 .github/actions/bun-install/action.yml 会额外做一层版本对齐校验它读取package.json中packageManager字段的bunx.y.z引脚与镜像内bun --version比对。若镜像内 bun 与仓库引脚不一致例如镜像更新滞后该动作会为当前任务单独安装引脚版本——因为 bun 版本偏差会扰动对版本敏感的代码生成如gen:tool-views和测试运行器行为。固定版本的原生构建辅助工具两个 rootRUN。sccache以版本锁定的 GitHub release 压缩包下载并安装到/usr/local/binZig 以固定 release 归档下载、解压到/opt并通过符号链接暴露为/usr/local/bin/zig。烘焙这两者后自托管路径上每任务的mozilla-actions/sccache-action与mlugg/setup-zig下载就消失了。cmake ninja两个 rootRUN。为原生 C 依赖服务audiopus_sys通过 CMake 构建捆绑的 libopusMSVC 交叉构建用 Ninja 生成。版本与.github/actions/ensure-cmake动作锁定的版本一致后者在这些工具已存在时直接 no-op。bazelisk 预热 Bazel。BAZELISK_HOME/opt/bazelisk被设为全局目录预热的bazelisk version在构建期就把固定版本 Bazel 下载进BAZELISK_HOME运行期任务永远不需要再抓取。随后chmod -R arX使其对runner用户可读可执行并清理 root 的 Bazel 缓存。最后一个install -d -o 1001 -g 1001 -m 0755 /home/runner/.cache预先以 runner 用户UID 1001拥有~/.cache——否则 kubelet 会以 root 创建该目录作为omp-bazel-reposubPath 挂载点的父目录破坏 Bazel 默认 output_user_root 等兄弟目录的权限。Rust 工具链USER runner rustupRUN。工具链以任务实际执行的runner用户身份安装这样 cargo/rustc 归任务所有且无需 sudo 即可见。RUSTUP_HOME/CARGO_HOME钉在/home/runner下~/.cargo/bin前置到PATH。rustup 把固定 nightly 装为默认工具链--profile minimal随后补装clippy、rustfmt、rust-analyzer组件以及aarch64-unknown-linux-gnuLinux arm64和x86_64-pc-windows-msvcWindows 交叉两个 target。同一层还cargo install了cargo-nextest、cargo-zigbuild、cargo-xwin三个原生辅助 CLI自托管原生构建路径不再逐任务抓取这些工具。因为默认工具链就是带这些组件/target 的固定 nightlyCI 里对应的 Rust setup 步骤自然退化为 no-op——这就是预热启动warm-start的收益所在。3. 构建、导入与滚动发布reload.sh全流程3.1 主机侧脚本构建上下文位于/root/omp-kata-runner-image/其中reload.sh完成整个周期构建 → 镜像内冒烟测试 → 导入 k3s containerd → 把 ARC 指向新 tag → 校验上线。它幂等且对未变更的重建是缓存命中的、近乎瞬时。以下脚本来自文档的逐字复刻/root与 kubeconfig 路径为真实主机路径#!/usr/bin/env bash # Rebuild the preloaded omp-kata runner image, import it into k3s containerd, # point the ARC runner scale set at it, and roll it out. Idempotent: safe to # re-run after editing ./Dockerfile. Docker layer cache makes an unchanged # rebuild near-instant. # # ./reload.sh # build tag omp-kata-runner:YYYY-MM-DD-HHMMSS # ./reload.sh 2026-06-20 # build tag omp-kata-runner:2026-06-20 # ./reload.sh foo:bar # build an explicit repo:tag set -euo pipefail export KUBECONFIG/etc/rancher/k3s/k3s.yaml cd $(dirname $0) arg${1:-$(date %Y-%m-%d-%H%M%S)} case $arg in *:*) IMAGE$arg;; *) IMAGEomp-kata-runner:$arg;; esac echo [1/5] building $IMAGE DOCKER_BUILDKIT1 docker build -t $IMAGE -t omp-kata-runner:preloaded . echo [2/5] verifying baked tools docker run --rm --entrypoint bash $IMAGE -lc set -e for b in gh fd rg magick bun cargo rustc pkg-config clang lld sccache zig cargo-nextest cargo-zigbuild cargo-xwin; do command -v $b /dev/null || { echo MISSING: $b; exit 1; } done echo tools OK | bun $(bun --version) | rust $(rustc --version) | sccache $(sccache --version | awk \{print $2}\) | zig $(zig version) | gh $(gh --version | head -1 | cut -d\ \ -f3) echo [3/5] importing into k3s containerd (k8s.io namespace) docker save $IMAGE | k3s ctr -n k8s.io images import --platform linux/amd64 - echo [4/5] pointing ARC runner scale set at $IMAGE sed -i s#image: omp-kata-runner:.*#image: $IMAGE# /root/arc-omp-values.yaml helm upgrade omp-kata --namespace arc-runners --version 0.14.2 \ -f /root/arc-omp-values.yaml \ oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set /dev/null echo [5/5] verifying rollout live$(kubectl get autoscalingrunnerset omp-kata -n arc-runners -o jsonpath{.spec.template.spec.containers[0].image}) echo ARC runner image is now: $live [ $live $IMAGE ] echo OK: reloaded $IMAGE || { echo MISMATCH: expected $IMAGE; exit 1; }不带参数运行即自动生成带日期的 tagcd /root/omp-kata-runner-image ./reload.sh3.2 五步逐一拆解Preamble。set -euo pipefail在首个错误处中止KUBECONFIG指向 k3s admin 配置cd进入构建上下文。tag 由$1解析无参数 → 时间戳 tagomp-kata-runner:YYYY-MM-DD-HHMMSS含冒号的参数foo:bar→ 显式repo:tag其余 → 作为omp-kata-runner:的后缀。[1/5] 构建。DOCKER_BUILDKIT1 docker build打两个 tag不可变的$IMAGE带日期和移动的omp-kata-runner:preloaded别名。BuildKit Docker 层缓存让未变更的重建近乎瞬时。[2/5] 校验烘焙工具。以 bash 入口运行新构建的镜像断言每个期望的二进制都在PATH上gh fd rg magick bun cargo rustc pkg-config clang lld sccache zig cargo-nextest cargo-zigbuild cargo-xwin任何一个缺失即让整个脚本失败随后打印关键版本元组bun / rust / sccache / zig / gh。这一步在任何东西接触集群之前就能捕获坏的 apt 集合、缺失的垫片或错误的工具链引脚。[3/5] 导入 k3s containerd。docker save $IMAGE | k3s ctr -n k8s.io images import --platform linux/amd64 -把镜像 tarball 从 Docker daemon 直接流入 k3s自带的 containerd位于k8s.io命名空间——这正是 kubelet 拉取镜像的命名空间。--platform linux/amd64匹配主机架构。注意docker save只给了带日期的$IMAGE所以只有带日期的 tag 被导入:preloaded别名始终只是 docker 本地的便利标签从不被导入、也不被 ARC 引用。[4/5] 把 ARC 指向新 tag。sed -i把/root/arc-omp-values.yaml中唯一的image: omp-kata-runner:...行改写为新 tag然后helm upgrade用钉在0.14.2的 chart 重新渲染 runner scale set。该 values 文件即 runner Pod 模板详见 infra/docs/04-arc-and-caching.md。[5/5] 校验上线。通过kubectl ... jsonpath从存活的autoscalingrunnerset读回镜像并断言等于$IMAGE打印OK或非零退出打印MISMATCH。此时间点之后创建的新临时 runner Pod 将从新镜像启动进行中的任务在旧镜像上跑完scale set 是 scale-to-zero会很快排空。3.3 从仓库驱动SSH 封装reload-runner.sh你不必在主机上保留reload.sh。仓库随附受版本控制的 Dockerfile 外加一个 SSH 驱动的封装脚本可从 checkout 远程执行整个发布流程infra/runner.Dockerfile——镜像定义权威来源infra/reload-runner.sh——把该 Dockerfile 复制到主机然后优先走直接 containerd 构建路径按需在远端构建目录下引导固定版本的buildkitdbuildctlnerdctl直接构建进 k3s 的k8s.io命名空间从该镜像仓库冒烟测试再helm upgradeARC。设置BUILD_BACKENDdocker可强制走传统的docker builddocker save | ctr images import路径。主机从不被硬编码用CI_HOST指向你的节点CI_HOSTCI_HOST ./infra/reload-runner.sh # dated tag CI_HOSTCI_HOST ./infra/reload-runner.sh 2026-06-20 # explicit tag它沿用与主机脚本相同的默认值远端构建目录、ARC values 路径、release 名、命名空间、chart 版本每个都可通过脚本头部注释列出的环境变量覆盖。仓库内脚本还额外支持这些运维旋钮默认值即参考部署取值环境变量默认值含义CI_HOST必填CI 主机的 ssh 目标REMOTE_CTX/root/omp-kata-runner-image远端 Dockerfile 构建目录ARC_VALUES/root/arc-omp-values.yaml远端 ARC scale-set helm values 文件ARC_RELEASEomp-katarunner scale set 的 helm release 名ARC_NAMESPACEarc-runnersscale set 所在命名空间ARC_CHART_VERSION0.14.2gha-runner-scale-setchart 版本KUBECONFIG_REMOTE/etc/rancher/k3s/k3s.yaml主机上的 kubeconfig 路径BUILD_BACKENDautoauto|containerd|dockerCONTAINERD_SOCKET_REMOTE/run/k3s/containerd/containerd.sock远端 containerd socketNERDCTL_VERSION2.1.6按需引导的 nerdctl 版本BUILDKIT_VERSION0.25.1按需引导的 BuildKit 版本RUNNER_MAX_RUNNERS8最大并发 Kata runner Pod 数RUNNER_CPU_REQUEST3每个 runner 请求的 CPU 核数RUNNER_CPU_LIMIT8每个 runner 的 CPU 限制Kata 热插拔上限RUNNER_MEMORY_REQUEST10Gi每个 runner 请求的内存RUNNER_MEMORY_LIMIT14Gi每个 runner 的内存限制Kata 热插拔上限关于 Burstable 资源语义脚本头部注释明确说明runner Pod 刻意做成burstable 而非 guaranteed。requests 服务于调度器的装箱8 × 3 CPU / 10Gi 在 32 vCPU / 125 GiB 主机上还留有余量limits 则是每个 Kata VM 的热插拔上限——单个重原生构建任务仍能拿到 8 vCPU。此前 requestslimits 的配置把主机钉死在 4 个 runner 上任何 4 任务的工作流扇出都要排队数分钟。内存限制之和8 × 14Gi 112Gi必须保持在主机 125 GiB 之下——因为 Kata 场景下主机 OOM 会不可预测地杀死 VM。仓库脚本还在helm upgrade时用--set-string注入上述资源请求/限制并把maxRunners写回 values 文件同时幂等地给 runner Pod 模板追加bazel-remote-ci的envFrom条目该 secret 由 infra/bazel-remote/setup.sh 创建使 bazel-remote 缓存凭据到达每个 runner Pod。最终校验不仅比对存活镜像 tag还比对maxRunners与四元组资源值全部匹配才打印OK。4. 为什么直接导入 k3s containerd而不是走镜像仓库这是一个单节点集群runner 镜像的唯一消费方就是同一节点上的 kubelet/containerd。引入镜像仓库意味着要多运行、加固、认证一个服务而收益为零。因此docker save | k3s ctr -n k8s.io images import把镜像直接放进 k3s 调度所用的 containerd 实例。containerd 会把短引用omp-kata-runner:tag在其存储中规范化为docker.io/library/omp-kata-runner:tag已核实导入的 tag 都以该前缀出现。ARC Pod 模板设置imagePullPolicy: IfNotPresent。因为镜像已在本机kubelet直接使用本地副本、绝不发起 pull——没有仓库、没有 pull 凭据、也没有仓库出口流量而 runner 出口封锁策略在 infra/docs/04-arc-and-caching.md 中本来就会阻断这类流量。代价镜像必须在每个调度 runner 的节点上重新导入。这里恰好只有一个节点所以一次重新发布 重建 重新导入下一个任务的微虚拟机冷启动但依赖从本地存储热载。5. 标签约定Tag可变性是否导入 containerd是否被 ARC 引用用途omp-kata-runner:YYYY-MM-DD-HHMMSS不可变是是有记录的构建runner 实际启动的镜像omp-kata-runner:preloaded移动否否docker 本地的最近一次构建别名默认reload.shtag 是时间戳date %Y-%m-%d-%H%M%S。你也可以传仅日期的 tag./reload.sh 2026-06-20或显式repo:tag。ARC 始终钉住不可变的日期 tag从不使用:preloaded。这让发布可复现也让回滚极其简单把 values 中的 image 行sed回上一个日期 tag它仍在本地存储中再helm upgrade即可。文档写作时的实况scale set 引用omp-kata-runner:2026-06-15-002621在 containerd 中存为docker.io/library/omp-kata-runner:2026-06-15-002621。6. 升级 bun / Rust / apt 集合并重新发布bun编辑 Dockerfile 中的ARG BUN_VERSION或传--build-arg BUN_VERSION...。Rust把ARG RUST_NIGHTLY改为新的固定 nightly。务必与仓库 CI 中dtolnay/rust-toolchainnightly步骤解析出的版本保持一致这样 CI 工具链安装继续保持 no-op。若镜像内 bun 与 .github/actions/bun-install/action.yml 读取的packageManager引脚不一致该动作会为任务安装引脚版本以兜底。apt 集合编辑apt-get install行。必须同步修改.github/actions/setup-system-deps若新增了被探测的工具还要同步其探测块——目前是fd、rg、magick、pkg-config --exists cairo pango。重新发布cd /root/omp-kata-runner-image ./reload.sh未变更层命中缓存、重建近乎瞬时烘焙工具校验为改动把关导入/helm-upgrade/校验三步把新 tag 发布出去。下一个任务的微虚拟机以更新后的工具链热启动。7. 验证7.1 烘焙工具校验任意 tagreload.sh的第 2 步在每次构建时都会执行。单独复检已有 tagdocker run --rm --entrypoint bash omp-kata-runner:preloaded -lc set -e for b in gh fd rg magick bun cargo rustc pkg-config clang lld sccache zig cargo-nextest cargo-zigbuild cargo-xwin; do command -v $b /dev/null || { echo MISSING: $b; exit 1; } done echo tools OK | bun $(bun --version) | rust $(rustc --version) | sccache $(set -- $(sccache --version); echo $2) | zig $(zig version) | gh $(set -- $(gh --version | head -1); echo $3) 注意当前仓库的权威 Dockerfile 与reload-runner.sh的校验列表已经扩展还包括zstd、cmake、ninja、bazelisk、bazel——以 infra/reload-runner.sh 中的verify_baked_tools函数为准。确认存活 ARC 引用及 tag 确实存在于 k3s 镜像仓库均为只读操作export KUBECONFIG/etc/rancher/k3s/k3s.yaml kubectl get autoscalingrunnerset omp-kata -n arc-runners \ -o jsonpath{.spec.template.spec.containers[0].image}{\n} k3s ctr -n k8s.io images ls | grep omp-kata-runner7.2 Kata 微虚拟机启动验证上面的烘焙工具校验是在普通 docker 下运行镜像不能证明镜像能在 Kata QEMU/KVM 微虚拟机里启动。要验证这点启动一个带runtimeClassName: kata-qemu的临时 Pod该 RuntimeClass 由 infra/docs/02-kata-runtime.md 配置同时确认依赖与guest内核export KUBECONFIG/etc/rancher/k3s/k3s.yaml kubectl run preload-verify -n arc-runners --restartNever \ --imageomp-kata-runner:2026-06-15-002621 \ --overrides{spec:{runtimeClassName:kata-qemu}} \ --command -- bash -lc uname -r; bun --version; rustc --version; magick -version | head -1 kubectl logs preload-verify -n arc-runners kubectl delete pod preload-verify -n arc-runners使用当前存活的 tag或任意已导入的 tag。uname -r应显示 Kataguest内核一个 6.x 的vmlinux.container构建而不是主机内核——这证明镜像确实在独立的微虚拟机中启动——而bun/rustc/magick各行为确认烘焙工具链在 VM 内存在。这里的kubectl run是整个流程中唯一创建集群对象的步骤如示例所示用完即删。参考部署中主机运行 CentOS Stream 10 内核7.0.10-1.el10.elrepo.x86_64Kata guest 运行6.18.28-194uname -r输出不同内核字符串即证明 workload 真实运行在独立 guest 内核中对照实验不带 RuntimeClass 的同一 Pod 在 runc 下会打印主机内核。Kata 运行时本身还配套了 infra/tune-kata-runtime.sh 这个 SSH 驱动脚本用于把default_vcpus/default_memory启动下限、guest 与 virtiofsd 的开放文件数上限sysctl.fs.nr_open与--rlimit-nofile均为 8388608以及 virtiofsd 线程池--thread-pool-size4写入configuration-qemu.toml并对新kata-qemuPod 做一次完整冒烟验证——其验证逻辑会从kubectl exec的 guest 侧和/proc/virtiofsd/limits主机侧双向核对文件描述符上限。小结为什么Kata 微虚拟机每个任务冷启动、任务后即销毁把依赖安装留在任务运行时等于每次重复支付 apt/bun/rustup/工具下载成本预加载镜像把它移到构建期任务启动即依赖热载。怎么构建infra/runner.Dockerfile在官方 actions-runnerUbuntu 24.04之上叠加系统依赖cairo/pango 栈、fd/rg/magick 垫片、gh、系统级 bun、固定版本 sccache/Zig/cmake/ninja、预热 bazelisk/Bazel以及以 runner 用户安装的固定 Rust nightly 组件 交叉 target cargo 原生辅助 CLI。怎么发布reload.sh主机侧/infra/reload-runner.shSSH 驱动执行 构建 → 烘焙工具校验 → 导入 k3s containerdk8s.io命名空间→helm upgrade指向 ARC → 读回存活autoscalingrunnerset校验全程幂等。为什么免仓库单节点、唯一消费方是本机 kubelet直接ctr importimagePullPolicy: IfNotPresent最简还顺带规避了出口封锁。怎么验证command -v遍历烘焙工具、kubectl/k3s ctr只读核对引用以及带kata-qemuRuntimeClass 的临时 Pod 检查 guest 内核与 VM 内工具版本。继续阅读 infra/docs/04-arc-and-caching.md了解 ARC 如何接入共享的 bazel-remote / Bun / Cargo 缓存存储并锁定 runner 出口。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价