123 lines
3.8 KiB
Bash
123 lines
3.8 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
# 说明:
|
||
|
|
# 在 master、node1、node2 三台节点上分别拉取指定镜像, 并导入到 containerd (k8s.io 命名空间)
|
||
|
|
# 不通过主机分发镜像归档, 而是每台节点各自拉取/导入。
|
||
|
|
#
|
||
|
|
# 使用示例:
|
||
|
|
# chmod +x k8s-image-pull-and-import.sh
|
||
|
|
# ./k8s-image-pull-and-import.sh beppeb/devstar-controller-manager:3.0.0.without_istio
|
||
|
|
#
|
||
|
|
# 可选环境变量:
|
||
|
|
# SSH_KEY 指定私钥路径 (默认: ~/.ssh/id_rsa, 若存在自动携带)
|
||
|
|
|
||
|
|
echo "==== K8s 镜像拉取并导入 containerd ===="
|
||
|
|
|
||
|
|
if [ $# -lt 1 ]; then
|
||
|
|
echo "用法: $0 <IMAGE[:TAG]>"
|
||
|
|
echo "示例: $0 beppeb/devstar-controller-manager:3.0.0.without_istio"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
IMAGE_INPUT="$1"
|
||
|
|
|
||
|
|
# 规范化镜像名, 若无 registry 前缀则补全 docker.io/
|
||
|
|
normalize_image() {
|
||
|
|
local img="$1"
|
||
|
|
if [[ "$img" != */*/* ]]; then
|
||
|
|
# 只有一个斜杠(如 library/nginx 或 beppeb/devstar-...): 仍可能缺少 registry
|
||
|
|
# Docker 的默认 registry 是 docker.io
|
||
|
|
echo "docker.io/${img}"
|
||
|
|
else
|
||
|
|
echo "$img"
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
CANONICAL_IMAGE=$(normalize_image "$IMAGE_INPUT")
|
||
|
|
echo "目标镜像: ${CANONICAL_IMAGE}"
|
||
|
|
|
||
|
|
# 节点列表: 与 k8s-step1-prepare-env.sh 风格一致
|
||
|
|
NODES=("172.17.0.15:master" "172.17.0.43:node1" "172.17.0.34:node2")
|
||
|
|
|
||
|
|
# 本机 IP 与 SSH 选项
|
||
|
|
LOCAL_IP=$(ip route get 1 | awk '{print $7; exit}')
|
||
|
|
SSH_OPTS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes'
|
||
|
|
SSH_KEY_PATH=${SSH_KEY:-$HOME/.ssh/id_rsa}
|
||
|
|
[ -f "$SSH_KEY_PATH" ] && SSH_ID="-i $SSH_KEY_PATH" || SSH_ID=""
|
||
|
|
|
||
|
|
run_remote() {
|
||
|
|
local ip="$1"; shift
|
||
|
|
local cmd="$*"
|
||
|
|
if [ "$ip" = "$LOCAL_IP" ]; then
|
||
|
|
bash -lc "$cmd"
|
||
|
|
else
|
||
|
|
ssh $SSH_OPTS $SSH_ID ubuntu@"$ip" "$cmd"
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# 在远端节点执行: 使用 docker 或 containerd 拉取镜像, 并确保导入到 containerd k8s.io
|
||
|
|
remote_pull_and_import_cmd() {
|
||
|
|
local image="$1"
|
||
|
|
# 注意: 使用单引号包裹, 传到远端后再展开变量
|
||
|
|
cat <<'EOF_REMOTE'
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
IMAGE_REMOTE="$IMAGE_PLACEHOLDER"
|
||
|
|
|
||
|
|
has_cmd() { command -v "$1" >/dev/null 2>&1; }
|
||
|
|
|
||
|
|
echo "[\"$(hostname)\"] 处理镜像: ${IMAGE_REMOTE}"
|
||
|
|
|
||
|
|
# 优先尝试 docker 拉取, 成功后直接导入 containerd (无需落盘)
|
||
|
|
if has_cmd docker; then
|
||
|
|
echo "[\"$(hostname)\"] 使用 docker pull"
|
||
|
|
sudo docker pull "${IMAGE_REMOTE}"
|
||
|
|
echo "[\"$(hostname)\"] 导入到 containerd (k8s.io)"
|
||
|
|
sudo docker save "${IMAGE_REMOTE}" | sudo ctr -n k8s.io images import - >/dev/null
|
||
|
|
else
|
||
|
|
echo "[\"$(hostname)\"] 未检测到 docker, 尝试使用 containerd 拉取"
|
||
|
|
# containerd 直接拉取到 k8s.io 命名空间
|
||
|
|
sudo ctr -n k8s.io images pull --all-platforms "${IMAGE_REMOTE}"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# 规范化 tag: 若镜像缺少 docker.io 前缀, 在 containerd 内补齐一份别名
|
||
|
|
NEED_PREFIX=0
|
||
|
|
if [[ "${IMAGE_REMOTE}" != docker.io/* ]]; then
|
||
|
|
NEED_PREFIX=1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ "$NEED_PREFIX" -eq 1 ]; then
|
||
|
|
# 仅当不存在 docker.io/ 前缀时, 补一个 docker.io/ 的 tag, 方便与清单匹配
|
||
|
|
# 计算补齐后的名字
|
||
|
|
if [[ "${IMAGE_REMOTE}" == */*/* ]]; then
|
||
|
|
# 已有显式 registry, 不重复打 tag
|
||
|
|
:
|
||
|
|
else
|
||
|
|
FIXED="docker.io/${IMAGE_REMOTE}"
|
||
|
|
echo "[\"$(hostname)\"] 为 containerd 打标签: ${FIXED}"
|
||
|
|
sudo ctr -n k8s.io images tag "${IMAGE_REMOTE}" "${FIXED}" || true
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "[\"$(hostname)\"] 验证镜像是否存在于 containerd:"
|
||
|
|
sudo ctr -n k8s.io images ls | grep -E "$(printf '%s' "${IMAGE_REMOTE}" | sed 's/[\/.\-]/\\&/g')" || true
|
||
|
|
EOF_REMOTE
|
||
|
|
}
|
||
|
|
|
||
|
|
# 遍历节点执行
|
||
|
|
for node in "${NODES[@]}"; do
|
||
|
|
IFS=':' read -r ip hostname <<< "$node"
|
||
|
|
echo "==== 在 ${hostname} (${ip}) 执行镜像拉取与导入 ===="
|
||
|
|
# 将占位符替换为实际镜像并远程执行
|
||
|
|
remote_script=$(remote_pull_and_import_cmd "$CANONICAL_IMAGE")
|
||
|
|
# 安全替换占位符为镜像名
|
||
|
|
remote_script=${remote_script//\$IMAGE_PLACEHOLDER/$CANONICAL_IMAGE}
|
||
|
|
run_remote "$ip" "$remote_script"
|
||
|
|
echo ""
|
||
|
|
done
|
||
|
|
|
||
|
|
echo "==== 完成 ===="
|
||
|
|
|
||
|
|
|