- 添加 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
24 KiB
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)
- ⚠️ 晚间高峰: 可能超时或失败
当前问题:
- ❌ 夜间缓存任务只有 2:00 AM 一个时间点,失败后无重试
- ❌ 没有利用欧洲节点 Proxy Cache 的自动缓存功能
- ❌ 本地 Harbor 和欧洲 Harbor 之间没有自动同步机制
- ❌ 镜像优先级管理不够精细
- ❌ 缺少缓存命中率监控
🎯 二、优化目标
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