遇到镜像版本不匹配问题时,可以使用该脚本

cat > /root/tag-manifest-images.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

MANIFEST_DIR=/etc/kubernetes/manifests
if [ ! -d "$MANIFEST_DIR" ]; then
  echo "目录 $MANIFEST_DIR 不存在!请确认 kubeadm 已初始化并生成 manifests。"
  exit 1
fi

# 收集 manifest 中的 image 列表
images_needed=$(grep -RhoP 'image:\s*\K.+' $MANIFEST_DIR | sed 's/"//g' | sed "s/'//g" | tr -d ' ' | sort -u)

if [ -z "$images_needed" ]; then
  echo "没有在 $MANIFEST_DIR 找到 image 条目。"
  exit 0
fi

echo "需要的镜像(来自 manifests):"
echo "$images_needed"
echo

# 列出本地镜像,格式 repo:tag
mapfile -t local_images < <(docker images --format '{{.Repository}}:{{.Tag}}' | sort -u)

# helper: 从 repo:tag 中取得 basename(最后一段,含tag)
basename_of() {
  local repotag="$1"
  # 取 repo 的最后一段加上 tag,示例: registry.cn/.../pause:3.9 -> pause:3.9
  local repo=${repotag%%:*}
  local tag=${repotag#*:}
  local base=$(echo "$repo" | awk -F/ '{print $NF}')
  echo "${base}:${tag}"
}

echo "开始逐个处理所需镜像..."
missing=""
for img in $images_needed; do
  echo "处理 -> $img"
  # 如果已经本地存在精确名字,跳过
  if docker image inspect "$img" >/dev/null 2>&1; then
    echo "  已存在:$img (本地存在精确镜像)"
    continue
  fi

  # 获取需要的镜像的 basename(例如 pause:3.6 -> pause:3.6; 或 kube-apiserver:v1.28.2 -> kube-apiserver:v1.28.2)
  need_base=$(echo "$img" | awk -F/ '{print $NF}')
  need_name=$(echo "$need_base")  # e.g. pause:3.6

  # 在本地镜像中寻找最后 path 段匹配的镜像(忽略 registry 前缀)
  found=""
  for li in "${local_images[@]}"; do
    local_base=$(basename_of "$li")
    # 比较 base 名称(不比较 tag 精确),如果 repository 最后一段名相同就认作匹配
    repo_name=$(echo "$li" | awk -F/ '{print $NF}' | cut -d: -f1)
    need_repo_name=$(echo "$need_name" | cut -d: -f1)
    if [ "$repo_name" = "$need_repo_name" ]; then
      found="$li"
      break
    fi
  done

  if [ -n "$found" ]; then
    echo "  找到本地镜像: $found -> 将被 tag 为 $img"
    docker tag "$found" "$img" && echo "  已 tag: $found -> $img"
  else
    echo "  未找到可替代的本地镜像 (需要手动拉取或导入): $img"
    missing="${missing}\n${img}"
  fi
done

if [ -n "$missing" ]; then
  echo
  echo "下面是未能自动解决的镜像(请手动拉取或从可翻墙主机导出再加载):"
  echo -e "$missing"
  echo
  echo "示例手动拉取(如果可以访问国内镜像仓库,请替换为对应的国内镜像):"
  echo "  docker pull <镜像名>"
  echo "或者在另一台能翻墙机器上:"
  echo "  docker pull <镜像名>"
  echo "  docker save -o /tmp/img.tar <镜像名>"
  echo "  scp /tmp/img.tar your-server:/tmp/"
  echo "  docker load -i /tmp/img.tar"
fi

echo
echo "完成。现在重启 kubelet: systemctl restart kubelet"
EOF

chmod +x /root/tag-manifest-images.sh
sudo /root/tag-manifest-images.sh

        先 chmod +x tag-manifest-images.sh 然后执行 sudo ./tag-manifest-images.sh

脚本作用

脚本会:

  • 列出 /etc/kubernetes/manifests 中所有 image: 值;

  • 对每个需要的 image,检查本地是否已有该精确 image(docker image inspect);

  • 如果没有精确镜像,脚本会尝试在本地镜像仓库里找“最后一段(basename)相同”的镜像(比如 pause:3.9pause:3.6 basename 都是 pause),并将第一个匹配到的本地镜像 docker tag 成所需名字;

  • 对找不到的 image,会把它列出来,提示你手动 pull 或在可翻墙机器上拉下来后 docker load

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐