主题
Rancher Monitoring 109.0.4+up80.9.1-rancher.18 镜像离线收集推送手册
- 日期:2026-08-01
- Chart:
rancher-monitoring 109.0.4+up80.9.1-rancher.18(appVersion v0.87.1,上游 kube-prometheus-stack) - 目标仓库:Harbor
192.168.122.156:30000,项目rancher(HTTP 明文,已在 docker daemoninsecure-registries中注册) - 镜像源:DaoCloud 镜像站
docker.m.daocloud.io/ 华为云 SWRswr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/(免翻墙拉取 docker.io) - 结果:22 个镜像全部推送成功,主架构(linux/amd64,windows-exporter 为 windows/amd64)可用
1. 背景与目标
内网/离线环境部署 Rancher Monitoring 时,集群无法直接访问 docker.io。需要:
- 从 chart 包中完整提取该版本依赖的全部镜像清单(不能漏掉 init 容器、sidecar 等);
- 通过国内镜像源拉取,推送到内网 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 ~/monitoring-images && cd ~/monitoring-images
helm repo add rancher-charts https://charts.rancher.io
helm repo update
helm pull rancher-charts/rancher-monitoring --version "109.0.4+up80.9.1-rancher.18"
tar xzf rancher-monitoring-109.0.4+up80.9.1-rancher.18.tgz3.2 渲染模板 + 解析 values 双保险
只用 helm template 会漏掉默认未启用组件的镜像(windows-exporter、thanos、image-renderer 等);只 grep values 又处理不了 repository + tag 拼接和子 chart。因此两步结合:
bash
# ① 渲染默认模板,抓字面值 image:
helm template monitoring ./rancher-monitoring --namespace cattle-monitoring-system > rendered.yaml
# ② Python 遍历主 chart 与全部子 chart 的 values.yaml,
# 提取 {registry, repository, tag} 组合与字面值 image,与 ① 合并去重
python3 extract.py | sort -u > images.txt # 脚本见附录 A本版本提取结果共 22 个镜像,全部位于 docker.io/rancher/ 命名空间下(清单见附录 B)。
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
skopeo copy --all --retry-times=3 \
--dest-tls-verify=false \
"docker://${SRC_REGISTRY}/${img}" \
"docker://${DST_REGISTRY}/${img}" \
&& echo "OK $img" || echo "FAIL $img"
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 无法处理。解法:放弃 --all,按架构单独复制:skopeo copy --override-os linux --override-arch amd64 ... |
skopeo 1.4.1 无 --preserve-digests | unknown flag | 该参数为新版 skopeo 才有;--format oci 也不能绕过上述 bug |
| 华为云 SWR 匿名拉取限流 | denied: You may not login yet | SWR 对匿名 token 请求限频,隔几分钟后重试即可;--retry-times 对该错误无效(发生在取 token 阶段) |
| SWR ddn-k8s 镜像为扁平单架构 | 推送后 skopeo inspect --raw 只见一个 manifest | ddn-k8s 同步时只保留了单架构。若需多架构请用 DaoCloud 源 + --all |
| Harbor API 列表"缺仓库"假象 | /projects/rancher/repositories 返回不全 | 接口分页默认每页 100,项目已有 100+ 仓库时须翻页;以 artifact 级查询为准 |
| Windows 镜像复制 | 默认按 host 平台(linux)选 manifest 失败 | 显式指定 --override-os windows --override-arch amd64 |
本次实际操作中,22 个镜像经 DaoCloud 源推送 16 个成功;6 个含 attestation 层的镜像(kuberlr-kubectl、grafana-image-renderer、kube-webhook-certgen、nginx、windows-exporter、pushprox)改用 --override-os/--override-arch 单架构推送成功。本环境集群为 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 / 22查看镜像架构:
bash
skopeo inspect --tls-verify=false \
docker://192.168.122.156:30000/rancher/prom-prometheus:v3.8.1 | python3 -c \
"import json,sys; d=json.load(sys.stdin); print(d['Os'], d['Architecture'])"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 中声明。
附录 A:镜像提取脚本 extract.py
python
#!/usr/bin/env python3
"""提取 rancher-monitoring chart 全部容器镜像(values + 渲染模板)"""
import yaml, glob, re, sys
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)
files = ["rancher-monitoring/values.yaml"] + glob.glob("rancher-monitoring/charts/*/values.yaml")
for f in files:
for d in yaml.safe_load_all(open(f)):
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("/")
if ":" in img.split("/")[-1]:
print(img)附录 B:完整镜像清单(22 个)
rancher/appco-alertmanager:0.30.0-12.16
rancher/appco-grafana:12.3.1-1.12
rancher/appco-k8s-sidecar:2.1.2-1.10
rancher/appco-kube-rbac-proxy:0.20.1-16.14
rancher/appco-kube-rbac-proxy:0.20.1-16.15
rancher/appco-kube-state-metrics:2.17.0-10.14
rancher/appco-node-exporter:1.10.2-14.3
rancher/appco-thanos:0.40.1-8.1
rancher/kuberlr-kubectl:v7.1.1
rancher/mirrored-curlimages-curl:8.20.0
rancher/mirrored-grafana-grafana-image-renderer:v5.10.1-1
rancher/mirrored-jkroepke-kube-webhook-certgen:1.7.4
rancher/mirrored-library-busybox:1.31.1
rancher/mirrored-library-busybox:1.37.0
rancher/mirrored-library-nginx:1.31.3-alpine
rancher/mirrored-prometheus-adapter-prometheus-adapter:v0.12.0
rancher/mirrored-prometheus-operator-admission-webhook:v0.87.1
rancher/mirrored-prometheus-operator-prometheus-config-reloader:v0.87.1
rancher/mirrored-prometheus-operator-prometheus-operator:v0.87.1
rancher/mirrored-prometheus-windows-exporter:0.31.3
rancher/prom-prometheus:v3.8.1
rancher/pushprox:v0.1.11