Skip to content

feat: distribute bazel JKS truststore via squid-ca-cert (Vault) - #19

Open
ccijunk wants to merge 25 commits into
mainfrom
feat/jks-truststore
Open

feat: distribute bazel JKS truststore via squid-ca-cert (Vault)#19
ccijunk wants to merge 25 commits into
mainfrom
feat/jks-truststore

Conversation

@ccijunk

@ccijunk ccijunk commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

Distribution of the Bazel/JVM truststore (squid-bazel-trust.jks) from Vault via the squid-ca-cert SecretDefinition, plus the 0.1.6 cache strategy (per-addressing refresh_pattern rules) and traffic-test tooling fixes.

Changes

  • deploy/chart/templates/secret-definition.yaml: squid-ca-cert keysMap 增加 squid-bazel-trust.jks(Vault property squid_bazel_trust_v3_jks),随 CA 一起分发到 buildkitd / ascend-gha-runners / nv-action / squid
  • deploy/chart/values.yaml: caBundleKey/caPublicKey 对齐线上 v3 名(squid_ca_bundle_v3_pem/squid_ca_v3_pem),新增 caTruststoreKey
  • deploy/chart/templates/configmap.yaml + Chart.yaml: cache strategy 0.1.6(0.1.5 → 0.1.6)
    • immutable 规则只给内容寻址的 A 类制品(.whl/.crate/.deb10080 100% 525600 ignore-reload override-expire ignore-no-store
    • 可变 B 类(.pth/.pt/.safetensors、codeload refs/heads、索引页)降级 0 20% 4320(尊重 LM 老化)
    • codeload refs/tags + github releases/download → immutable
    • 移除 squid 7.6 不支持的 ignore-no-cache / override-vary(ERROR/Unknown option)、删除失效 .docker.io 规则、域名转义 \\.pypi\\.org 等、max=525600(消除 cropped 告警)
  • deploy/CACHE-STRATEGY.md(新增): refresh_pattern 机制、CI 流量 A/B 源站分类(内容寻址 vs 可覆盖)、13 条规则逐条审计、推荐配置形态
  • deploy/tool → traffic-test/tool: 测试目录重命名(typo fix),新增 10-16 用例
  • traffic-test/run-tool-traffic.sh: wait_case 改为等待 Volcano Job phase(vj 分批调度导致窗口污染),修复缺失 -n $NS;新增 wait_pods_done(pods 可能比 vj phase 晚结束);LOG_DIR 改为可配置环境变量
  • traffic-test/analyze-tool-traffic.py: awk printf %d 将 >2GB 字节计数截断为负值 → %.0f;窗口终点 DONE+180s 捕获分批调度尾部流量;HIT% 与 Prometheus client_out/origin_in 交叉验证
  • traffic-test/tool/01-pip.yaml: set -o pipefail(避免 tail 掩盖失败)、PIP_CERT 去重;jsdelivr CDN 替换为 gh-proxy 获取 requirements.txt
  • traffic-test/tool/03-github.yaml: 移除 github.com 可达性探测(应要求删除,无意义)
  • traffic-test/tool/cachedemo.yaml: hf-mirror.com 加入 NO_PROXY
  • traffic-test/tool/08-bazel.yaml: JKS 经 Vault 同步后是 base64 文本(KV v2 只存字符串),postStart 解码到 /etc/squid-bazel-trust/squid-bazel-trust.jks 再写 .bazelrc
  • traffic-test/run-per-case-wlcb.sh(新增): wlcb-001 顺序逐 case 监控 wrapper,每 case 独立启动 Prometheus 监控并收集流量 TSV
  • traffic-test/WLCB-001-TRAFFIC-REPORT.md(新增): wlcb-001 warm cache 16 工具流量模式分析报告,含逐 case 客户端/源站/命中率/模式分类
  • deploy/DEPLOY.md: 更新 §1.2 / §2.3 / §2.5(secret 表、单卷 items 挂载、Vault base64 说明)

关键坑

  1. Vault KV v2 只存字符串,二进制 JKS 写入时自动 base64 → 挂载出来是 base64 文本,需消费端解码一次
  2. K8s secret 卷固定只读(CRI 挂载 ro),解码产物需写到容器层目录或 /tmp
  3. Bazel JVM 忽略 JAVA_TOOL_OPTIONS,trustStore 参数只能走 .bazelrc startup
  4. squid 7.6 移除 ignore-no-cacheoverride-vary 是未知选项(ERROR);override-expire/ignore-reload/ignore-no-store 为 legacy WARNING 但有效
  5. ConfigMap 经 subPath 挂载不热更新,配置变更须 rollout restart(kubelet 不会重载 subPath 文件)
  6. Volcano 分批调度(minAvailable=1):vj 状态 Completed 可能早于最后批次 pods 流量结束(差 1-3 分钟),analyze 窗口需加尾部缓冲,否则 case 窗口内只剩背景流量 → HIT% 假性为 0
  7. 背景 TLS 噪音:未知客户端(源 IP 10.0.0.209/10.0.0.225,不在任何 pod/Service 列表)每 1-5s 对 api.github.com:443 发 CONNECT + TLS 失败(cache.log A000412 = SSL alert bad certificate),每分钟 ~10-20 条 24/7 持续,与 case 流量无关

Test (gy-006, 0.1.6 复测)

case 0.1.4 0.1.6
01 pip 99.9%(7.5GB out,回源 0.1%)
03 git clone (→gh-proxy) 0% 0.0%(git smart-HTTP pack 为 POST,结构性不可缓存;codeload/releases 规则未被此 case 覆盖,未实测)
05 goproxy 89.7% 100%
08 bazel 94.5% 99.9%(7.4GB HIT)
09 npm 95.4% 99.9%
wget .pth 100% 93.3%(按设计降级,尊重 LM 老化)
  • 08-bazel JKS: DIRECT 26761ms vs SQUID 25546ms,1.0x FASTER(两个变体均 Succeeded)
  • case 01(pip)曾误报 0%:实为 Volcano 分批调度导致 analyze 窗口与真实流量错位(窗口内只有背景 api.github CONNECT),DONE+180s 修复后实测 99.9% HIT
  • case 03 流量经 squid 到 gh-proxy.test.osinfra.cn(03-github.yaml 用 insteadOf 把 github.com 重写到 gh-proxy 镜像),client_out/origin_in 交叉验证全程走代理

wlcb-001 测试 (warm cache, 16 工具)

traffic-test/WLCB-001-TRAFFIC-REPORT.md — 逐 case 流量模式分析。

模式 Cases 特征
平稳流 01-pip, 02-apt, 03-github, 07-cmake, 08-bazel, 09-npm, 11-conda, 12-uv, 15-pnpm, 16-yum 10 个 case,命中率 >91%,源站极低
短时突发 04-curl 命中率 97.5%,源站 1.2 MB/s
低命中直连 06-wget 命中率仅 1.1%,几乎全透传
长尾衰减 05-obsutil 命中率从 96%→2.4%,耗时 760s
下载→编译 10-cargo 650s,前 170s 下载后 480s 编译
快速脉冲 14-git-lfs 35s 完成,命中率 99.7%
跳过 13-huggingface 用户要求跳过

关键发现:

  • 15 个可用 case 中 12 个命中率 >91%,warm cache 效果显著
  • obsutil(OBS 对象存储)和 wget(动态 URL)是最差的缓存场景
  • pip 117s (56 MB/s) vs uv 55s (13.8 MB/s) — uv 虽带宽更低但完成更快

happyaron and others added 16 commits August 12, 2026 11:05
只依赖已有数据源,不引入新组件:
- 各 Squid 的 access.log(命中/字节/客户端/bump-splice)
- HAProxy stats CSV :8404(后端分发与健康)
- cgroup cpu.stat(CPU 秒 → 每 GB CPU 成本)

按 begin/end 框定区间输出四层指标: Squid 缓存效果 / SSL Bump CPU 成本 /
HAProxy 分发健康 / 客户端归因。

采集上有三个坑,都在脚本里处理了:

1. 必须框定区间。累计值把预热、健康检查、历史负载混在一起,
   算出来的命中率和 CPU/GB 没有意义。

2. 健康检查要剔除。每 3 秒 × 3 后端 × 2 节点,日志里是 NONE_NONE/400、
   方法为 -,不滤掉会把请求数和命中率彻底冲淡。

3. CONNECT 隧道不是对象请求。实测 bump 的 CONNECT 记录是
   NONE_NONE/200 bytes=0,只是建隧道,真正负载会作为解密后的
   GET https://... 再记一行 —— 混进去会凭空翻倍请求数并稀释命中率。
   splice 则相反,是 TCP_TUNNEL 带真实字节且不可能命中。
   最初的实现把这两者搞混了,4 次下载被记成 8 个请求。

实测(4 个从未取过的包,分别跑纯 MISS 与纯 HIT 两个窗口):
  纯 MISS: 命中率 0%   , 44.42 CPU秒/GB
  纯 HIT : 命中率 76.4%, 37.13 CPU秒/GB

注意这个小样本(4 请求、低并发)不足以复现 k8s 压测里
「纯 HIT 比 MISS 更吃 CPU」的结论 —— 那是 N=120 高并发下 TLS 批量加密
打满 CPU 的效应,低并发时开销主要在握手和证书生成。
脚本的作用是提供采集手段,系数仍需在目标并发下实测。

归因层依赖 PROXY protocol(见 PR #9),未生效时脚本会给出提示。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
原先只报一个「每 GB CPU」,这个数不可信,有两个问题:

1. CPU 不与字节成正比。它由「每请求固定成本」(TLS 握手、证书生成、缓存查找)
   和「每字节边际成本」(加密、I/O)两项构成。只报每 GB 会把固定成本摊进字节,
   于是同一套环境下这个数随对象大小漂移 —— 实测 14MB 对象约 28 秒/GB,
   58KB-6MB 混合约 37-44 秒/GB,相差 1.6 倍。当成常数用会算错容量。

2. 窗口里的空闲 CPU 被算进了请求成本。Squid 零流量时也在烧 CPU:
   健康检查(每3秒×3后端×2节点)、日志写入、缓存索引维护。
   实测空闲基线约 0.004 CPU秒/秒(三副本合计)。窗口越稀疏(比如里面有大量
   docker run 启动等待时间),这部分占比越高,实测能占到测量值的三分之一。

改法:
- 新增 metrics.sh baseline [秒]: 零负载时测一次空闲 CPU 速率,存 .metrics-baseline
- end 时按窗口时长扣除空闲基线,输出「原始 − 基线 = 归因」
- 拆成两项输出: 每请求 CPU / 每 GB CPU, 并同时给出平均对象大小
- 明确标注每 GB CPU 不是常数, 并给出容量公式:
    核数 ≈ 请求速率 × 每请求CPU + 吞吐(GB/s) × 每GB CPU
  拟合这两项需要在不同对象大小/并发下各跑一个窗口

顺带纠正之前基于这个指标得出的结论: 早先用「纯 MISS 44.42 秒/GB vs
纯 HIT 37.13 秒/GB」比较两者 CPU 成本是无效的 —— 两个窗口对象集不同,
差值又落在空闲基线污染的范围内,不足以支撑任何 HIT/MISS 结论。
低并发本来也测不出 k8s 压测里 N=120 时「HIT 比 MISS 更吃 CPU」的效应,
脚本里已加注,避免再用小样本去推翻高并发结论。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
两层都从已经在采集的 access.log 字段算出来,不需要新数据源。

延迟层(字段 $2 耗时ms),按 HIT/MISS 分开出 p50/p95/p99:
- 均值会被长尾骗过去。实测同一个 14MB 对象的 TCP_HIT 耗时分布为
  133/246/251/256/273/5106 ms —— 同样是命中,最慢的比最快的高 38 倍。
  这种尾巴用两次 wall-clock 采样(用例 04 现在的做法)根本看不见。
- 按命中结果分开是必要的: MISS 延迟基本由源站带宽支配,HIT 延迟才是
  缓存真正买到的东西,混在一起两者互相污染。
- 对在线业务而言 p99 才是用户实际感受,这是从「省了多少带宽」转向
  「用户等多久」时最先需要的指标。

错误层,关键是把代理故障与源站故障分开:
- 判据是层级字段: Squid 自己生成的错误是 HIER_NONE(压根没连上源站),
  真正到达源站再返回的错误带 HIER_DIRECT 等。
- 为什么重要: 源站 404(包不存在)是正常现象,不该告警;而 DNS 失败、
  连接失败、ACL 拒绝才是要告警的。k8s 压测里 120 并发中 31-37 个「失败」
  其实全是源站 404,不是 Squid 故障(见 reports/stress-benchmark-20260811.md)。
- 另外单列客户端中断(*_ABORTED)与隧道失败(CONNECT 阶段即失败)。

验证: 故意混入一个不存在的包,输出正确归类为「源站4xx 1 / 代理故障 0」。

实现上把窗口日志先落到临时文件再多趟分析,避免为每个指标重复 docker exec。

注意分位数的口径可以搬到生产,代码不能: Prometheus 要用预先分桶的
histogram,无法从计数器抓取值反算真实 p99。已在脚本头部注明。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
分层性能指标采集脚本:命中 / 延迟分位 / 错误分类 / 两项 CPU 成本
依据 PR #12(scripts/metrics.sh)的建议改造用例 04。旧版只打印首次(MISS)/
二次(HIT)两个孤立 wall-clock,看不见长尾、不分类错误、不测 CPU 成本。

新版用 metrics.sh begin/end 框定 MISS 与 HIT 两个窗口:
- 固定客户端 IP(balance source → 同一台 Squid)+ cache-busting URL,
  保证窗口1是真 MISS、窗口2是真 HIT(各 Squid 缓存独立、无 peer)
- 先测空闲 CPU 基线并在归因时扣除
- 保留 HTTP 200 真断言,分层指标作为信息输出

实测效果(本地 Compose):
- MISS p50=3638ms / 命中率0% / 每请求CPU 0.247s
- HIT  p50=130 p95=148 p99=149ms / 命中率100% / 每请求CPU 0.085s
- 缓存价值 = 延迟 28× 提速; CONNECT 隧道正确去重(未重复计数)
- 归因层正确检测到 Compose 侧无 PROXY protocol(#9)并提示

README 同步更新测试点表与预期输出。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
把 tests/04 的分层指标口径搬到 K8s(与 Compose 版 metrics.sh 完全同口径:
健康检查过滤 / CONNECT 去重 / HIER 错误分类 / HIT-MISS 延迟分位 / CPU 两项成本),
只把数据源从 docker+HAProxy 换成 kubectl exec(access.log、cgroup v1 cpuacct.usage)
+ kubectl get endpoints。

- k8s/metrics-k8s.sh: K8s 版采集(baseline/begin/end/now)
- k8s/latency-test.sh: 一键 driver(起 client pod → baseline → MISS/HIT 两窗口 → 清理),
  等价 Compose 的 tests/04
- .gitignore: 忽略 .metrics-k8s-{state,baseline}
- README: 新增「K8s 上的同款采集」小节

测试集群(test-husheng, squid StatefulSet 2/3 Ready)实测:
- MISS p50≈1000ms / 命中率0% ; HIT n=30 p50≈167 p95≈176 p99≈177ms / 命中率100%
- CONNECT 隧道正确去重(bump 1 / bump 30)
- HIT 每请求 CPU(0.177)略高于 MISS(0.140),方向与「HIT 重新加密更吃 CPU」一致
- 归因层直接显示真实客户端 pod 段 IP —— K8s Service 保留源 IP,无需 PROXY protocol

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 从 gmarmstrong/buildkit@proxy-chaining 编译镜像, 正对照/缓存/负对照三场景实测通过
- 关键结论: 无 cert 配置 → CA 经 SSL_CERT_FILE 走系统信任库, 实测成立;
  PULL+RUN 共用一套 env 是 BuildKit 既有标准行为, 与 deploy 的 splice+registry-proxy 互补
- 新增 buildkitd-6996.toml / docker-compose.6996.yml, 与 fork 版并列

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs(buildkit): 上游 PR #6996(env 变量式上游代理)端到端验证报告与部署资产
test: 分层指标取代两次采样(Compose 用例04 + K8s 同款采集,两套实跑)
…sults

- 3 new refresh_patterns: .crate / .zip / .pth|pt|safetensors
- helm upgrade REVISION 14 (squid-rpardini-0.1.4), ArgoCD ownership + kubelet
  volume-sync gotchas
- retest: cargo 11% -> ~95% hit, wget 94MB .pth TCP_HIT zero-origin

feat(chart): 0.1.4 — force-cache rules for cargo/model-weight traffic

- refresh_pattern for .crate (cargo), .zip, .pth/.pt/.safetensors (model weights)
- measured: cargo hit 11% -> ~95%, wget 94MB .pth TCP_HIT zero-origin (gy-006)
- verified via helm upgrade REVISION 14
JKS truststore (Bazel/JDK) fetched from Vault (secrets/data/ascend/ci)
and synced into squid-ca-cert SecretDefinition for CI namespaces
(buildkitd, ascend-gha-runners, nv-action, squid). Align caBundleKey/
caPublicKey to v3 vault properties.
@opensourceways-bot

Copy link
Copy Markdown

Welcome To opensourceways Community

Hey @ccijunk , thanks for your contribution to the community.

Bot Usage Manual

I'm the Bot here serving you. You can find the instructions on how to interact with me at Here . That means you can comment below every pull request or issue to trigger Bot Commands.

@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

@opensourceways-bot

Copy link
Copy Markdown

Linking Issue Notice

@ccijunk , the pull request must be linked to at least one issue.
If an issue has already been linked, but the needs-issue label remains, you can remove the label by commenting /check-issue .

…alid options

- immutable rules only for content-addressed/A-class artifacts (.whl/.crate/.deb)
- .zip/.tar.gz/.pth demoted to LM-aging (0/20%/4320): ref-addressed & overwritable
- codeload refs/tags + github releases/download get immutable; refs/heads short TTL
- remove dead .docker.io rule, unescape domains, max 525960->525600 (no cropped warning)
- add CACHE-STRATEGY.md (full per-rule audit + CI scenario analysis)
- wait_case: wait on Volcano Job phase (pods scheduled in batches polluted
  subsequent case windows); fix missing -n $NS
- analyze: awk printf %d truncated >2GB byte counters to -2^32 (%.0f)
- 01-pip: add set -o pipefail so pip failures are not masked by tail
@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

- analyze: window ends DONE+180s; Volcano marks Job Completed while
  late-batch pods still stream (case 01 window held only background
  api.github CONNECTs → false 0% HIT)
- run-tool-traffic.sh: wait_pods_done helper (pods may outlive vj phase)
- CACHE-STRATEGY.md §10.1: document Volcano batching, background TLS
  noise (A000412 = bad_certificate alert from unknown 10.0.0.209/225),
  epoch access.log timestamps
- verified case 01 (pip) = 99.9% HIT (7.5GB out, 0.1% origin)
@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

…data fallback

Document first-match-wins ordering: extension immutable rules (whl/crate/deb)
intercept artifacts before domain rules, so .pypi.org/.golang.org/.debian.org/
.ubuntu.com actually only fallback to index metadata + unclassified content.
Ordering-sensitive: moving domain rules above extension rules drops .deb/.whl
from immutable to 0 20% 4320.
@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

…& gitcode 0%

- CACHE-STRATEGY.md §10.2: squid 7.6 stable-build swapout race triggered by
  SWAPFAIL under cold-cache concurrency; SFS shared volume 92% full as amplifier;
  fixes: free registry-cache / collapsed_forwarding / aufs-disks; 7.6 is a stable
  tag (SQUID_7_6), not dev — no upstream fix yet
- TOOL-RESULTS.md: gitcode clone 0% (POST pack, structural); non-git paths
  WAF-blocked (418/403/verification page); single-case cold apt = 65.4% HIT
- run-tool-traffic.sh: wait_pods_done must 'seen' a pod before trusting zero
  running pods (vj may be Completed before any pod is scheduled)
@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

- run-tool-traffic.sh wait_pods_done: 'seen' must trigger on ANY pod
  (incl. Succeeded); previous version stuck 30min when pods finished
  before the first poll
- analyze-tool-traffic.py:
  - cluster clock offset (+128s observed) — timeline is local, access.log
    is cluster; without it every window is misaligned
  - drop DONE+180 tail (DONE is now precise; back-to-back cases made
    +180 swallow the next case's traffic) — clamp e to next SUBMIT
  - read access.log from PREVIOUS container stdout (current access.log
    is recreated on restart, ~2min only); pod-IP filtering removed
    (Volcano rebuilds pods, IPs no longer match)
- tool/03-github.yaml: curl raw.githubusercontent.com --max-time 120
  (was hanging forever without timeout)
@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

…probe

- 01-pip.yaml: replace jsdelivr CDN with gh-proxy for requirements.txt fetch
- 03-github.yaml: remove github.com reachability probe (meaningless per request)
- cachedemo.yaml: add hf-mirror.com to NO_PROXY
- run-tool-traffic.sh: make LOG_DIR configurable via env var
- run-per-case-wlcb.sh: new wrapper for sequential per-case monitoring on wlcb-001
@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

16-tool sequential run on wlcb-001 with per-case Prometheus monitoring.
Reports client/origin throughput, hitrate, and pattern classification
(steady, burst, spike, decay) for each tool.
…s, huaweicloud mirror

- statefulset.yaml: add nodeAffinity and tolerations support (template)
- values.yaml: add nodeAffinity default (empty), switch alpine mirror to huaweicloud
- values-wlcb-001.yaml: new — wlcb-001 cluster values (amd64, node 192.168.1.49, cache toleration)
- values-gy-001.yaml: new — gy-001 cluster values (amd64, node 192.168.1.191, cache toleration)
@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

1 similar comment
@opensourceways-bot

Copy link
Copy Markdown

CLA Signature Pass

ccijunk, thanks for your pull request. All authors of the commits have signed the CLA. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants