Files
ljwx-k8s/direct-cache-failed-images.sh
2026-02-20 22:50:45 +08:00

193 lines
5.7 KiB
Bash
Executable File

#!/bin/bash
# 直接从源拉取镜像并推送到本地 Harbor
# 用于处理 EU Harbor 无法代理的镜像
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_error() { echo -e "${RED}[✗]${NC} $1"; }
log_warning() { echo -e "${YELLOW}[!]${NC} $1"; }
log_step() { echo -e "${CYAN}[→]${NC} $1"; }
LOCAL_HARBOR="harbor.omniverseai.net"
HARBOR_PROJECT="library"
# 解析镜像名称(移除 registry 前缀)
parse_image_name() {
local input_image="$1"
local image_name=""
local image_tag="latest"
# 移除 registry 前缀
if [[ "$input_image" =~ ^[^/]+\.[^/]+/ ]]; then
input_image=$(echo "$input_image" | sed -E 's|^[^/]+\.[^/]+/||')
fi
# 分离镜像名和标签
if [[ "$input_image" =~ : ]]; then
image_name="${input_image%:*}"
image_tag="${input_image##*:}"
else
image_name="$input_image"
fi
echo "${image_name}:${image_tag}"
}
# 扁平化镜像名
normalize_for_local_storage() {
local image="$1"
echo "$image" | sed 's|/|-|g'
}
# 直接缓存单个镜像
direct_cache_image() {
local input_image="$1"
log_info "=== 直接缓存镜像: $input_image ==="
# 解析镜像名
local normalized_image=$(parse_image_name "$input_image")
local local_image_name=$(normalize_for_local_storage "$normalized_image")
local dest_image="${LOCAL_HARBOR}/${HARBOR_PROJECT}/${local_image_name}"
log_info "本地存储为: $local_image_name"
# 直接从源拉取
log_step "[1/4] 从源拉取镜像(300秒超时)..."
if ! timeout 300 docker pull "$input_image" 2>&1 | grep -v "WARNING"; then
log_error "拉取失败: $input_image"
return 1
fi
log_success "拉取成功"
# 标记
log_step "[2/4] 标记镜像..."
if ! docker tag "$input_image" "$dest_image"; then
log_error "标记失败"
return 1
fi
log_success "标记成功"
# 推送
log_step "[3/4] 推送到本地 Harbor..."
if ! docker push "$dest_image" 2>&1 | grep -v "WARNING"; then
log_error "推送失败"
return 1
fi
log_success "推送成功"
# 验证
log_step "[4/4] 验证..."
docker rmi "$dest_image" &> /dev/null || true
if ! docker pull "$dest_image" &> /dev/null; then
log_error "验证失败"
return 1
fi
log_success "验证成功"
echo ""
log_success "✅ 镜像缓存完成!"
echo " 原始镜像: $input_image"
echo " 本地路径: $dest_image"
echo ""
return 0
}
# 登录本地 Harbor
log_step "登录本地 Harbor..."
if ! echo 'admin123' | docker login "$LOCAL_HARBOR" -u admin --password-stdin > /dev/null 2>&1; then
log_error "本地 Harbor 登录失败"
exit 1
fi
log_success "登录成功"
echo ""
# 失败的镜像列表
FAILED_IMAGES=(
"registry.k8s.io/pause:3.9"
"registry.k8s.io/coredns/coredns:v1.11.3"
"registry.k8s.io/ingress-nginx/controller:v1.11.3"
"registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231226-1a7112e06"
"registry.k8s.io/autoscaling/vpa-updater:1.2.0"
"registry.k8s.io/autoscaling/vpa-admission-controller:1.2.0"
"registry.k8s.io/dns/k8s-dns-node-cache:1.23.0"
"registry.k8s.io/sig-storage/livenessprobe:v2.14.0"
"registry.k8s.io/gateway-api/admission-server:v1.2.0"
"registry.k8s.io/dashboard/dashboard:v2.7.0"
"registry.k8s.io/dashboard/metrics-scraper:v1.0.9"
"nicolaka/netshoot:latest"
"quay.io/jetstack/cert-manager-controller:v1.16.2"
"quay.io/jetstack/cert-manager-webhook:v1.16.2"
"quay.io/jetstack/cert-manager-cainjector:v1.16.2"
"quay.io/jetstack/cert-manager-acmesolver:v1.16.2"
"quay.io/argoproj/argocd:v2.13.2"
"quay.io/argoproj/argocd:v2.13.1"
"quay.io/prometheus/prometheus:v2.55.1"
"quay.io/prometheus/prometheus:v2.55.0"
"quay.io/prometheus/alertmanager:v0.27.0"
"quay.io/prometheus/node-exporter:v1.8.2"
"quay.io/prometheus/blackbox-exporter:v0.25.0"
"grafana/tempo:2.7.3"
"aquasec/trivy:0.58.2"
"velero/velero:v1.15.0"
"ghcr.io/external-secrets/external-secrets:v0.11.0"
"quay.io/bitnami/sealed-secrets-controller:v0.27.2"
"ghcr.io/stakater/reloader:v1.2.3"
)
TOTAL=${#FAILED_IMAGES[@]}
SUCCESS=0
FAILED=0
FAILED_LIST=()
log_info "开始处理 $TOTAL 个失败的镜像..."
echo ""
for i in "${!FAILED_IMAGES[@]}"; do
image="${FAILED_IMAGES[$i]}"
current=$((i + 1))
echo ""
log_info "进度: [$current/$TOTAL] 处理: $image"
echo "───────────────────────────────────────────────"
if direct_cache_image "$image"; then
((SUCCESS++))
else
((FAILED++))
FAILED_LIST+=("$image")
fi
echo "───────────────────────────────────────────────"
done
# 显示总结
echo ""
echo "═══════════════════════════════════════════════"
log_info "直接缓存完成统计"
echo "═══════════════════════════════════════════════"
echo " 总计: $TOTAL"
echo " 成功: $SUCCESS"
echo " 失败: $FAILED"
if [[ $FAILED -gt 0 ]]; then
echo ""
log_error "仍然失败的镜像:"
for img in "${FAILED_LIST[@]}"; do
echo " ✗ $img"
done
fi
echo "═══════════════════════════════════════════════"
echo ""