主题
Longhorn 109.3.2+up1.11.3 镜像离线收集推送手册
- 日期:2026-08-01
- Chart:
longhorn 109.3.2+up1.11.3(appVersion v1.11.3,上游 longhorn/longhorn) - 目标仓库:Harbor
192.168.122.156:30000,项目rancher(HTTP 明文,已在 docker daemoninsecure-registries中注册) - 镜像源:DaoCloud 镜像站
docker.m.daocloud.io(免翻墙拉取 docker.io) - 结果:13 个镜像全部推送成功,其中 7 个多架构(
--all)、6 个因 attestation 层回退为 linux/amd64 单架构,主架构可用
1. 背景与目标
内网/离线环境部署 Longhorn(Rancher 集成分布式块存储)时,集群无法直接访问 docker.io。需要:
- 从 chart 包中完整提取该版本依赖的全部镜像清单(含 CSI 组件、support-bundle-kit 等默认模板未渲染出的镜像);
- 通过国内镜像源拉取,推送到内网 Harbor;
- 保持
rancher/xxx:tag原始路径不变,部署时只需设置全局systemDefaultRegistry,无需逐条改 values。
2. 工具准备
| 工具 | 版本 | 用途 |
|---|---|---|
| helm | v3.19.4 | 下载 chart、渲染模板 |
| skopeo | 1.4.1 | 跨仓库复制镜像(无需 docker pull,省本地磁盘) |
| python3 + pyyaml | 3.x / 6.0.2 | 解析 values.yaml 提取镜像 |
| curl | - | Harbor API 验证 |
bash
# 登录目标仓库(skopeo 凭据与 docker 独立存储)
skopeo login --tls-verify=false -u <用户名> -p '<密码>' 192.168.122.156:30000
# 确认 Harbor 项目存在(push 前项目必须先创建,Harbor 不会自动建项目)
curl -s -u '<用户名>:<密码>' \
"http://192.168.122.156:30000/api/v2.0/projects?name=rancher"3. 提取镜像清单
3.1 下载 chart
bash
mkdir -p ~/longhorn-images && cd ~/longhorn-images
helm repo add rancher-charts https://charts.rancher.io
helm repo update
helm pull rancher-charts/longhorn --version "109.3.2+up1.11.3"
tar xzf longhorn-109.3.2+up1.11.3.tgz3.2 渲染模板 + 解析 values 双保险
默认 helm template 只渲染出 3 个镜像(manager / share-manager / ui),CSI 六组件、engine、instance-manager、backing-image-manager、support-bundle-kit 均由 Longhorn Manager 在运行时按 Setting 拉起,模板中不出现,必须解析 values.yaml 补全:
bash
# ① 渲染默认模板,抓字面值 image:
helm template longhorn ./longhorn --namespace longhorn-system > rendered.yaml
# ② Python 遍历 values.yaml,提取 {registry, repository, tag} 组合与字面值 image,与 ① 合并去重
python3 extract.py | sort -u > images.txt # 脚本见附录 A本版本提取结果共 13 个镜像,全部位于 docker.io/rancher/ 命名空间下(清单见附录 B)。
openshift.oauthProxy的 repository/tag 默认为空(非 OpenShift 环境不需要),不计入清单。
4. 推送镜像到私有仓库
4.1 推送脚本(skopeo 免本地存储,自动回退单架构)
bash
#!/bin/bash
SRC_REGISTRY="docker.m.daocloud.io" # DaoCloud 国内源
# SRC_REGISTRY="swr.cn-north-4.myhuaweicloud.com" # 或华为云 SWR(源地址需拼 ddn-k8s/docker.io/ 前缀)
DST_REGISTRY="192.168.122.156:30000"
LIST="./images.txt"
while IFS= read -r img; do
[ -z "$img" ] && continue
if skopeo copy --all --retry-times=3 \
--dest-tls-verify=false \
"docker://${SRC_REGISTRY}/${img}" \
"docker://${DST_REGISTRY}/${img}" >/dev/null 2>push.err; then
echo "OK(all) $img"
elif skopeo copy --override-os linux --override-arch amd64 --retry-times=3 \
--dest-tls-verify=false \
"docker://${SRC_REGISTRY}/${img}" \
"docker://${DST_REGISTRY}/${img}" >/dev/null 2>push.err; then
echo "OK(amd64) $img" # attestation 层导致 --all 失败时回退单架构
else
echo "FAIL $img"; sed 's/^/ /' push.err | tail -5
fi
done < "$LIST"使用 SWR 源时源地址为:
docker://swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/rancher/xxx:tag
4.2 踩坑记录
| 问题 | 现象 | 原因与解法 |
|---|---|---|
| skopeo 1.4.1 复制含证明层镜像失败 | unsupported MIME type for compression: application/vnd.in-toto+json | buildkit 构建的镜像带 in-toto attestation 层,--all 重建 manifest 列表时老版本 skopeo 无法处理。解法:回退 --override-os linux --override-arch amd64 单架构复制 |
| 华为云 SWR 匿名拉取限流 | denied: You may not login yet | SWR 对匿名 token 请求限频,隔几分钟后重试即可;--retry-times 对该错误无效(发生在取 token 阶段) |
| Harbor API 列表"缺仓库"假象 | /projects/rancher/repositories 返回不全 | 接口分页默认每页 100,项目已有 100+ 仓库时须翻页;以 artifact 级查询为准 |
本次实际操作中,13 个镜像经 DaoCloud 源全部推送成功:7 个(csi-attacher、csi-node-driver-registrar、csi-provisioner、csi-resizer、csi-snapshotter、livenessprobe、support-bundle-kit)以 --all 多架构推送;6 个(backing-image-manager、longhorn-engine、longhorn-instance-manager、longhorn-manager、longhorn-share-manager、longhorn-ui)因 attestation 层回退为 linux/amd64 单架构。本环境集群为 amd64,单架构满足需求。
5. 验证
以 artifact 级查询为准(不受分页影响):
bash
miss=0
while IFS= read -r img; do
[ -z "$img" ] && continue
repo_name="${img#rancher/}"; repo_name="${repo_name%:*}"; tag="${img##*:}"
code=$(curl -s -o /dev/null -w "%{http_code}" -u '<用户名>:<密码>' \
"http://192.168.122.156:30000/api/v2.0/projects/rancher/repositories/${repo_name}/artifacts/${tag}")
[ "$code" != "200" ] && { echo "MISSING: $img"; miss=$((miss+1)); }
done < images.txt
echo "缺失: $miss / $(grep -c . images.txt)" # 期望输出: 缺失: 0 / 13查看镜像架构:
bash
skopeo inspect --tls-verify=false \
docker://192.168.122.156:30000/rancher/mirrored-longhornio-longhorn-manager:v1.11.3 | python3 -c \
"import json,sys; d=json.load(sys.stdin); print(d['Os'], d['Architecture'])"
# 输出: linux amd646. 集群侧使用
镜像路径与 docker.io 原始路径完全一致,部署时只需指向私有仓库:
- Rancher UI:全局设置 → System Default Registry 设为
192.168.122.156:30000; - 或 Helm values:
yaml
global:
cattle:
systemDefaultRegistry: 192.168.122.156:30000节点 containerd 需将 192.168.122.156:30000 配置为 HTTP 仓库(insecure),或在 registries.yaml 中声明。
注意:Longhorn Manager 启动后会把 engine / instance-manager 等镜像地址写入 Longhorn Setting,由 Manager 自行拉起对应 DaemonSet。只要
systemDefaultRegistry生效使 manager 镜像拉取成功,且其余镜像保持 chart 默认的rancher/xxx相对路径,即可全部从私有仓库拉取。
附录 A:镜像提取脚本 extract.py
python
#!/usr/bin/env python3
"""提取 longhorn chart 全部容器镜像(values + 渲染模板)"""
import yaml, re
images = set()
def walk(node):
if isinstance(node, dict):
if isinstance(node.get("repository"), str):
repo = node["repository"]
tag = node.get("tag")
registry = node.get("registry")
if tag not in (None, ""):
full = f"{repo}:{tag}"
if isinstance(registry, str) and registry:
full = f"{registry}/{full}"
images.add(full)
if isinstance(node.get("image"), str) and ":" in node["image"] and " " not in node["image"]:
images.add(node["image"])
for v in node.values():
walk(v)
elif isinstance(node, list):
for v in node:
walk(v)
for d in yaml.safe_load_all(open("longhorn/values.yaml")):
if d:
walk(d)
for m in re.finditer(r'image:\s*"?([^\s"]+)"?', open("rendered.yaml").read()):
if "{{" not in m.group(1):
images.add(m.group(1))
for img in sorted(images):
img = img.lstrip("/")
img = img.removeprefix("docker.io/")
if ":" in img.split("/")[-1]:
print(img)附录 B:完整镜像清单(13 个)
rancher/mirrored-longhornio-backing-image-manager:v1.11.3
rancher/mirrored-longhornio-csi-attacher:v4.12.0
rancher/mirrored-longhornio-csi-node-driver-registrar:v2.17.0
rancher/mirrored-longhornio-csi-provisioner:v6.3.0
rancher/mirrored-longhornio-csi-resizer:v2.2.0
rancher/mirrored-longhornio-csi-snapshotter:v8.6.0
rancher/mirrored-longhornio-livenessprobe:v2.19.0
rancher/mirrored-longhornio-longhorn-engine:v1.11.3
rancher/mirrored-longhornio-longhorn-instance-manager:v1.11.3
rancher/mirrored-longhornio-longhorn-manager:v1.11.3
rancher/mirrored-longhornio-longhorn-share-manager:v1.11.3
rancher/mirrored-longhornio-longhorn-ui:v1.11.3
rancher/mirrored-longhornio-support-bundle-kit:v0.0.88