Skip to content

Longhorn 109.3.2+up1.11.3 镜像离线收集推送手册

  • 日期:2026-08-01
  • Chartlonghorn 109.3.2+up1.11.3(appVersion v1.11.3,上游 longhorn/longhorn)
  • 目标仓库:Harbor 192.168.122.156:30000,项目 rancher(HTTP 明文,已在 docker daemon insecure-registries 中注册)
  • 镜像源:DaoCloud 镜像站 docker.m.daocloud.io(免翻墙拉取 docker.io)
  • 结果:13 个镜像全部推送成功,其中 7 个多架构(--all)、6 个因 attestation 层回退为 linux/amd64 单架构,主架构可用

1. 背景与目标

内网/离线环境部署 Longhorn(Rancher 集成分布式块存储)时,集群无法直接访问 docker.io。需要:

  1. 从 chart 包中完整提取该版本依赖的全部镜像清单(含 CSI 组件、support-bundle-kit 等默认模板未渲染出的镜像);
  2. 通过国内镜像源拉取,推送到内网 Harbor;
  3. 保持 rancher/xxx:tag 原始路径不变,部署时只需设置全局 systemDefaultRegistry,无需逐条改 values。

2. 工具准备

工具版本用途
helmv3.19.4下载 chart、渲染模板
skopeo1.4.1跨仓库复制镜像(无需 docker pull,省本地磁盘)
python3 + pyyaml3.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.tgz

3.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+jsonbuildkit 构建的镜像带 in-toto attestation 层,--all 重建 manifest 列表时老版本 skopeo 无法处理。解法:回退 --override-os linux --override-arch amd64 单架构复制
华为云 SWR 匿名拉取限流denied: You may not login yetSWR 对匿名 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 amd64

6. 集群侧使用

镜像路径与 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