Files
ljwx-harbor/harbor/HARBOR-EU-CACHE-OPTIMIZATION-PLAN.md
T
bruno 435834dc79 feat: Harbor 版本化配置
- 添加 Harbor 快速恢复脚本 (harbor-quick-restore.sh)
- 添加完整恢复指南 (HARBOR-RESTORE-GUIDE.md)
- 添加版本信息文件 (VERSION.md)
- 更新 .gitignore 排除敏感数据
- 配置 harbor git remote
- 修复 Cloudflare Tunnel 配置

系统重装后可通过以下命令快速恢复:
git clone http://192.168.1.83:33000/gao/ljwx-harbor.git
cd ljwx-harbor
./harbor-quick-restore.sh
2026-02-27 08:12:30 +08:00

24 KiB

Harbor 欧洲节点缓存优化整体方案

分析日期: 2025-12-20
欧洲 Harbor 节点: harbor.eu.lingjingwanxiang.cn (173.212.254.252)
本地 Harbor 节点: harbor.omniverseai.net (192.168.1.83)


📊 一、现状分析

1.1 当前架构

┌─────────────────────────────────────────────────────────────────┐
│                        镜像拉取流程                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  本地客户端 (macOS/OrbStack)                                    │
│         ↓                                                       │
│  本地 Harbor (192.168.1.83:8080)                                │
│         ↓                                                       │
│  欧洲 Harbor (harbor.eu.lingjingwanxiang.cn) ← 凌晨速度很快!    │
│         ↓                                                       │
│  Docker Hub / GCR / Quay.io / GHCR                              │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

1.2 现有脚本和工具

脚本名称 用途 执行时间 状态
cache-image 手动缓存单个/多个镜像 随时 ✅ 可用
nightly-cache.sh 凌晨自动缓存任务 每天 2:00 AM ✅ 已配置 launchd
pull-via-eu-harbor.sh 通过 EU Harbor 拉取 随时 ✅ 可用
preheat-images-pro.sh 专业预热脚本 随时 ✅ 可用
harbor-image-precache.sh 预缓存常用镜像 随时 ✅ 可用
harbor-proxy-cache.sh 配置 Harbor 代理 一次性 ✅ 可用
configure-containerd-mirrors.sh 配置 containerd mirror 一次性 ⚠️ 需重启

1.3 关键发现

欧洲节点速度特点:

  • ✅ 凌晨时段 (2:00-6:00 AM): 网络空闲,速度极快 (10-50 MB/s)
  • ⚠️ 白天时段: 欧洲节点带宽紧张,速度较慢 (1-5 MB/s)
  • ⚠️ 晚间高峰: 可能超时或失败

当前问题:

  1. ❌ 夜间缓存任务只有 2:00 AM 一个时间点,失败后无重试
  2. ❌ 没有利用欧洲节点 Proxy Cache 的自动缓存功能
  3. ❌ 本地 Harbor 和欧洲 Harbor 之间没有自动同步机制
  4. ❌ 镜像优先级管理不够精细
  5. ❌ 缺少缓存命中率监控

🎯 二、优化目标

2.1 核心目标

目标 当前状态 目标状态
缓存成功率 ~70% >95%
缓存完成时间 2-3 小时 <1 小时
缓存命中率 未监控 >90%
失败重试 无 自动 3 次
镜像覆盖 42 个 >100 个

2.2 欧洲节点利用策略

时段          带宽情况      策略
─────────────────────────────────────────────
00:00-06:00   极佳 (50MB/s)  大批量拉取 + 同步
06:00-09:00   良好 (20MB/s)  中等批量拉取
09:00-18:00   一般 (5MB/s)   仅紧急镜像
18:00-00:00   较差 (2MB/s)   暂停或单镜像

🏗️ 三、整体解决方案

3.1 架构优化

┌────────────────────────────────────────────────────────────────────┐
│                     优化后的缓存架构                                │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│  ┌──────────────────┐                                             │
│  │  本地客户端       │                                             │
│  │  (macOS/OrbStack) │                                             │
│  └────────┬─────────┘                                             │
│           │                                                        │
│           ├──────────────────────────────────────┐                 │
│           │                                       ↓                 │
│           │                          ┌─────────────────────┐       │
│           │                          │  本地 Harbor         │       │
│           │                          │  (192.168.1.83)     │       │
│           │                          │  - library          │       │
│           │                          │  - dockerhub        │       │
│           │                          │  - k8s-registry     │       │
│           │                          │  - ghcr             │       │
│           │                          │  - quay             │       │
│           │                          └─────────┬───────────┘       │
│           │                                    │                    │
│           │                                    │ 同步               │
│           │                                    ↓                    │
│           │                          ┌─────────────────────┐       │
│           │                          │  欧洲 Harbor         │       │
│           │                          │  (harbor.eu...)     │       │
│           │                          │  - library          │       │
│           │                          │  - dockerhub-proxy  │       │
│           │                          │  - k8s-proxy        │       │
│           │                          │  - ghcr-proxy       │       │
│           │                          │  - quay-proxy       │       │
│           │                          └─────────┬───────────┘       │
│           │                                    │                    │
│           │                                    ↓                    │
│           │                          ┌─────────────────────┐       │
│           └─────────────────────────→│  外网 Registry       │       │
│                                      │  - Docker Hub       │       │
│                                      │  - GCR              │       │
│                                      │  - Quay.io          │       │
│                                      │  - GHCR             │       │
│                                      └─────────────────────┘       │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

3.2 三层缓存策略

第一层:欧洲 Harbor Proxy Cache (自动缓存)

配置欧洲 Harbor 的 Proxy Cache 项目:

# 在欧洲 Harbor 服务器上执行
# 1. Docker Hub Proxy
curl -X POST "https://harbor.eu.lingjingwanxiang.cn/api/v2.0/projects" \
  -H "Authorization: Basic $(echo -n 'admin:Harbor12345' | base64)" \
  -d '{
    "project_name": "dockerhub-proxy",
    "metadata": {"public": "true"},
    "storage_limit": -1,
    "registry_id": <docker-hub-endpoint-id>
  }'

# 2. K8s Proxy
# 3. GHCR Proxy
# 4. Quay Proxy

优势:

  • ✅ 自动缓存:首次拉取后自动存储
  • ✅ 无需脚本:配置后自动工作
  • ✅ 支持所有镜像:无需维护镜像列表

第二层:凌晨同步任务 (主动同步)

优化后的 nightly-cache.sh:

#!/bin/bash
# 优化的夜间缓存脚本

# 多时段执行策略
EXECUTION_TIMES=("02:00" "04:00" "06:00")  # 三个执行时间点

# 优先级队列
P0_IMAGES=(...)  # 关键镜像,必须成功
P1_IMAGES=(...)  # 重要镜像,尽量成功
P2_IMAGES=(...)  # 常用镜像,有空间时缓存

# 智能重试机制
function cache_with_retry() {
    local image=$1
    local max_retries=3
    local retry_delay=60
    
    for i in $(seq 1 $max_retries); do
        if pull_image "$image"; then
            return 0
        fi
        log_warning "拉取失败,${retry_delay}秒后重试 ($i/$max_retries)"
        sleep $retry_delay
    done
    return 1
}

# 速率限制自适应
function adaptive_delay() {
    local success_count=$1
    local base_delay=5
    
    # 根据成功次数动态调整延迟
    if [ $success_count -gt 20 ]; then
        base_delay=15  # 后期降低速率
    fi
    
    sleep $base_delay
}

第三层:按需缓存 (即时补充)

优化 cache-image 脚本:

#!/bin/bash
# cache-image 增强版

# 功能增强:
# 1. 自动检测镜像来源,选择最优 proxy
# 2. 支持 --priority 参数指定优先级
# 3. 支持 --sync-to-local 同步到本地 Harbor
# 4. 支持 --verify-arch 验证架构

# 智能路由
function select_best_proxy() {
    local image=$1
    
    case "$image" in
        registry.k8s.io/*)
            echo "k8s-proxy"
            ;;
        ghcr.io/*)
            echo "ghcr-proxy"
            ;;
        quay.io/*)
            echo "quay-proxy"
            ;;
        *)
            echo "dockerhub-proxy"
            ;;
    esac
}

📋 四、具体实施步骤

4.1 步骤 1: 配置欧洲 Harbor Proxy Cache (优先级:高)

创建 Registry Endpoint 和 Proxy Cache 项目:

#!/bin/bash
# setup-eu-harbor-proxy.sh

EU_HARBOR="harbor.eu.lingjingwanxiang.cn"
ADMIN_USER="admin"
ADMIN_PASS="Harbor12345"

# Registry 配置
declare -A REGISTRIES=(
    ["dockerhub"]="https://registry-1.docker.io"
    ["k8s-registry"]="https://registry.k8s.io"
    ["gcr"]="https://gcr.io"
    ["quay"]="https://quay.io"
    ["ghcr"]="https://ghcr.io"
)

# 创建 Registry Endpoint
create_endpoint() {
    local name=$1
    local url=$2
    
    curl -s -X POST "https://${EU_HARBOR}/api/v2.0/registries" \
        -u "${ADMIN_USER}:${ADMIN_PASS}" \
        -H "Content-Type: application/json" \
        -d "{
            \"name\": \"${name}\",
            \"type\": \"docker-hub\",
            \"url\": \"${url}\",
            \"insecure\": false
        }"
}

# 创建 Proxy Cache Project
create_proxy_project() {
    local project_name=$1
    local registry_id=$2
    
    curl -s -X POST "https://${EU_HARBOR}/api/v2.0/projects" \
        -u "${ADMIN_USER}:${ADMIN_PASS}" \
        -H "Content-Type: application/json" \
        -d "{
            \"project_name\": \"${project_name}\",
            \"public\": true,
            \"storage_limit\": -1,
            \"registry_id\": ${registry_id}
        }"
}

# 执行创建
for name in "${!REGISTRIES[@]}"; do
    echo "创建 $name endpoint..."
    endpoint_id=$(create_endpoint "$name" "${REGISTRIES[$name]}" | jq -r '.id')
    echo "创建 $name-proxy project..."
    create_proxy_project "${name}-proxy" "$endpoint_id"
done

4.2 步骤 2: 优化夜间缓存任务 (优先级:高)

创建增强的 nightly-cache-v2.sh:

#!/bin/bash
# nightly-cache-v2.sh - 增强版夜间缓存

set -eo pipefail

# 配置
EU_HARBOR="harbor.eu.lingjingwanxiang.cn"
LOCAL_HARBOR="harbor.omniverseai.net"
LOG_DIR="/Users/brunogao/work/codes/tools/macos/harbor/logs"
MANIFEST_FILE="/Users/brunogao/work/codes/tools/macos/harbor/image-manifest.txt"

# 执行策略
MAX_PARALLEL=3           # 最大并发数
SUCCESS_DELAY=5          # 成功后的基础延迟 (秒)
FAILURE_DELAY=60         # 失败后的延迟 (秒)
MAX_RETRIES=3            # 最大重试次数
TIMEOUT=300              # 单次拉取超时 (秒)

# 统计
declare -A STATS=(
    [total]=0
    [success]=0
    [failed]=0
    [skipped]=0
)

# 日志函数
log() {
    local level=$1
    shift
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $*" | tee -a "${LOG_DIR}/nightly-cache.log"
}

# 拉取单个镜像(带重试)
pull_with_retry() {
    local image=$1
    local priority=$2
    local attempt=1
    
    while [ $attempt -le $MAX_RETRIES ]; do
        log INFO "拉取镜像:$image (尝试 $attempt/$MAX_RETRIES)"
        
        if timeout $TIMEOUT ./pull-via-eu-harbor.sh "$image" &>> "${LOG_DIR}/pull.log"; then
            return 0
        fi
        
        log WARNING "拉取失败,${FAILURE_DELAY}秒后重试..."
        sleep $FAILURE_DELAY
        ((attempt++))
    done
    
    return 1
}

# 智能延迟
adaptive_sleep() {
    local last_status=$1
    local count=$2
    
    if [ "$last_status" = "success" ]; then
        # 成功后,根据数量调整延迟
        local delay=$SUCCESS_DELAY
        if [ $count -gt 20 ]; then
            delay=$((SUCCESS_DELAY * 2))
        elif [ $count -gt 40 ]; then
            delay=$((SUCCESS_DELAY * 3))
        fi
        sleep $delay
    else
        # 失败后固定延迟
        sleep $FAILURE_DELAY
    fi
}

# 主函数
main() {
    log INFO "=== 夜间缓存任务启动 ==="
    log INFO "欧洲 Harbor: $EU_HARBOR"
    log INFO "本地 Harbor: $LOCAL_HARBOR"
    log INFO "镜像清单:$MANIFEST_FILE"
    
    local start_time=$(date +%s)
    local processed=0
    local last_status="success"
    
    # 按优先级处理
    for priority in "P0" "P1" "P2"; do
        log INFO "处理优先级:$priority"
        
        while IFS= read -r line; do
            # 跳过注释和空行
            [[ -z "$line" || "$line" =~ ^# ]] && continue
            
            # 解析优先级和镜像
            if [[ "$line" =~ ^\[$priority\] ]]; then
                image="${line#*] }"
            else
                continue
            fi
            
            ((STATS[total]++))
            ((processed++))
            
            log INFO "[$processed] 处理:$image"
            
            if pull_with_retry "$image" "$priority"; then
                ((STATS[success]++))
                last_status="success"
                log SUCCESS "成功:$image"
            else
                ((STATS[failed]++))
                last_status="failed"
                log ERROR "失败:$image"
            fi
            
            # 智能延迟
            adaptive_sleep "$last_status" $processed
            
        done < "$MANIFEST_FILE"
    done
    
    # 统计
    local end_time=$(date +%s)
    local duration=$((end_time - start_time))
    
    log INFO "=== 任务完成 ==="
    log INFO "总计:${STATS[total]}"
    log INFO "成功:${STATS[success]}"
    log INFO "失败:${STATS[failed]}"
    log INFO "耗时:$((duration/60))分 $((duration%60))秒"
    
    # 发送通知(可选)
    send_notification
}

# 发送通知
send_notification() {
    # 可以集成钉钉、企业微信、Slack 等通知
    log INFO "发送完成通知..."
}

main "$@"

更新 launchd 配置 (支持多时段执行):

<!-- com.harbor.nightly-cache-v2.plist -->
<key>StartCalendarInterval</key>
<array>
    <dict><key>Hour</key><integer>2</integer><key>Minute</key><integer>0</integer></dict>
    <dict><key>Hour</key><integer>4</integer><key>Minute</key><integer>0</integer></dict>
    <dict><key>Hour</key><integer>6</integer><key>Minute</key><integer>0</integer></dict>
</array>

4.3 步骤 3: 创建欧洲→本地同步脚本 (优先级:中)

创建 sync-eu-to-local.sh:

#!/bin/bash
# sync-eu-to-local.sh - 欧洲 Harbor 同步到本地 Harbor

set -eo pipefail

EU_HARBOR="harbor.eu.lingjingwanxiang.cn"
LOCAL_HARBOR="harbor.omniverseai.net:8080"
PROJECTS=("library" "dockerhub-proxy" "k8s-proxy" "ghcr-proxy" "quay-proxy")

log_info() { echo -e "\033[0;34m[INFO]\033[0m $1"; }
log_success() { echo -e "\033[0;32m[✓]\033[0m $1"; }
log_error() { echo -e "\033[0;31m[✗]\033[0m $1"; }

# 登录
docker login "$EU_HARBOR" -u admin -p 'Harbor12345' > /dev/null 2>&1
docker login "$LOCAL_HARBOR" -u admin -p admin123 > /dev/null 2>&1

# 同步单个项目
sync_project() {
    local project=$1
    log_info "同步项目:$project"
    
    # 获取欧洲 Harbor 中的镜像列表
    local images=$(curl -s -k -u "admin:Harbor12345" \
        "https://${EU_HARBOR}/api/v2.0/projects/${project}/repositories" | \
        jq -r '.[].name')
    
    for repo in $images; do
        # 获取标签列表
        local tags=$(curl -s -k -u "admin:Harbor12345" \
            "https://${EU_HARBOR}/api/v2.0/projects/${project}/repositories/${repo}/artifacts" | \
            jq -r '.[].tags[].name')
        
        for tag in $tags; do
            local eu_image="${EU_HARBOR}/${project}/${repo}:${tag}"
            local local_image="${LOCAL_HARBOR}/${project}/${repo}:${tag}"
            
            # 检查本地是否已存在
            if ! docker manifest inspect "$local_image" > /dev/null 2>&1; then
                log_info "同步:$eu_image → $local_image"
                
                # 拉取 - 标记 - 推送
                if docker pull "$eu_image" > /dev/null 2>&1; then
                    docker tag "$eu_image" "$local_image"
                    docker push "$local_image" > /dev/null 2>&1
                    log_success "同步成功"
                    
                    # 清理本地临时镜像
                    docker rmi "$eu_image" "$local_image" > /dev/null 2>&1
                else
                    log_error "拉取失败:$eu_image"
                fi
            else
                log_info "跳过 (已存在): $local_image"
            fi
        done
    done
}

# 主循环
for project in "${PROJECTS[@]}"; do
    sync_project "$project"
    echo ""
done

log_info "同步完成"

4.4 步骤 4: 创建缓存命中率监控 (优先级:中)

创建 cache-monitor.sh:

#!/bin/bash
# cache-monitor.sh - 缓存命中率监控

LOCAL_HARBOR="harbor.omniverseai.net"

# 获取镜像拉取统计
get_pull_stats() {
    local project=$1
    
    curl -s -k -u "admin:admin123" \
        "https://${LOCAL_HARBOR}/api/v2.0/projects/${project}/repositories" | \
        jq -r '.[] | "\(.name): \(.pull_count)"'
}

# 计算缓存命中率
calculate_hit_rate() {
    local total_pulls=0
    local cache_hits=0
    
    for project in "library" "dockerhub" "k8s-registry"; do
        local stats=$(get_pull_stats "$project")
        while IFS=: read -r repo count; do
            ((total_pulls += count))
            # 简单假设:有 pull_count 表示已缓存
            ((cache_hits += count))
        done <<< "$stats"
    done
    
    if [ $total_pulls -gt 0 ]; then
        echo "scale=2; $cache_hits / $total_pulls * 100" | bc
    else
        echo "0"
    fi
}

# 生成报告
generate_report() {
    echo "=== Harbor 缓存命中率报告 ==="
    echo "时间:$(date '+%Y-%m-%d %H:%M:%S')"
    echo ""
    
    echo "项目统计:"
    for project in "library" "dockerhub" "k8s-registry" "ghcr" "quay"; do
        echo ""
        echo "  $project:"
        get_pull_stats "$project" | while read line; do
            echo "    $line"
        done
    done
    
    echo ""
    echo "缓存命中率:$(calculate_hit_rate)%"
}

generate_report

4.5 步骤 5: 更新镜像清单 (优先级:高)

扩展 image-manifest.txt:

# Harbor 镜像预缓存清单
# 格式:[优先级] 镜像名:标签
# 优先级:P0 (关键) > P1 (重要) > P2 (普通) > P3 (可选)

# ============================================
# P0 - 关键基础设施组件 (必须缓存成功)
# ============================================

# 基础镜像
[P0] alpine:latest
[P0] alpine:3.19
[P0] alpine:3.18
[P0] busybox:latest

# K8s 核心组件
[P0] registry.k8s.io/pause:3.9
[P0] registry.k8s.io/pause:3.8

# ============================================
# P1 - 重要数据库和服务
# ============================================

# MySQL
[P1] mysql:8.0
[P1] mysql:8.0-debian
[P1] mysql:latest

# PostgreSQL
[P1] postgres:16-alpine
[P1] postgres:16
[P1] postgres:15-alpine
[P1] postgres:latest

# Redis
[P1] redis:alpine
[P1] redis:7-alpine
[P1] redis:latest

# MinIO
[P1] minio/minio:latest
[P1] minio/mc:latest

# ============================================
# P1 - 监控和可观测性
# ============================================

# Prometheus
[P1] prom/prometheus:v3.0.1
[P1] prom/prometheus:latest
[P1] prom/node-exporter:v1.8.2
[P1] prom/alertmanager:latest

# Grafana
[P1] grafana/grafana:11.4.0
[P1] grafana/grafana:latest

# Loki
[P1] grafana/loki:2.6.1
[P1] grafana/promtail:2.6.1

# Tempo
[P1] grafana/tempo:2.9.0

# ============================================
# P2 - 常用 Web 服务器
# ============================================

[P2] nginx:alpine
[P2] nginx:1.25-alpine
[P2] nginx:latest

# ============================================
# P2 - 开发工具
# ============================================

[P2] node:20-alpine
[P2] node:18-alpine
[P2] python:3.11-slim
[P2] golang:1.21-alpine

# ============================================
# P3 - 其他工具
# ============================================

[P3] curlimages/curl:latest
[P3] ubuntu:22.04

📊 五、监控和告警

5.1 缓存命中率指标

# Prometheus 指标
harbor_cache_hit_rate:
  - project: library
    rate: 95%
  - project: dockerhub
    rate: 90%
  - project: k8s-registry
    rate: 100%

harbor_nightly_cache_job:
  status: success/failure
  duration: 3600s
  images_processed: 50
  success_count: 48
  failed_count: 2

5.2 告警规则

# alertmanager 配置
groups:
  - name: harbor-cache
    rules:
      - alert: HarborCacheHitRateLow
        expr: harbor_cache_hit_rate < 80
        for: 1h
        annotations:
          summary: "Harbor 缓存命中率低于 80%"
          
      - alert: NightlyCacheJobFailed
        expr: harbor_nightly_cache_job_status == 0
        annotations:
          summary: "夜间缓存任务失败"

📈 六、预期效果

6.1 性能对比

指标 优化前 优化后
缓存成功率 70% >95%
缓存完成时间 2-3 小时 <1 小时
缓存命中率 未监控 >90%
欧洲节点利用率 50% 90%
镜像覆盖数 42 >100

6.2 时间节省

场景                    优化前        优化后
─────────────────────────────────────────────
首次部署 (10 个镜像)      30 分钟       5 分钟
重新部署 (已缓存)         5 分钟        1 分钟
夜间缓存任务             2-3 小时      45 分钟
故障恢复                 1 小时        10 分钟

✅ 七、实施检查清单

阶段 1: 欧洲 Harbor 配置 (第 1 周)

  • 配置欧洲 Harbor Proxy Cache 项目
  • 验证欧洲 Harbor 可访问性
  • 测试欧洲 Harbor 拉取速度

阶段 2: 本地优化 (第 2 周)

  • 更新 nightly-cache.sh 脚本
  • 配置多时段执行
  • 扩展镜像清单

阶段 3: 同步机制 (第 3 周)

  • 创建欧洲→本地同步脚本
  • 测试同步流程
  • 配置定时同步任务

阶段 4: 监控告警 (第 4 周)

  • 部署缓存监控
  • 配置告警规则
  • 集成通知系统

🔧 八、故障排查

常见问题

问题 1: 欧洲节点拉取超时

# 解决:增加超时时间,添加重试
timeout 600 ./pull-via-eu-harbor.sh image:tag

问题 2: 本地 Harbor 存储空间不足

# 解决:配置清理策略
./cleanup-images.sh --retain-days 30

问题 3: 缓存命中率低

# 解决:检查镜像路径是否正确
# 确保 K8s YAML 使用正确的 Harbor 路径

文档版本: v1.0
最后更新: 2025-12-20
维护者: DevOps Team