Files
ljwx-k8s/AUTO-IMAGE-CACHE-SOLUTIONS.md
2026-02-20 22:50:45 +08:00

676 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 自动镜像缓存解决方案
## 方案对比
| 方案 | 透明度 | 自动化 | 复杂度 | 推荐度 |
|------|--------|--------|--------|--------|
| **1. OrbStack Registry Mirrors** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐ | ⭐⭐⭐⭐⭐ |
| **2. Docker Pull Wrapper** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| **3. kubectl Wrapper** | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| **4. K8s Mutating Webhook** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| **5. Claude Code Integration** | ⭐⭐⭐ | ⭐⭐⭐ | ⭐ | ⭐⭐⭐⭐ |
---
## ⭐ 推荐方案:多层防护策略
### 层级 1: OrbStack Registry Mirrors(最透明)
**原理**: 配置 OrbStack 使用本地 Harbor 作为 registry mirror,所有镜像拉取自动走缓存。
**优点**:
- ✅ 完全透明,无需修改代码
- ✅ 对所有容器运行时生效
- ✅ 性能最优
- ✅ 无需 wrapper
**缺点**:
- ⚠️ 需要预先缓存镜像
- ⚠️ 仅支持 Docker Hub
**实现**: 见下文
---
### 层级 2: Docker/kubectl Wrapper(智能拦截)
**原理**: 创建命令 wrapper,自动检测失败并缓存镜像。
**优点**:
- ✅ 自动检测和修复
- ✅ 支持所有 registry
- ✅ 可记录日志
**缺点**:
- ⚠️ 需要使用 wrapper 命令
**实现**: 见下文
---
### 层级 3: Claude Code CLAUDE.md 集成(AI 辅助)
**原理**: 在 CLAUDE.md 中添加自动修复指令,Claude 遇到镜像问题自动执行。
**优点**:
- ✅ Claude 自动识别
- ✅ 无需人工干预
- ✅ 灵活智能
**实现**: 见下文
---
## 实现方案
### 方案 1: OrbStack Registry Mirrors(推荐)
#### 配置文件位置
```
~/.orbstack/config/docker.json
```
#### 配置内容
```json
{
"registry-mirrors": [
"http://harbor.omniverseai.net:8080"
],
"insecure-registries": [
"harbor.omniverseai.net:8080"
]
}
```
#### 自动配置脚本
```bash
#!/bin/bash
# setup-orbstack-registry-mirror.sh
ORBSTACK_CONFIG="$HOME/.orbstack/config/docker.json"
HARBOR_MIRROR="http://harbor.omniverseai.net:8080"
# 创建配置目录
mkdir -p "$(dirname "$ORBSTACK_CONFIG")"
# 生成配置
cat > "$ORBSTACK_CONFIG" << EOF
{
"registry-mirrors": [
"$HARBOR_MIRROR"
],
"insecure-registries": [
"$HARBOR_MIRROR"
],
"max-concurrent-downloads": 10,
"max-concurrent-uploads": 5
}
EOF
echo "✅ OrbStack 配置已更新"
echo "⚠️ 需要重启 OrbStack 生效"
echo ""
echo "重启命令: orb restart"
```
#### 验证
```bash
# 检查配置
cat ~/.orbstack/config/docker.json
# 重启 OrbStack
orb restart
# 测试拉取
docker pull nginx:alpine
# 查看是否使用镜像
docker pull nginx:alpine 2>&1 | grep -i harbor
```
#### 限制
- ⚠️ 仅适用于 Docker Hub 镜像
- ⚠️ 需要提前缓存镜像到 Harbor
- ⚠️ gcr.io, quay.io 等不走 mirror
---
### 方案 2: Docker Pull Wrapper
#### 创建 Wrapper
```bash
#!/bin/bash
# /usr/local/bin/docker-cached
REAL_DOCKER="/usr/bin/docker"
CACHE_SCRIPT="/Users/brunogao/work/codes/tools/macos/k8s/cache-image.sh"
# 如果是 pull 命令
if [[ "$1" == "pull" ]]; then
IMAGE="$2"
echo "🔍 检查镜像: $IMAGE"
# 尝试直接拉取
if ! $REAL_DOCKER pull "$IMAGE" 2>&1 | tee /tmp/docker-pull.log | grep -q "error\|failed\|timeout"; then
echo "✅ 直接拉取成功"
exit 0
fi
# 拉取失败,使用缓存
echo "⚠️ 直接拉取失败,使用 Harbor 缓存..."
if [[ -x "$CACHE_SCRIPT" ]]; then
$CACHE_SCRIPT "$IMAGE"
# 拉取本地 Harbor 镜像
LOCAL_IMAGE="harbor.omniverseai.net:8080/library/${IMAGE##*/}"
$REAL_DOCKER pull "$LOCAL_IMAGE"
# 重新标记为原始名称
$REAL_DOCKER tag "$LOCAL_IMAGE" "$IMAGE"
echo "✅ 已从 Harbor 缓存拉取"
else
echo "❌ 缓存脚本不存在: $CACHE_SCRIPT"
exit 1
fi
else
# 其他命令直接透传
exec $REAL_DOCKER "$@"
fi
```
#### 使用方式
```bash
# 方式 1: alias
alias docker='docker-cached'
# 方式 2: PATH 优先级
export PATH="/usr/local/bin:$PATH"
# 使用
docker pull nginx:alpine # 自动缓存
```
---
### 方案 3: kubectl Wrapper(智能检测)
#### 创建 Wrapper
```bash
#!/bin/bash
# /usr/local/bin/kubectl-cached
REAL_KUBECTL="/usr/local/bin/kubectl"
CACHE_SCRIPT="/Users/brunogao/work/codes/tools/macos/k8s/cache-image.sh"
# 执行原始命令
$REAL_KUBECTL "$@"
EXIT_CODE=$?
# 如果是 apply/create 命令,检查 ImagePull 错误
if [[ "$1" =~ ^(apply|create)$ ]]; then
sleep 5 # 等待 Pod 创建
# 检查是否有 ImagePull 失败
FAILED_PODS=$($REAL_KUBECTL get pods --all-namespaces -o json | \
jq -r '.items[] | select(.status.containerStatuses[]?.state.waiting?.reason | test("ImagePull|ErrImage")) | "\(.metadata.namespace)/\(.metadata.name)"')
if [[ -n "$FAILED_PODS" ]]; then
echo ""
echo "⚠️ 检测到镜像拉取失败,自动修复中..."
echo ""
while IFS= read -r pod; do
NS="${pod%/*}"
POD_NAME="${pod##*/}"
# 获取 Deployment/StatefulSet
OWNER=$($REAL_KUBECTL get pod "$POD_NAME" -n "$NS" -o json | \
jq -r '.metadata.ownerReferences[]? | select(.kind | test("ReplicaSet|StatefulSet")) | .name')
if [[ "$OWNER" =~ ^(.+)-[a-z0-9]+$ ]]; then
DEPLOY_NAME="${BASH_REMATCH[1]}"
echo "🔧 修复: $NS/$DEPLOY_NAME"
$CACHE_SCRIPT --update-deployment "$NS/$DEPLOY_NAME"
fi
done <<< "$FAILED_PODS"
echo ""
echo "✅ 自动修复完成"
fi
fi
exit $EXIT_CODE
```
#### 使用方式
```bash
# alias
alias kubectl='kubectl-cached'
# 部署
kubectl apply -f deployment.yaml # 自动检测并修复
```
---
### 方案 4: Claude Code CLAUDE.md 集成
#### 在项目根目录添加配置
**位置**: `/Users/brunogao/work/codes/tools/macos/CLAUDE.md`
**内容**:
```markdown
# Claude Code 配置
## 镜像拉取问题自动修复
当遇到以下情况时,自动执行镜像缓存:
### 识别条件
- Kubernetes Pod 状态为 `ImagePullBackOff` 或 `ErrImagePull`
- kubectl 命令返回镜像拉取错误
- docker pull 命令超时或失败
### 自动修复流程
1. 检测到镜像拉取失败
2. 自动执行: `/Users/brunogao/work/codes/tools/macos/k8s/cache-image.sh --update-deployment <namespace>/<deployment>`
3. 等待 Pod 重启
4. 验证修复成功
### 快速修复命令
```bash
# 自动修复 Deployment
cd /Users/brunogao/work/codes/tools/macos/k8s
./cache-image.sh --update-deployment <namespace>/<deployment>
```
### 手动缓存
```bash
# 缓存单个镜像
./cache-image.sh <image>:<tag>
# 批量缓存
./cache-image.sh <image1> <image2> <image3>
```
### 重要提示
- ✅ 优先使用 `--update-deployment` 自动修复
- ✅ 所有镜像会缓存到 `harbor.omniverseai.net:8080/library/`
- ✅ 脚本支持 Docker Hub, GCR, Quay 等所有公共仓库
- ⚠️ 遇到 ImagePull 问题必须立即执行,不要等待
```
---
### 方案 5: 综合自动化脚本
#### 创建智能监控脚本
```bash
#!/bin/bash
# watch-and-fix-images.sh
# 持续监控并自动修复镜像拉取问题
CACHE_SCRIPT="/Users/brunogao/work/codes/tools/macos/k8s/cache-image.sh"
CHECK_INTERVAL=30
echo "🔍 启动镜像拉取监控..."
echo "检查间隔: ${CHECK_INTERVAL}s"
echo ""
while true; do
# 查找所有 ImagePull 失败的 Pods
FAILED_PODS=$(kubectl get pods --all-namespaces -o json 2>/dev/null | \
jq -r '.items[] |
select(.status.containerStatuses[]?.state.waiting?.reason |
test("ImagePull|ErrImage")) |
"\(.metadata.namespace)/\(.metadata.name)"')
if [[ -n "$FAILED_PODS" ]]; then
echo "⚠️ [$(date '+%Y-%m-%d %H:%M:%S')] 检测到镜像拉取失败"
echo ""
# 去重 Deployment
declare -A FIXED_DEPLOYS
while IFS= read -r pod; do
[[ -z "$pod" ]] && continue
NS="${pod%/*}"
POD_NAME="${pod##*/}"
# 获取 Deployment
OWNER=$(kubectl get pod "$POD_NAME" -n "$NS" -o json 2>/dev/null | \
jq -r '.metadata.ownerReferences[]? |
select(.kind | test("ReplicaSet")) | .name')
if [[ "$OWNER" =~ ^(.+)-[a-z0-9]+$ ]]; then
DEPLOY_NAME="${BASH_REMATCH[1]}"
DEPLOY_KEY="$NS/$DEPLOY_NAME"
# 避免重复修复
if [[ -z "${FIXED_DEPLOYS[$DEPLOY_KEY]}" ]]; then
echo "🔧 自动修复: $DEPLOY_KEY"
if $CACHE_SCRIPT --update-deployment "$DEPLOY_KEY" &>> /tmp/image-fix.log; then
echo " ✅ 修复成功"
FIXED_DEPLOYS[$DEPLOY_KEY]=1
else
echo " ❌ 修复失败,查看日志: /tmp/image-fix.log"
fi
echo ""
fi
fi
done <<< "$FAILED_PODS"
echo "等待 Pod 重启..."
sleep 10
fi
sleep $CHECK_INTERVAL
done
```
#### 后台运行
```bash
# 启动监控
nohup ./watch-and-fix-images.sh > /tmp/image-watch.log 2>&1 &
# 查看日志
tail -f /tmp/image-watch.log
# 停止监控
pkill -f watch-and-fix-images.sh
```
---
## 最佳实践:组合方案
### 推荐配置(多层防护)
```
层级 1: OrbStack Registry Mirror
↓ (90% 镜像直接缓存)
层级 2: kubectl wrapper 自动检测
↓ (剩余镜像自动修复)
层级 3: Claude Code CLAUDE.md
↓ (AI 辅助决策)
层级 4: 手动 cache-image.sh
↓ (兜底方案)
```
### 实施步骤
#### Step 1: 配置 OrbStack Mirror
```bash
./setup-orbstack-registry-mirror.sh
orb restart
```
#### Step 2: 安装 kubectl wrapper
```bash
sudo cp kubectl-cached /usr/local/bin/
echo 'alias kubectl="kubectl-cached"' >> ~/.zshrc
source ~/.zshrc
```
#### Step 3: 配置 Claude Code
```bash
# 在项目根目录 CLAUDE.md 添加镜像修复指令
cat >> /Users/brunogao/work/codes/tools/macos/CLAUDE.md << 'EOF'
## 自动镜像缓存
遇到 ImagePullBackOff 时自动执行:
```bash
cd /Users/brunogao/work/codes/tools/macos/k8s
./cache-image.sh --update-deployment <namespace>/<deployment>
```
EOF
```
#### Step 4: (可选)启动后台监控
```bash
# 开机自启动
cat > ~/Library/LaunchAgents/com.k8s.image-watcher.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.k8s.image-watcher</string>
<key>ProgramArguments</key>
<array>
<string>/Users/brunogao/work/codes/tools/macos/k8s/watch-and-fix-images.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/image-watch.log</string>
<key>StandardErrorPath</key>
<string>/tmp/image-watch-error.log</string>
</dict>
</plist>
EOF
launchctl load ~/Library/LaunchAgents/com.k8s.image-watcher.plist
```
---
## 方案对比详细分析
### 1. OrbStack Registry Mirror
**工作原理**:
```
docker pull nginx:alpine
↓
OrbStack 拦截
↓
首先查询: harbor.omniverseai.net:8080/library/nginx:alpine
├─ 存在 → 直接使用 ✅
└─ 不存在 → 回退到 Docker Hub
```
**优点**:
- 完全透明
- 性能最高
- 无需代码修改
**缺点**:
- 仅支持 Docker Hub
- 需要预缓存
**适用场景**:
- 常用基础镜像(nginx, redis, mysql)
- 已知镜像列表
---
### 2. Docker/kubectl Wrapper
**工作原理**:
```
kubectl apply -f deployment.yaml
↓
kubectl-cached 拦截
↓
执行原始命令
↓
检测 ImagePull 错误
├─ 无错误 → 完成 ✅
└─ 有错误 → 自动执行 cache-image.sh
↓
缓存镜像
↓
更新 Deployment
↓
完成 ✅
```
**优点**:
- 自动检测
- 支持所有 registry
- 可记录日志
**缺点**:
- 首次部署会失败
- 需要等待修复
**适用场景**:
- 新镜像部署
- 不确定的镜像
---
### 3. Claude Code Integration
**工作原理**:
```
Claude 执行 kubectl apply
↓
检测到 ImagePullBackOff
↓
读取 CLAUDE.md 指令
↓
自动执行: ./cache-image.sh --update-deployment
↓
继续部署 ✅
```
**优点**:
- AI 自动决策
- 灵活智能
- 无需人工干预
**缺点**:
- 依赖 Claude Code
- 需要明确指令
**适用场景**:
- Claude 辅助开发
- 自动化部署
---
## 测试验证
### 测试场景 1: 新镜像部署
```bash
# 清除本地镜像
docker rmi nginx:alpine
# 测试 OrbStack mirror
docker pull nginx:alpine
# 预期: 从 Harbor 快速拉取
# 测试 kubectl wrapper
kubectl apply -f test-deployment.yaml
# 预期: 自动检测并修复
```
### 测试场景 2: GCR 镜像
```bash
# 测试 cache-image.sh
./cache-image.sh gcr.io/distroless/static:latest
# 验证缓存
docker pull harbor.omniverseai.net:8080/library/static:latest
```
---
## 监控和日志
### 查看 OrbStack Mirror 日志
```bash
# OrbStack 日志
tail -f ~/.orbstack/logs/docker.log | grep -i mirror
```
### 查看 wrapper 日志
```bash
# kubectl wrapper
tail -f /tmp/kubectl-cached.log
# docker wrapper
tail -f /tmp/docker-pull.log
```
### 查看自动修复日志
```bash
tail -f /tmp/image-fix.log
tail -f /tmp/image-watch.log
```
---
## 故障排查
### OrbStack Mirror 不生效
```bash
# 检查配置
cat ~/.orbstack/config/docker.json
# 检查 OrbStack 状态
orb status
# 重启 OrbStack
orb restart
# 验证
docker info | grep -i mirror
```
### Wrapper 未执行
```bash
# 检查 PATH
echo $PATH
# 检查 alias
alias | grep kubectl
# 检查权限
ls -l /usr/local/bin/kubectl-cached
```
---
## 总结
| 场景 | 推荐方案 |
|------|----------|
| **日常使用** | OrbStack Mirror + kubectl wrapper |
| **Claude 开发** | CLAUDE.md + cache-image.sh |
| **生产环境** | 所有方案组合 |
| **快速修复** | cache-image.sh --update-deployment |
**最佳实践**:
1. 配置 OrbStack Mirror(透明加速)
2. 安装 kubectl wrapper(自动修复)
3. 配置 Claude Code(AI 辅助)
4. 保留 cache-image.sh(兜底方案)
**维护建议**:
- 定期同步常用镜像到 Harbor
- 监控 wrapper 日志
- 更新 CLAUDE.md 指令
---
**最后更新**: 2025-12-24
**作者**: Claude AI + Bruno Gao