Harbor 内网镜像仓库 — 专项交接(需求规格书)¶
用途:把「内网镜像仓库」这件事整体移交到专门的 Harbor 对话执行;本文档是需求规格与 验收标准,不是操作步骤。执行方按此落地,结果回填到第 8 节约定路径。 生成时间:2026-10-01 | 主题目录:
ghcr-slow-20261001/关联文档:PROXY-CHECK-AND-HARBOR.md(代理速率排查,另一条线,互不阻塞) 前提更新(2026-10-01):代理专项已复测并回填PROXY-FINDINGS.md—— 4 台节点拉取 1.2–1.8 MiB/s(9 MiB 镜像 5–8 s),未复现历史卡住;本文档中「首次入库慢」的 相关表述以该文件为准。
1. 目标¶
一次彻底解决:让 k8s 集群拉取镜像不再依赖海外链路。 落地后应满足:新增镜像、节点重建、Pod 重调度都从内网 Harbor 取像,海外源只承担「首次入库」。
衡量成功的两条:① 镜像引用名零改动;② 节点重建不再受慢链路与 ghcr.io 超时影响。
2. 已确认的环境事实(2026-10-01 实测,请勿重复取证)¶
2.1 接入点已预留(这是改动量小的根本原因)¶
| 项 | 现状 |
|---|---|
| containerd | v2.3.5,4 台节点均 active |
| registry 配置 | config_path = "/etc/containerd/certs.d"([config.toml 第 30-31 行]) |
/etc/containerd/certs.d/ |
目录不存在 → 只需新建,不必改 config.toml、不必重启 containerd |
| sandbox 镜像 | pinned_images.sandbox = registry.k8s.io/pause:3.10.2(同样走该 registry 配置) |
| 节点 | 4 台:k8s-master-01(.10) + k8s-node-01~03(.13/.14/.15) |
| StorageClass | nfs-csi(默认) / nfs-csi-hdd / local-ssd |
| 现有 Harbor | 无 |
2.2 镜像源分布(集群在跑容器的实际来源)¶
| registry | 容器数 | 性质 | 是否需纳管 |
|---|---|---|---|
registry.k8s.io |
15 | 海外 | 是 |
quay.io |
15 | 海外 | 是 |
registry.gitlab.com |
11 | 海外(gitlab-org/build/cng/* 官方镜像) |
是 |
docker.io |
6 + 3 隐式 | 海外 | 是 |
ghcr.io |
4 | 海外 | 是 |
合计约 49 个去重镜像条目;单节点 containerd 存储占用实测 15 GB(.13)。
2.3 宿主资源(R620,192.168.31.249)¶
| 项 | 现状 | 含义 |
|---|---|---|
| CPU / 内存 | 32 核 / 117 GB(可用 68 GB) | 资源充足 |
| 系统盘 | /dev/sda3 220 G → /,余 53 GB |
只放系统,不放 Harbor 数据 |
| 数据盘 | /dev/sdb 1.8 T → /data,余 1.2 T |
Harbor 数据落这里(另有 /srv/nfs/k8s-hdd 余 482 G 可用作 NFS 后端) |
| 磁盘类型 | 全机机械盘(HDD) | 顺序读写百 MB/s 量级,对镜像缓存足够(远高于外网 1.8 MiB/s) |
| Docker | 29.1.3,active | 可承载 Harbor 的 compose 部署 |
| KVM | 13 台虚机在跑 | 宿主机负载可观 |
3. 需求规格(逐条可验收)¶
| # | 要求 | 说明 |
|---|---|---|
| R1 | 镜像引用名零改动 | 各工程的 values / deploy.yaml / manifests 中的 ghcr.io/... 等一律不动,改由节点侧 mirror 完成 |
| R2 | 覆盖 5 个上游源 | ghcr.io、registry.k8s.io、quay.io、registry.gitlab.com、docker.io |
| R3 | 每个源一个代理缓存 project,project 名与 registry 域名完全一致 | 如 project 名 ghcr.io,使 containerd 请求路径 /v2/ghcr.io/<repo>/... 天然对齐,这是 R1 成立的前提 |
| R4 | 节点接入不改 config.toml、不重启 containerd,不影响运行中 Pod |
只新增 /etc/containerd/certs.d/<registry>/hosts.toml |
| R5 | 证书可用即可,且方案明确 | 内网自签 CA(需分发到 4 台节点)或复用现有域名体系;必须写明轮换方式 |
| R6 | 幂等 | 重复执行零变更、零报错、全跳过 |
| R7 | 可回滚 | 删除 hosts.toml 即回到直连;回滚步骤需实测过并写入 SOP |
| R8 | Harbor 可观测 | 至少覆盖存活与缓存命中;可按现有 textfile → node_exporter:9100 路线接入(该路线不新增端口) |
| R9 | 交付 SOP.md + RUNBOOK.md |
按工程规范八章结构;含备份台账(backup/README.md) |
| R10 | 存量镜像一次性入库 | 按第 2.2 节的 49 条清单预热;必须包含 helm hook 类镜像(如 ghcr.io/jkroepke/kube-webhook-certgen)—— 「按需代拉」不覆盖这个场景,不预热则 hook 首次仍会撞 --timeout |
| R11 | 凭据管理 | Harbor admin 口令入 ~/.secrets/(600),不入交付物、不入文档、不打终端 |
4. 已知坑(务必先读,多数会直接影响成败)¶
| # | 坑 | 应对 |
|---|---|---|
| K1 | fake-ip 劫持内网域名:4 台节点 DNS 均为 192.168.31.2(OpenWrt/Clash),Harbor 若用域名访问,域名会被解析成 198.18.x.x fake-ip 而被代理劫持 → 内网不通 |
直接用 IP 访问最稳;若必须用域名,需在 Clash 的 fake-ip-filter 中排除该域名,并在节点 /etc/hosts 兜底 |
| K2 | ~~磁盘不足~~ 已澄清,不构成阻碍:系统盘虽仅余 53 GB,但数据盘 /dev/sdb(1.8 T)挂在 /data,余 1.2 T;/srv/nfs/k8s-hdd 另余 482 G |
Harbor 数据落 /data(VM 的 qcow2 放这里)。注意区分系统盘与数据盘,不要只看 / |
| K3 | docker.io 路径不一致:镜像写作 redis:7.4-alpine(隐式 docker.io/library/),但实际 endpoint 是 registry-1.docker.io |
hosts.toml 建在 docker.io,Harbor project 名用 docker.io;另需处理 library/ 前缀差异 |
| K4 | registry.gitlab.com 是公网源(非集群内自建 GitLab),已确认镜像形如 gitlab-org/build/cng/* |
纳入代理缓存,不要误判为内部源而排除 |
| K5 | 首次入库需经海外链路,速率取决于代理链路质量(2026-10-01 复测正常:1.2–1.8 MiB/s;但曾观测到一次卡住,根因未证实) | 仍建议一次做完(R10);若入库期间再次卡住,按 PROXY-FINDINGS.md 建议②冻结出口节点做单变量对比,不要凭单次样本下结论 |
| K6 | helm release 的 values 基线红线 | 若验证过程需要 helm upgrade,必须 -f <现场> -f <overlay>,只传 overlay 会触发全栈重建(已出过事故) |
| K7 | 集群内 GitLab Container Registry 是自建服务 | 不要把「拉 GitLab registry」绕进 Harbor 形成环;本次不涉及自建 registry 的改造 |
5. 部署形态(二选一,推荐 A)¶
| 方案 A:独立 VM(推荐) | 方案 B:k8s 内 Helm 部署 | |
|---|---|---|
| 与集群 | 解耦,Harbor 存活不依赖 k8s | 耦合 |
| 存储/入口/证书 | 需自备(可挂 NFS) | 复用 nfs-csi-hdd + Traefik + 现有证书体系 |
| 鸡生蛋风险 | 无 | 有(Harbor 镜像需先有;可用节点本地镜像导入) |
| 建议 | 新建 KVM 虚机(如 4 vCPU / 8 GB / ≥150 GB 盘) | 仅在磁盘确实解决不了时选 |
磁盘已不构成阻碍(见 K2):Harbor 数据落 /data(余 1.2 T)即可开工。
6. 实施要求(工程纪律)¶
- 幂等 + 备份 + 回滚:按全局变更规范,改动前备份登记
backup/README.md; - 三态判定:节点探测区分 done / pending / unknown,unknown 一律中止(「查不到」≠「没有」);
- 高危标记:修改 containerd 配置目录、重启服务、删除镜像均属高危,须醒目记录;
- 失败阈值:同一逻辑连续失败 2 次即停,不得换参数重试绕过;
- 分批:4 台节点分批推进,达阈值即停并回滚本批;
- 验证走 stdin 不落盘:分发脚本优先
ssh <host> 'python3 -' < script.py。
7. 验收标准(必须逐条实测并记录证据)¶
| # | 验收项 | 判据 |
|---|---|---|
| A1 | 缓存命中后的拉取速度 | 任一节点 ctr -n k8s.io images pull <某 ghcr 镜像>:≥ 1 MiB/s、耗时 ≤ 60 s |
| A2 | 确实走 Harbor(而非直连) | Harbor 访问日志/缓存命中计数增长,或临时阻断出网后仍能拉 |
| A3 | 现有负载无扰动 | 全部 Pod 无重建、无 ImagePullBackOff;kubectl get pods -A 前后一致 |
| A4 | hook 镜像可从 Harbor 快速取用 | 对 hook 镜像验证:Harbor 命中后拉取 ≤ 5 s。注意:--no-hooks 是否去掉是独立决策,当前决定保留(见 BASELINE:代理按延迟选路,首次/新版本拉取仍可能遇低带宽节点)。不要因本项而擅自修改部署工程的 helm 调用 |
| A5 | 幂等 | 二次执行:零变更、全跳过 |
| A6 | 回滚可用 | 删除 hosts.toml 后确认回到直连(curl 验证),再恢复 |
| A7 | 5 个源全覆盖 | 每个 registry 各拉 1 个镜像验证命中 |
8. 结果回填契约¶
结果写入路径:
/home/rain/Documents/k8s_ins/ghcr-slow-20261001/HARBOR-RESULT.md
必备小节(顺序固定):
## 1. 部署形态与主机(含 IP、资源、存储方案)## 2. 实际改动清单(逐文件、逐节点,含含 K1/K3 的处理方式)## 3. 证书方案与轮换方式## 4. registry → Harbor project 映射表(5 个源)## 5. 存量镜像入库清单与容量占用(实际 GB)## 6. 验收结果(逐条对 A1~A7,附证据)## 7. 遇到的问题与绕过方式## 8. 回滚方式(已实测)## 9. 遗留项与后续建议
约定:只写结论与关键证据;Harbor 口令、CA 私钥等凭据一律脱敏,只写存放路径;
写完后把路径告知,本对话据此更新 HANDOFF.md / BASELINE.md。
9. 边界(本次不做)¶
- ❌ 不改任何业务工程的镜像引用与 helm values(R1 的意义就在于此)
- ❌ 不动现有 helm release(除非 A4 验证,且必须带现场 values 基线)
- ❌ 不删除节点上现有镜像(保留作回滚与降级)
- ❌ 不改造集群内自建的 GitLab Container Registry
- ❌ 不把凭据写入交付物目录
- ⏸ 代理速率排查是另一条线(见
PROXY-CHECK-AND-HARBOR.md),本次不阻塞、不代办
10. 与另一条线的关系¶
| 代理速率排查 | Harbor 专项 | |
|---|---|---|
| 解决什么 | 首次入库慢(以及所有海外依赖的通用问题) | 重复拉取与外部依赖的运行时风险 |
| 谁做 | 专门的代理对话 | 专门的 Harbor 对话 |
| 关系 | 互不阻塞;Harbor 在代理未修好时也能落地(只是首次慢一次) | — |
来源:
/home/rain/Documents/k8s_ins/ghcr-slow-20261001/HARBOR-HANDOFF.md| 最后更新:2026-10-01 02:32(由build/sync.py同步,请勿在站点侧修改)