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

14 KiB
Raw Permalink Blame History

自动镜像缓存解决方案

方案对比

方案 透明度 自动化 复杂度 推荐度
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

配置内容

{
  "registry-mirrors": [
    "http://harbor.omniverseai.net:8080"
  ],
  "insecure-registries": [
    "harbor.omniverseai.net:8080"
  ]
}

自动配置脚本

#!/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"

验证

# 检查配置
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

#!/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

使用方式

# 方式 1: alias
alias docker='docker-cached'

# 方式 2: PATH 优先级
export PATH="/usr/local/bin:$PATH"

# 使用
docker pull nginx:alpine  # 自动缓存

方案 3: kubectl Wrapper(智能检测)

创建 Wrapper

#!/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

使用方式

# alias
alias kubectl='kubectl-cached'

# 部署
kubectl apply -f deployment.yaml  # 自动检测并修复

方案 4: Claude Code CLAUDE.md 集成

在项目根目录添加配置

位置: /Users/brunogao/work/codes/tools/macos/CLAUDE.md

内容:

# 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>

手动缓存

# 缓存单个镜像
./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

后台运行

# 启动监控
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

./setup-orbstack-registry-mirror.sh
orb restart

Step 2: 安装 kubectl wrapper

sudo cp kubectl-cached /usr/local/bin/
echo 'alias kubectl="kubectl-cached"' >> ~/.zshrc
source ~/.zshrc

Step 3: 配置 Claude Code

# 在项目根目录 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: 新镜像部署

# 清除本地镜像
docker rmi nginx:alpine

# 测试 OrbStack mirror
docker pull nginx:alpine
# 预期: 从 Harbor 快速拉取

# 测试 kubectl wrapper
kubectl apply -f test-deployment.yaml
# 预期: 自动检测并修复

测试场景 2: GCR 镜像

# 测试 cache-image.sh
./cache-image.sh gcr.io/distroless/static:latest

# 验证缓存
docker pull harbor.omniverseai.net:8080/library/static:latest

监控和日志

查看 OrbStack Mirror 日志

# OrbStack 日志
tail -f ~/.orbstack/logs/docker.log | grep -i mirror

查看 wrapper 日志

# kubectl wrapper
tail -f /tmp/kubectl-cached.log

# docker wrapper
tail -f /tmp/docker-pull.log

查看自动修复日志

tail -f /tmp/image-fix.log
tail -f /tmp/image-watch.log

故障排查

OrbStack Mirror 不生效

# 检查配置
cat ~/.orbstack/config/docker.json

# 检查 OrbStack 状态
orb status

# 重启 OrbStack
orb restart

# 验证
docker info | grep -i mirror

Wrapper 未执行

# 检查 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