ci: reuse G14 tools image for GitOps jobs
This commit is contained in:
@@ -24,6 +24,7 @@ G14 是 HWLAB 的旁路 DEV 集群目标。G14 CI/CD 必须只作用于 G14 k3s
|
||||
- 默认 registry prefix 是 `127.0.0.1:5000/hwlab`,用于 G14 单节点 k3s 的 node-local registry。
|
||||
- 默认 CI/CD proxy 是 G14 本机 `http://127.0.0.1:10808` / `socks5h://127.0.0.1:10808`。Tekton CI step、Docker-in-Docker sidecar 和 publish step 都注入 proxy/no_proxy;publish step 必须先在 DIND 内 `docker pull $HWLAB_DEV_BASE_IMAGE`,再进入 DEV base-image preflight、build 和 registry push,保证 npm、base image 拉取和 registry push 走 G14 本机代理边界。
|
||||
- `ci-json` 不允许每次运行时重新 `apt-get install` 或 `npx playwright install --with-deps`。它必须使用已经预热的 CI 基础镜像,当前默认由 `scripts/g14-gitops-render.mjs` 固定为 `mcr.microsoft.com/playwright@sha256:b0ab6f3cb99aa7803adbc14d9027ec1785fc6e433b97e134e0f8fe61683b6b53`;该镜像在 G14 k3s/containerd 中已缓存,包含 Node、npm、Git、Python3、OpenSSH、curl、Playwright 系统依赖和 `/ms-playwright/chromium-1217`。脚本启动时必须输出 `ci-base-image` 和 `playwright-cache-check` 结构化日志;缺少工具或 Chromium cache 时直接失败并修基础镜像,不能回退到 runtime apt 下载。若以后需要 Node 22 固定版本,先构建并推送 G14 registry 内的 Node22+Playwright runner 镜像,再修改 `HWLAB_G14_CI_JSON_IMAGE`/render 默认值。
|
||||
- Poller、control-plane reconciler 和 image publish step 也不允许每次运行时 `apk add`。当前 G14 registry 固定工具镜像是 `127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-v1`,包含 Node 22、npm、Git、OpenSSH、curl、Python3 和 Docker CLI;生成的脚本只做 proxy preflight 与工具存在性检查。若需要升级工具,先在 G14 构建/推送新的工具镜像,再修改 `HWLAB_G14_CI_TOOLS_IMAGE`/render 默认值并由 reconciler apply。
|
||||
- 任何依赖下载阶段都必须有可观测诊断。生成的 Tekton 脚本在 apt/apk、npm、Playwright browser、Docker base image pull 和 GitOps promote 之前输出结构化 `dependency-proxy-probe`、`dependency-curl-probe` 或 `dependency-download-*` 日志,至少包含 phase、目标 URL/镜像、脱敏 proxy、首包耗时、总耗时、下载字节数和速度。CI/CD 卡在下载时,先用这些日志判断是 proxy 不可达、目标源慢、DNS/首包慢还是下载吞吐低,再决定是否切换 G14 代理节点或预热镜像;不能只凭 PipelineRun Running 时长判断业务测试失败。
|
||||
|
||||
常用命令:
|
||||
|
||||
@@ -19,6 +19,7 @@ const defaultProxyUrl = process.env.HWLAB_G14_PROXY_URL || "http://127.0.0.1:108
|
||||
const defaultAllProxyUrl = process.env.HWLAB_G14_ALL_PROXY_URL || "socks5h://127.0.0.1:10808";
|
||||
const defaultNoProxy = process.env.HWLAB_G14_NO_PROXY || "127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,192.168.0.0/16,.svc,.cluster.local,kubernetes.default.svc,registry.hwlab-ci.svc,hwlab-registry.hwlab-ci.svc";
|
||||
const ciJsonRunnerImage = process.env.HWLAB_G14_CI_JSON_IMAGE || "mcr.microsoft.com/playwright@sha256:b0ab6f3cb99aa7803adbc14d9027ec1785fc6e433b97e134e0f8fe61683b6b53";
|
||||
const ciToolsRunnerImage = process.env.HWLAB_G14_CI_TOOLS_IMAGE || "127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-v1";
|
||||
const sourceCommitPattern = /^[a-f0-9]{7,40}$/u;
|
||||
|
||||
function proxyEnv() {
|
||||
@@ -455,8 +456,9 @@ function ciJsonScript(ci) {
|
||||
function publishScript() {
|
||||
return `#!/bin/sh
|
||||
set -eu
|
||||
${dependencyProxyProbeScript("image-publish-pre-apk", "https://dl-cdn.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz")}
|
||||
apk add --no-cache docker-cli git openssh-client python3
|
||||
${dependencyProxyProbeScript("image-publish-proxy-preflight", "http://deb.debian.org/debian/dists/bookworm/InRelease")}
|
||||
echo '{"event":"ci-base-image","phase":"image-publish","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'
|
||||
for tool in node npm git python3 ssh docker; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"image-publish","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
|
||||
export DOCKER_HOST=unix:///var/run/docker.sock
|
||||
export HWLAB_CI_ARTIFACT_RUN_ID="$(context.pipelineRun.name)"
|
||||
export HWLAB_CI_ARTIFACT_RUN_OWNER="tekton"
|
||||
@@ -545,8 +547,9 @@ echo '{"status":"pushed","gitopsBranch":"'"$(params.gitops-branch)"'","sourceRev
|
||||
function controlPlaneReconcileScript() {
|
||||
return `#!/bin/sh
|
||||
set -eu
|
||||
${dependencyProxyProbeScript("control-plane-pre-apk", "https://dl-cdn.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz")}
|
||||
apk add --no-cache git openssh-client ca-certificates
|
||||
${dependencyProxyProbeScript("control-plane-proxy-preflight", "http://deb.debian.org/debian/dists/bookworm/InRelease")}
|
||||
echo '{"event":"ci-base-image","phase":"control-plane-reconciler","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'
|
||||
for tool in node npm git python3 ssh curl; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"control-plane-reconciler","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
|
||||
mkdir -p /root/.ssh
|
||||
cp /workspace/git-ssh/ssh-privatekey /root/.ssh/id_rsa
|
||||
chmod 600 /root/.ssh/id_rsa
|
||||
@@ -653,8 +656,9 @@ NODE
|
||||
function pollerScript() {
|
||||
return `#!/bin/sh
|
||||
set -eu
|
||||
${dependencyProxyProbeScript("poller-pre-apk", "https://dl-cdn.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz")}
|
||||
apk add --no-cache git openssh-client ca-certificates
|
||||
${dependencyProxyProbeScript("poller-proxy-preflight", "http://deb.debian.org/debian/dists/bookworm/InRelease")}
|
||||
echo '{"event":"ci-base-image","phase":"poller","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'
|
||||
for tool in node git ssh curl; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"poller","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
|
||||
mkdir -p /root/.ssh
|
||||
cp /workspace/git-ssh/ssh-privatekey /root/.ssh/id_rsa
|
||||
chmod 600 /root/.ssh/id_rsa
|
||||
@@ -923,7 +927,7 @@ function tektonPipeline(ci) {
|
||||
}],
|
||||
steps: [{
|
||||
name: "publish",
|
||||
image: "node:22-alpine",
|
||||
image: ciToolsRunnerImage,
|
||||
env: [{ name: "DOCKER_HOST", value: "unix:///var/run/docker.sock" }, ...proxyEnv()],
|
||||
volumeMounts: [{ name: "docker-run", mountPath: "/var/run" }],
|
||||
script: publishScript()
|
||||
@@ -1045,7 +1049,7 @@ function tektonPollerCronJob(args) {
|
||||
dnsPolicy: "ClusterFirstWithHostNet",
|
||||
containers: [{
|
||||
name: "poll",
|
||||
image: "node:22-alpine",
|
||||
image: ciToolsRunnerImage,
|
||||
imagePullPolicy: "IfNotPresent",
|
||||
env: [
|
||||
...proxyEnv(),
|
||||
@@ -1111,7 +1115,7 @@ function tektonControlPlaneReconcilerCronJob(args) {
|
||||
dnsPolicy: "ClusterFirstWithHostNet",
|
||||
containers: [{
|
||||
name: "reconcile",
|
||||
image: "node:22-alpine",
|
||||
image: ciToolsRunnerImage,
|
||||
imagePullPolicy: "IfNotPresent",
|
||||
env: [
|
||||
...proxyEnv(),
|
||||
|
||||
Reference in New Issue
Block a user