Files
ljwx-k8s/deploy-auto-fix.sh
2026-02-20 22:50:45 +08:00

358 lines
13 KiB
Bash
Executable File

#!/bin/bash
# 自动镜像修复系统 - 针对当前环境的定制化部署
# 基于现有 OrbStack 配置,保留所有现有设置
set -e
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
RED='\033[0;31m'
CYAN='\033[0;36m'
NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warning() { echo -e "${YELLOW}[!]${NC} $1"; }
log_error() { echo -e "${RED}[✗]${NC} $1"; }
log_step() { echo -e "${CYAN}[STEP]${NC} $1"; }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ORBSTACK_CONFIG="$HOME/.orbstack/config/docker.json"
HARBOR_MIRROR="http://harbor.omniverseai.net:8080"
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_info "自动镜像修复系统 - 定制化部署"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# 显示当前环境
log_step "1/4 环境检查"
echo ""
if [[ -f "$ORBSTACK_CONFIG" ]]; then
log_success "OrbStack 配置文件存在"
# 检查 registry-mirrors
MIRRORS_COUNT=$(jq '.["registry-mirrors"] | length' "$ORBSTACK_CONFIG" 2>/dev/null || echo "0")
if [[ "$MIRRORS_COUNT" -eq 0 ]]; then
log_warning "Registry Mirrors: 未配置 (将添加)"
else
log_success "Registry Mirrors: 已配置 $MIRRORS_COUNT 个"
fi
# 检查 insecure-registries
INSECURE_COUNT=$(jq '.["insecure-registries"] | length' "$ORBSTACK_CONFIG" 2>/dev/null || echo "0")
log_success "Insecure Registries: 已配置 $INSECURE_COUNT 个"
else
log_error "OrbStack 配置文件不存在"
exit 1
fi
# 检查 kubectl alias
if grep -q "kubectl-auto-fix" "$HOME/.zshrc" 2>/dev/null; then
log_success "kubectl wrapper: 已安装"
KUBECTL_INSTALLED=true
else
log_warning "kubectl wrapper: 未安装 (将添加)"
KUBECTL_INSTALLED=false
fi
# 检查 LaunchAgent
if [[ -f "$HOME/Library/LaunchAgents/com.k8s.image-watcher.plist" ]]; then
log_success "后台监控: 已安装"
WATCHER_INSTALLED=true
else
log_warning "后台监控: 未安装 (可选)"
WATCHER_INSTALLED=false
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_step "2/4 配置 Registry Mirror(保留现有配置)"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# 备份现有配置
BACKUP="${ORBSTACK_CONFIG}.backup.$(date +%Y%m%d_%H%M%S)"
cp "$ORBSTACK_CONFIG" "$BACKUP"
log_success "已备份配置到: $BACKUP"
# 使用 jq 安全地添加 registry-mirrors,保留所有其他配置
jq --arg mirror "$HARBOR_MIRROR" \
'.["registry-mirrors"] = [$mirror]' \
"$ORBSTACK_CONFIG" > "${ORBSTACK_CONFIG}.tmp"
mv "${ORBSTACK_CONFIG}.tmp" "$ORBSTACK_CONFIG"
log_success "已添加 Registry Mirror: $HARBOR_MIRROR"
echo ""
log_info "更新后的配置:"
cat "$ORBSTACK_CONFIG" | jq '.'
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_step "3/4 安装 kubectl wrapper"
echo "═══════════════════════════════════════════════════════════════"
echo ""
if [[ "$KUBECTL_INSTALLED" == "true" ]]; then
log_warning "kubectl wrapper 已安装,跳过"
else
# 检查脚本是否存在
if [[ ! -f "$SCRIPT_DIR/kubectl-auto-fix" ]]; then
log_error "kubectl-auto-fix 脚本不存在"
exit 1
fi
# 确保脚本可执行
chmod +x "$SCRIPT_DIR/kubectl-auto-fix"
# 添加 alias 到 .zshrc
cat >> "$HOME/.zshrc" << EOF
# ═══════════════════════════════════════════════════════════════
# kubectl auto-fix wrapper (添加时间: $(date '+%Y-%m-%d %H:%M:%S'))
# 自动检测并修复 ImagePullBackOff 错误
# ═══════════════════════════════════════════════════════════════
alias kubectl="$SCRIPT_DIR/kubectl-auto-fix"
EOF
log_success "已添加 kubectl alias 到 ~/.zshrc"
echo ""
log_info "生效方式:"
echo " 1. 当前终端: source ~/.zshrc"
echo " 2. 新终端会自动生效"
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_step "4/4 配置后台监控服务(可选)"
echo "═══════════════════════════════════════════════════════════════"
echo ""
if [[ "$WATCHER_INSTALLED" == "true" ]]; then
log_warning "后台监控已安装,跳过"
else
read -p "是否安装后台监控服务? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
# 检查脚本是否存在
if [[ ! -f "$SCRIPT_DIR/watch-and-fix-images.sh" ]]; then
log_error "watch-and-fix-images.sh 脚本不存在"
else
chmod +x "$SCRIPT_DIR/watch-and-fix-images.sh"
PLIST_FILE="$HOME/Library/LaunchAgents/com.k8s.image-watcher.plist"
cat > "$PLIST_FILE" << 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>$SCRIPT_DIR/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>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin</string>
</dict>
</dict>
</plist>
EOF
log_success "已创建 LaunchAgent: $PLIST_FILE"
read -p "是否立即启动后台监控? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
launchctl load "$PLIST_FILE" 2>/dev/null || true
log_success "后台监控已启动"
echo ""
log_info "查看日志: tail -f /tmp/image-watch.log"
else
log_info "稍后启动: launchctl load $PLIST_FILE"
fi
fi
else
log_info "跳过后台监控安装"
fi
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_success "部署完成"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# 显示摘要
echo "📋 部署摘要:"
echo ""
echo " ✅ Layer 1: OrbStack Registry Mirror"
echo " - Harbor: $HARBOR_MIRROR"
echo " - 配置: $ORBSTACK_CONFIG"
echo " - 需重启: orb restart"
echo ""
if [[ "$KUBECTL_INSTALLED" == "false" ]]; then
echo " ✅ Layer 2: kubectl wrapper (新安装)"
echo " - 脚本: $SCRIPT_DIR/kubectl-auto-fix"
echo " - 生效: source ~/.zshrc"
echo ""
fi
if [[ -f "$HOME/Library/LaunchAgents/com.k8s.image-watcher.plist" ]]; then
echo " ✅ Layer 3: 后台监控"
echo " - 日志: /tmp/image-watch.log"
echo " - 间隔: 30秒"
echo ""
fi
echo " ✅ Layer 4: Claude Code 集成"
echo " - 配置: /Users/brunogao/work/codes/tools/macos/CLAUDE.md"
echo " - 自动: Claude 遇到 ImagePull 错误时自动执行"
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_warning "下一步操作"
echo "═══════════════════════════════════════════════════════════════"
echo ""
echo "1️⃣ 重启 OrbStack (使 Registry Mirror 生效)"
echo " orb restart"
echo ""
echo "2️⃣ 刷新当前终端 (使 kubectl wrapper 生效)"
echo " source ~/.zshrc"
echo ""
echo "3️⃣ 测试镜像拉取 (验证 Registry Mirror)"
echo " docker pull nginx:alpine"
echo " docker pull redis:7-alpine"
echo ""
echo "4️⃣ 测试 kubectl wrapper (验证自动修复)"
echo " kubectl apply -f test-deployment.yaml"
echo ""
echo "5️⃣ 验证工作流程"
echo " kubectl get pods --all-namespaces | grep -i imagepull"
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_info "工作原理"
echo "═══════════════════════════════════════════════════════════════"
echo ""
echo "当拉取镜像时:"
echo ""
echo " 1. Docker/K8s 请求 docker.io/nginx:alpine"
echo " 2. OrbStack 自动转发到 $HARBOR_MIRROR"
echo " 3. 如果本地 Harbor 有缓存 → 直接返回 ✅"
echo " 4. 如果本地没有 → Harbor 从上游拉取并缓存"
echo " 5. 后续请求直接使用本地缓存 🚀"
echo ""
echo "如果仍然失败:"
echo ""
echo " 6. kubectl wrapper 检测到 ImagePullBackOff"
echo " 7. 自动调用 cache-image.sh 从 EU Harbor 拉取"
echo " 8. 推送到本地 Harbor"
echo " 9. 更新 Deployment 使用本地镜像"
echo " 10. Pod 自动重启并成功拉取 ✅"
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_info "故障排查"
echo "═══════════════════════════════════════════════════════════════"
echo ""
echo "• Registry Mirror 不工作:"
echo " docker info | grep -A 5 'Registry Mirrors'"
echo ""
echo "• kubectl wrapper 日志:"
echo " tail -f /tmp/kubectl-auto-fix.log"
echo ""
echo "• 后台监控日志:"
echo " tail -f /tmp/image-watch.log"
echo ""
echo "• 停止后台监控:"
echo " launchctl unload ~/Library/LaunchAgents/com.k8s.image-watcher.plist"
echo ""
echo "• 手动缓存镜像:"
echo " cd $SCRIPT_DIR"
echo " ./cache-image.sh nginx:alpine"
echo " ./cache-image.sh --update-deployment namespace/deployment"
echo ""
echo "═══════════════════════════════════════════════════════════════"
log_success "🎉 部署成功!现在你的系统已具备自动镜像修复能力"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# 询问是否立即重启 OrbStack
read -p "是否立即重启 OrbStack? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
log_info "正在重启 OrbStack..."
# 退出 OrbStack 应用
osascript -e 'quit app "OrbStack"' 2>/dev/null || pkill -9 OrbStack
log_info "等待 OrbStack 完全退出..."
sleep 3
# 重新启动 OrbStack
open -a OrbStack
log_success "OrbStack 已重启"
echo ""
log_info "等待 OrbStack 启动(约 10 秒)..."
# 等待 Docker 守护进程就绪
for i in {1..20}; do
if docker info &>/dev/null; then
break
fi
sleep 1
done
sleep 3
# 验证
log_info "验证 Registry Mirror 配置..."
if docker info 2>/dev/null | grep -q "Registry Mirrors"; then
log_success "Registry Mirror 配置已生效"
echo ""
docker info 2>/dev/null | grep -A 3 "Registry Mirrors"
else
log_warning "未检测到 Registry Mirror,可能需要等待更长时间"
log_info "手动检查: docker info | grep -A 3 'Registry Mirrors'"
fi
echo ""
log_info "现在可以测试镜像拉取:"
echo " docker pull nginx:alpine"
else
echo ""
log_warning "请稍后手动重启 OrbStack:"
echo ""
echo " 方式 1: 使用命令行"
echo " osascript -e 'quit app \"OrbStack\"'"
echo " sleep 3"
echo " open -a OrbStack"
echo ""
echo " 方式 2: 使用 GUI"
echo " OrbStack 菜单栏 → Quit OrbStack"
echo " 然后重新打开 OrbStack 应用"
fi
echo ""