拓冰建站拓冰建站
首页 / 资讯中心 / 正文

K8S集群监控镜像清单与离线打包:一次备齐所有镜像

简介这份资源面向Kubernetes运维工程师、SRE及云原生监控学习者聚焦集群监控体系的镜像与配置落地解决监控组件离线部署、镜像拉取困难及配置模板缺失等问题。压缩包共124个文件约650.88MB以57个yaml清单、16个gz镜像包、14个txt说明、8个json配置为主另含yml、tmpl模板、log日志、silences静默规则及license、notice等辅助文件覆盖Prometheus、Grafana、Alertmanager、amtool、prometheus-webhook-dingtalk等核心组件的镜像与配套配置。目录中镜像包与清单文件相互对应便于按组件快速定位所需资源适合搭建或迁移K8S监控环境时直接取用。目前已有382人学习下载可作为集群监控部署、告警配置与镜像离线分发的实用参考合集。1. K8S集群监控资源镜像清单从“拉不到镜像”到“一次备齐”做 K8S 集群监控最让人血压升高的瞬间不是 Prometheus 规则写错而是 Pod 卡在ImagePullBackOffkubectl describe pod一看——镜像仓库连不上或者某个 exporter 镜像 tag 根本不存在。尤其是内网环境、离线机房、信创服务器上部署 kube-prometheus-stack 时几十个镜像要一个个docker pull、docker save、docker load漏一个就前功尽弃。这份 K8S 集群监控资源镜像清单及镜像合集解决的就是这件事把一套完整监控栈所需的全部容器镜像提前梳理清楚、批量拉取、统一打包让集群搭建和监控部署不再被镜像问题卡住。适合正在做 k8s 集群搭建、k8s 部署 prometheus、以及需要离线交付的运维和平台工程师。下面从镜像清单怎么定、怎么拉、怎么导、怎么验一步步拆开讲。2. 监控栈镜像清单怎么定先搞清楚要跑哪些组件2.1 一套标准监控栈到底包含哪些镜像很多人以为监控就是 Prometheus 加 Grafana 两个镜像实际上一套能用的 kube-prometheus-stack 至少涉及四类组件指标采集、指标存储与查询、告警、可视化。每一类下面又有若干镜像而且版本之间互相咬合不能随便混搭。以社区最常用的 kube-prometheus-stack 为例核心镜像大致分这么几组组件类别代表镜像作用指标采集prometheus-node-exporter采集节点 CPU/内存/磁盘/网络指标采集kube-state-metrics把 K8S 对象状态转成指标指标采集prometheus-operator管理 Prometheus 实例和配置指标存储prometheus时序数据库与查询引擎告警alertmanager告警分组、去重、路由可视化grafana仪表盘展示附加采集blackbox-exporter黑盒探测 HTTP/TCP/ICMP附加采集pushgateway接收短生命周期任务指标这张表不是让你照抄而是让你意识到镜像清单的粒度要细到每个 Deployment/StatefulSet/DaemonSet 实际引用的 image 字段。少一个 node-exporter节点指标就是空的少一个 kube-state-metricsPod 重启次数、Deployment 副本数这些关键指标全都没有。我一般会先把 Helm chart 的 values 拉下来用helm template渲染成纯 YAML再从里面把所有image:字段抽出来。这样得到的清单才是真正会被 K8S 调度的镜像而不是凭记忆列出来的。2.2 用 helm template 抽取真实镜像清单直接helm install再去看 Pod 用了什么镜像属于事后补救。更稳的做法是渲染阶段就把镜像清单拿到手。下面这段命令把 chart 渲染成 YAML再用 grep 和 sort 去重得到一份干净的镜像列表。# 添加 prometheus-community 仓库 helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update # 渲染 kube-prometheus-stack 模板到本地文件 helm template monitoring prometheus-community/kube-prometheus-stack \ --namespace monitoring \ --set grafana.enabledtrue \ --set prometheus.prometheusSpec.replicas1 \ monitoring-rendered.yaml # 抽取所有 image 字段并去重排序 grep -E ^\simage: monitoring-rendered.yaml \ | sed s/.*image:\s*// \ | tr -d \ | sort -u \ image-list.txt # 查看结果 cat image-list.txt这段逻辑的关键点helm template不会真正连集群只做本地渲染所以可以在任何有 helm 的机器上跑。grep -E ^\simage:匹配的是 YAML 里缩进后的 image 字段sed去掉前缀tr -d 去掉可能存在的引号最后sort -u去重。得到的image-list.txt就是这份 chart 在当前 values 下真正需要的全部镜像。参数说明--namespace monitoring只影响渲染出的 namespace 字段不影响镜像地址--set后面的开关按你实际要启用的组件来比如不需要 grafana 就设grafana.enabledfalse清单里自然少一个镜像。注意有些 chart 的镜像地址带{{ }}模板变量渲染后会被替换成实际值所以一定要用渲染后的结果不要直接看 values.yaml。2.3 镜像 tag 与 digest为什么不能只记 tag镜像清单里最容易翻车的地方是 tag。prometheus:v2.45.0这种 tag 看起来明确但它是可变的——同一个 tag 可以被重新推送内容就变了。生产环境更稳的做法是记录 digest形如prometheussha256:abc123...。不过 digest 可读性差人工核对困难。我的习惯是清单里同时保留 tag 和 digest 两列tag 用于人看和拉取digest 用于校验。拉取时用 tag打包前用docker inspect或skopeo inspect把 digest 记下来导入后比对 digest 是否一致。# 用 skopeo 查看镜像 digest不需要本地 docker daemon skopeo inspect docker://prometheus/prometheus:v2.45.0 \ | grep -E Digest|RepoTagsskopeo inspect的好处是不用先把镜像拉到本地直接查远程仓库元数据适合在清单整理阶段快速核对。如果返回的 Digest 和你记录的一致说明镜像没被重新推送过。这一步在离线交付前做一遍能避免“明明拉的是同一个 tag行为却不一样”的玄学问题。3. 批量拉取与离线打包把镜像合集做成一个 tar3.1 批量拉取脚本与并发控制清单有了接下来是拉取。一个个docker pull太慢写个循环是最基本的。但循环里要注意两点一是失败要记录不能拉一半断了不知道缺哪个二是并发别开太大否则把本地磁盘 IO 和网络打满反而更慢。#!/bin/bash # pull-images.sh - 按清单批量拉取镜像 IMAGE_LISTimage-list.txt FAILED_LOGpull-failed.log MAX_PARALLEL4 $FAILED_LOG pull_one() { local img$1 if docker pull $img /dev/null 21; then echo [OK] $img else echo [FAIL] $img echo $img $FAILED_LOG fi } export -f pull_one export FAILED_LOG # 用 xargs 控制并发数 cat $IMAGE_LIST | xargs -P $MAX_PARALLEL -I {} bash -c pull_one $ _ {} echo 拉取完成失败列表见 $FAILED_LOG逻辑说明xargs -P 4表示最多 4 个并发进程-I {}把每一行作为参数传给后面的 bash。pull_one函数里把成功和失败分开输出失败的同时追加到pull-failed.log。这样即使中途有镜像拉不到也不会中断整体流程最后看日志补拉即可。参数说明MAX_PARALLEL根据你的网络带宽和磁盘调整内网 registry 可以开到 8公网拉取建议 4 以内。docker pull的输出被重定向到/dev/null避免并发时日志交错看不清需要详细输出可以去掉重定向。3.2 docker save 打包与分层压缩镜像全部拉到本地后用docker save打包成一个 tar。这里有个坑如果直接docker save img1 img2 ... all.tar镜像多了之后 tar 会非常大而且没有压缩。更好的做法是先 save 再 gzip或者用docker save输出到管道直接压缩。# 把清单里所有镜像打包并压缩 docker save $(cat image-list.txt | tr \n ) \ | gzip -1 monitoring-images.tar.gz # 查看包大小 ls -lh monitoring-images.tar.gzgzip -1表示最低压缩级别速度最快压缩率也够用。镜像层本身很多已经是压缩过的再用高压缩级别收益不大反而耗时。如果镜像特别多可以分批 save比如每 10 个一个包避免单个 tar 过大导致传输中断后要重来。注意docker save后面跟的是镜像名列表如果清单里有重复或空行先清理一下。另外docker save保留的是镜像的 tag 和层数据导入后 tag 不变但 digest 可能因为重新打包而变化所以校验要以导入后的实际 digest 为准。3.3 导入端 docker load 与 containerd 的差异离线包拿到目标机器后导入方式取决于容器运行时。用 Docker 的集群直接docker load用 containerd 的集群现在大多数 K8S 发行版默认 containerd就不能用 docker load 了得用ctr或nerdctl。# Docker 运行时 docker load monitoring-images.tar.gz # containerd 运行时用 ctr 导入到 k8s.io 命名空间 ctr -n k8s.io images import monitoring-images.tar.gz # 如果装了 nerdctl更接近 docker 体验 nerdctl -n k8s.io load monitoring-images.tar.gz关键差异containerd 有命名空间概念K8S 用的是k8s.io这个 namespace导入时必须加-n k8s.io否则ctr images ls看不到K8S 也拉不到。这是离线部署里最常见的翻车点之一——镜像明明导入了Pod 还是 ImagePullBackOff就是因为导错了 namespace。导入后验证# Docker docker images | grep -E prometheus|grafana|alertmanager # containerd ctr -n k8s.io images ls | grep -E prometheus|grafana|alertmanager如果清单里的镜像地址带私有 registry 前缀比如registry.internal:5000/prometheus/prometheus导入后 tag 会保留这个前缀K8S 的 image 字段也要对应改否则还是会去公网拉。4. 镜像清单落地时的避坑与排查4.1 现象Pod 一直 ImagePullBackOff但镜像明明导入了原因containerd 命名空间不对或者镜像 tag 与 YAML 里写的不完全一致。K8S 默认从k8s.io命名空间找镜像如果导入时没加-n k8s.io镜像在 default 命名空间K8S 看不到。解决用ctr -n k8s.io images ls确认镜像在正确命名空间再核对 YAML 里的 image 字段是否和导入的 tag 完全一致包括 registry 前缀和 tag 后缀。差一个字符都会导致重新去远程拉。4.2 现象helm template 渲染出的镜像清单比实际运行的少原因有些镜像是在 chart 的 hook 或子 chart 里定义的helm template默认不渲染 hook或者子 chart 的 values 被覆盖后镜像变了。解决加--no-hooks的反面是默认不渲染 hook需要显式加--include-crds和检查子 chart。更稳的做法是部署到测试集群后用kubectl get pods -n monitoring -o jsonpath把所有实际镜像再抽一遍和渲染清单做差集。kubectl get pods -n monitoring -o jsonpath{range .items[*]}{.spec.containers[*].image}{\n}{end} | sort -u4.3 现象docker save 打包后文件巨大传输经常断原因一次性 save 所有镜像单个 tar 几十 GB网络传输不稳定时容易断断了又要从头来。解决分批打包每批 5 到 10 个镜像或者用skopeo copy直接同步到目标 registry避免落地 tar 文件。如果必须用 tar配合split分卷传输后cat合并。4.4 现象导入后镜像 digest 和清单记录不一致原因docker save再docker load的过程中镜像配置可能被重新计算digest 变化。或者中间经过了私有 registry 的重新打包。解决如果对 digest 有严格要求用skopeo copy保持 digest 不变或者直接在目标环境从同一个 registry 拉取不走 save/load。校验时以导入后docker inspect --format{{.Id}}或ctr images ls的 digest 为准和源端比对。4.5 现象私有 registry 前缀导致 K8S 拉取失败原因清单里的镜像地址是prometheus/prometheus但集群配置了私有 registry mirror实际拉取时被重写成registry.internal/prometheus/prometheus而私有 registry 里没有这个镜像。解决统一镜像地址。要么在清单阶段就把所有镜像 retag 成私有 registry 前缀要么在 K8S 的 image 字段里写全地址。用docker tag或skopeo copy批量加前缀再重新打包。5. 用 skopeo 做镜像合集的增量同步与校验最后一章讲一个我实际交付时最常用的技巧用skopeo替代docker pull/save/load三件套直接做 registry 到 registry 的同步同时生成可校验的清单。这样既省掉本地磁盘中转又能保留 digest特别适合多集群批量交付。skopeo copy的基本用法是从一个 registry 复制到另一个或者从 registry 复制到本地目录dir 格式再打包。下面这个脚本把清单里的镜像同步到本地 dir并生成一个带 digest 的清单文件。#!/bin/bash # sync-with-skopeo.sh - 用 skopeo 同步镜像并记录 digest IMAGE_LISTimage-list.txt DEST_DIR./images-dir MANIFESTimage-manifest.csv mkdir -p $DEST_DIR echo image,digest $MANIFEST while read -r img; do [ -z $img ] continue # 把镜像名里的 / 和 : 替换成 _ 作为目录名 safe_name$(echo $img | tr /: __) dest$DEST_DIR/$safe_name if skopeo copy --all docker://$img dir:$dest /dev/null 21; then digest$(skopeo inspect dir:$dest | grep -oP Digest:\s*\K[^]) echo $img,$digest $MANIFEST echo [OK] $img - $digest else echo [FAIL] $img fi done $IMAGE_LIST逻辑说明skopeo copy --all会复制镜像的所有架构和 tag 信息到本地 dir 格式。skopeo inspect从本地 dir 读取 digest写入 CSV。这样得到的image-manifest.csv就是一份可追溯的镜像合集清单交付时连同images-dir一起打包目标端用skopeo copy dir:... docker://...推送到私有 registrydigest 保持不变。参数说明--all表示复制所有架构如果只需要 amd64 可以去掉减小体积。dir:格式是 skopeo 的本地目录格式不是 tar但可以直接用tar czf打包整个目录。目标端推送时用skopeo copy --all dir:./images-dir/xxx docker://registry.internal/xxx注意目标 registry 要允许推送。校验环节我习惯在目标端推送完成后用skopeo inspect docker://registry.internal/xxx再取一次 digest和 CSV 里的比对。全部一致才算交付完成。这个习惯帮我挡过好几次“镜像推上去了但层不完整”的问题——skopeo 的 digest 校验比docker pull成功更可靠因为它校验的是 manifest 和层的完整性。说个我自己的教训早期做离线交付图省事只用docker save打包结果有一次目标机器磁盘空间不够docker load到一半失败镜像处于半导入状态docker images能看到但跑起来就报层缺失。后来改成 skopeo 的 dir 格式加 digest 校验每个镜像独立目录坏一个不影响其他重传也只需要传单个目录。这个习惯一直保留到现在虽然多花几分钟做校验但省掉了现场排查的几小时。希望帮到你。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门