12 KiB
12 KiB
镜像缓存工具使用指南
概述
cache-image.sh 是一个通用的 Kubernetes 镜像缓存工具,通过 EU Harbor 中转将镜像缓存到本地 Harbor,解决 Docker Hub 等公网仓库访问超时问题。
核心功能
- ✅ 单个镜像缓存 - 快速缓存指定镜像
- ✅ 批量缓存 - 从文件或命令行批量处理
- ✅ 自动更新 Deployment - 缓存后自动更新 K8s 部署
- ✅ 从 Pod 提取镜像 - 分析失败 Pod 并缓存其镜像
- ✅ 智能镜像解析 - 自动处理各种镜像格式
- ✅ 详细进度显示 - 完整的执行日志和统计
快速开始
基本用法
# 缓存单个镜像
./cache-image.sh nginx:alpine
# 缓存多个镜像
./cache-image.sh nginx:alpine redis:7 mysql:8.0
# 从文件批量缓存
./cache-image.sh -f images.txt
高级用法
# 自动修复 Deployment 镜像拉取问题
./cache-image.sh --update-deployment kubernetes-dashboard/kubernetes-dashboard
# 从失败的 Pod 获取镜像并缓存
./cache-image.sh --from-pod kubernetes-dashboard/dashboard-xxx
# 预览操作(不实际执行)
./cache-image.sh --dry-run nginx:alpine redis:7
使用场景
场景 1: Deployment 镜像拉取失败
问题:
kubectl get pods -n kubernetes-dashboard
NAME READY STATUS RESTARTS AGE
kubernetes-dashboard-79cbcf9fb6-hwpxp 0/1 ImagePullBackOff 0 5m
解决:
# 方案 A: 自动修复(推荐)
./cache-image.sh --update-deployment kubernetes-dashboard/kubernetes-dashboard
# 方案 B: 手动缓存
kubectl describe pod kubernetes-dashboard-79cbcf9fb6-hwpxp -n kubernetes-dashboard | grep Image:
# 输出: Image: kubernetesui/dashboard:v2.7.0
./cache-image.sh kubernetesui/dashboard:v2.7.0
# 然后手动更新
kubectl set image deployment/kubernetes-dashboard \
kubernetes-dashboard=harbor.omniverseai.net:8080/library/dashboard:v2.7.0 \
-n kubernetes-dashboard
场景 2: 新部署应用前预缓存
应用 YAML:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: app
image: myorg/myapp:v1.0.0
- name: sidecar
image: envoyproxy/envoy:v1.28.0
预缓存镜像:
./cache-image.sh myorg/myapp:v1.0.0 envoyproxy/envoy:v1.28.0
部署时使用本地镜像:
spec:
template:
spec:
containers:
- name: app
image: harbor.omniverseai.net:8080/library/myapp:v1.0.0
- name: sidecar
image: harbor.omniverseai.net:8080/library/envoy:v1.28.0
场景 3: 批量预热镜像
创建镜像列表文件 (images.txt):
# Monitoring stack
prometheus/prometheus:v2.45.0
grafana/grafana:10.0.0
prom/node-exporter:v1.6.0
# Databases
mysql:8.0
redis:7.2-alpine
postgres:15-alpine
# Application
nginx:alpine
python:3.11-slim
批量缓存:
./cache-image.sh -f images.txt
输出示例:
[INFO] 从文件读取镜像列表: images.txt
[INFO] 找到 8 个镜像
[INFO] 进度: [1/8] 处理: prometheus/prometheus:v2.45.0
───────────────────────────────────────────────
[✓] 镜像缓存完成!
本地路径: harbor.omniverseai.net:8080/library/prometheus:v2.45.0
───────────────────────────────────────────────
...
═══════════════════════════════════════════════
[INFO] 批量缓存完成统计
═══════════════════════════════════════════════
总计: 8
成功: 7
失败: 1
场景 4: Helm Chart 部署前准备
检查 Helm Chart 需要的镜像:
# 查看将要部署的镜像
helm template my-release stable/mysql | grep "image:"
# 输出:
# image: "mysql:8.0"
# image: "busybox:1.35"
预缓存镜像:
./cache-image.sh mysql:8.0 busybox:1.35
部署时覆盖镜像:
helm install my-release stable/mysql \
--set image.repository=harbor.omniverseai.net:8080/library/mysql \
--set image.tag=8.0
命令参考
选项说明
| 选项 | 说明 | 示例 |
|---|---|---|
-f, --file |
从文件读取镜像列表 | -f images.txt |
-p, --project |
指定 Harbor 项目(默认 library) | -p myproject |
-u, --update-deployment |
缓存后自动更新 Deployment | --update-deployment ns/deploy |
--from-pod |
从 Pod 提取镜像并缓存 | --from-pod ns/pod-name |
--dry-run |
仅显示操作,不实际执行 | --dry-run |
-h, --help |
显示帮助信息 | -h |
镜像格式支持
脚本会自动解析以下格式的镜像:
| 输入格式 | 解析结果 | 本地 Harbor 路径 |
|---|---|---|
nginx:alpine |
nginx:alpine | harbor.omniverseai.net:8080/library/nginx:alpine |
nginx |
nginx:latest | harbor.omniverseai.net:8080/library/nginx:latest |
mysql/mysql-server:8.0 |
mysql-server:8.0 | harbor.omniverseai.net:8080/library/mysql-server:8.0 |
docker.io/library/redis:7 |
redis:7 | harbor.omniverseai.net:8080/library/redis:7 |
gcr.io/project/image:v1 |
image:v1 | harbor.omniverseai.net:8080/library/image:v1 |
quay.io/org/app:latest |
app:latest | harbor.omniverseai.net:8080/library/app:latest |
规则:
- 自动移除 registry 前缀(docker.io, gcr.io, quay.io 等)
- 自动移除组织前缀(保留镜像名)
- 未指定 tag 时自动添加
:latest - 统一推送到本地 Harbor 的
library项目
工作流程
单个镜像缓存流程
输入镜像: nginx:alpine
↓
[1/5] 从 EU Harbor 拉取
├─ 尝试: harbor.eu.lingjingwanxiang.cn/library/nginx:alpine
└─ 失败则尝试: harbor.eu.lingjingwanxiang.cn/dockerhub-proxy/library/nginx:alpine
↓
[2/5] 标记为本地镜像
→ docker tag ... harbor.omniverseai.net:8080/library/nginx:alpine
↓
[3/5] 推送到本地 Harbor
→ docker push harbor.omniverseai.net:8080/library/nginx:alpine
↓
[4/5] 验证拉取
→ docker pull harbor.omniverseai.net:8080/library/nginx:alpine
↓
[5/5] 检查架构
→ docker inspect ... --format '{{.Architecture}}'
↓
✅ 完成
自动更新 Deployment 流程
输入: kubernetes-dashboard/kubernetes-dashboard
↓
[1] 获取 Deployment 信息
→ kubectl get deployment kubernetes-dashboard -n kubernetes-dashboard
↓
[2] 提取所有容器镜像
→ kubernetesui/dashboard:v2.7.0
→ kubernetesui/metrics-scraper:v1.0.8
↓
[3] 批量缓存镜像
→ ./cache-image.sh kubernetesui/dashboard:v2.7.0 kubernetesui/metrics-scraper:v1.0.8
↓
[4] 更新 Deployment 镜像
→ kubectl set image deployment/kubernetes-dashboard \
kubernetes-dashboard=harbor.omniverseai.net:8080/library/dashboard:v2.7.0 \
dashboard-metrics-scraper=harbor.omniverseai.net:8080/library/metrics-scraper:v1.0.8
↓
[5] 验证 Pod 重启
→ kubectl get pods -n kubernetes-dashboard
↓
✅ 完成
集成到 Claude 工作流
在部署脚本中使用
#!/bin/bash
# deploy-my-app.sh
set -e
# 定义镜像
IMAGES=(
"myorg/myapp:v1.0.0"
"redis:7.2-alpine"
"nginx:alpine"
)
# 预缓存镜像
echo "=== 预缓存镜像 ==="
/path/to/cache-image.sh "${IMAGES[@]}"
# 部署应用
echo "=== 部署应用 ==="
kubectl apply -f deployment.yaml
# 等待就绪
echo "=== 等待 Pod 就绪 ==="
kubectl rollout status deployment/myapp -n default
作为 Pre-flight Check
#!/bin/bash
# preflight-check.sh
# 检查并缓存 Helm Chart 依赖镜像
CHART_IMAGES=$(helm template my-release ./mychart | grep "image:" | awk '{print $2}' | tr -d '"' | sort -u)
echo "=== 预缓存 Helm Chart 镜像 ==="
for image in $CHART_IMAGES; do
/path/to/cache-image.sh "$image" || {
echo "警告: 镜像 $image 缓存失败"
}
done
# 部署 Helm Chart
helm install my-release ./mychart
在 CI/CD 中使用
Gitea Actions / GitHub Actions:
name: Deploy to Kubernetes
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Cache Docker images
run: |
chmod +x ./cache-image.sh
./cache-image.sh -f .ci/images.txt
- name: Deploy to K8s
run: |
kubectl apply -f k8s/
kubectl rollout status deployment/myapp
故障排查
问题 1: EU Harbor 连接失败
错误:
[✗] 两个源都拉取失败: nginx:alpine
解决:
# 检查 EU Harbor 连通性
curl -I https://harbor.eu.lingjingwanxiang.cn
# 检查 Docker 代理配置
docker info | grep -i proxy
# 手动登录测试
docker login harbor.eu.lingjingwanxiang.cn -u admin -p Harbor12345
问题 2: 本地 Harbor 推送失败
错误:
[✗] 推送失败
denied: requested access to the resource is denied
解决:
# 检查本地 Harbor 状态
curl http://192.168.1.83:8080/api/v2.0/health
# 检查 library 项目是否存在
curl -u admin:admin123 http://192.168.1.83:8080/api/v2.0/projects | jq '.[] | select(.name=="library")'
# 重新登录
docker login harbor.omniverseai.net:8080 -u admin -p admin123
问题 3: Deployment 更新失败
错误:
Error from server (NotFound): deployments.apps "kubernetes-dashboard" not found
解决:
# 检查 Deployment 是否存在
kubectl get deployment -n kubernetes-dashboard
# 检查命名空间格式
./cache-image.sh --update-deployment kubernetes-dashboard/kubernetes-dashboard
# ↑ namespace ↑ deployment name
高级技巧
1. 指定自定义 Harbor 项目
# 推送到 myproject 项目
./cache-image.sh -p myproject nginx:alpine
# 结果: harbor.omniverseai.net:8080/myproject/nginx:alpine
2. 批量处理带注释的镜像列表
images.txt:
# Production images
nginx:1.24-alpine # Web server
redis:7.2-alpine # Cache
# Development images
python:3.11-slim # Dev runtime
postgres:15-alpine # Dev database
./cache-image.sh -f images.txt
# 自动跳过注释和空行
3. 组合使用 kubectl 和 cache-image
# 获取集群中所有使用的镜像
kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{end}' | \
sort -u > cluster-images.txt
# 全部缓存到本地
./cache-image.sh -f cluster-images.txt
4. 并行缓存(使用 GNU Parallel)
# 安装 parallel
brew install parallel
# 并行缓存(4 个并发)
cat images.txt | parallel -j4 ./cache-image.sh {}
性能优化
缓存统计
# 单个镜像平均耗时: ~30-60 秒
# - 拉取: 15-30s(取决于镜像大小)
# - 推送: 10-20s
# - 验证: 5-10s
# 批量缓存 10 个镜像: ~5-10 分钟
加速建议
-
使用本地 Docker 缓存
- Docker 会缓存已拉取的 layer
- 相同 base image 只需拉取一次
-
批量操作优先
# 推荐(单次登录) ./cache-image.sh img1 img2 img3 # 不推荐(多次登录) ./cache-image.sh img1 ./cache-image.sh img2 ./cache-image.sh img3 -
使用 --dry-run 预检
./cache-image.sh --dry-run -f large-list.txt # 快速验证镜像格式和数量
最佳实践
1. 部署前预缓存
# 创建项目镜像清单
cat > myapp-images.txt << EOF
myapp/backend:v1.2.3
myapp/frontend:v1.2.3
redis:7.2-alpine
postgres:15
EOF
# 部署前缓存
./cache-image.sh -f myapp-images.txt
# 然后部署
kubectl apply -f myapp-deployment.yaml
2. 定期同步关键镜像
# 创建 cron 任务
0 2 * * * /path/to/cache-image.sh -f /path/to/critical-images.txt
3. 版本化镜像管理
# 按环境组织
./cache-image.sh -f images-prod.txt
./cache-image.sh -f images-staging.txt
./cache-image.sh -f images-dev.txt
相关文档
- 主 README: README.md
- 镜像缓存方案: HARBOR-IMAGE-CACHE-SOLUTION.md
- 端口参考: PORT-REFERENCE.md
- Dashboard 访问: DASHBOARD-ACCESS-GUIDE.md
脚本位置: /Users/brunogao/work/codes/tools/macos/k8s/cache-image.sh
最后更新: 2025-12-24
版本: v1.0