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

302 lines
9.0 KiB
Bash
Executable File

#!/bin/bash
# Kubernetes 集群快速修复脚本
# 用途: 修复镜像拉取失败和优化集群性能
# 生成时间: 2026-01-04
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查必要工具
check_prerequisites() {
log_info "检查必要工具..."
if ! command -v kubectl &> /dev/null; then
log_error "kubectl 未安装,请先安装 kubectl"
exit 1
fi
if ! command -v docker &> /dev/null; then
log_error "docker 未安装,请先安装 Docker"
exit 1
fi
if [ ! -f "./cache-image.sh" ]; then
log_error "cache-image.sh 未找到,请确保在正确的目录下运行此脚本"
exit 1
fi
log_success "工具检查通过"
}
# 显示菜单
show_menu() {
echo ""
echo "======================================"
echo " Kubernetes 集群快速修复菜单"
echo "======================================"
echo "1. 🔥 紧急修复: 修复 Grafana 组件镜像拉取失败 (loki, tempo)"
echo "2. 📦 批量缓存: 缓存所有 P1 高优先级镜像 (40+ 个)"
echo "3. 🧹 清理: 删除 dev 命名空间失败的 Deployment"
echo "4. 📊 诊断: 查看所有失败和异常的 Pod"
echo "5. 🔍 检查: 查看镜像拉取错误事件"
echo "6. ⚡ 全自动: 执行所有修复步骤 (1 + 2)"
echo "7. 📈 部署: 安装 Metrics Server"
echo "0. 退出"
echo "======================================"
}
# P0: 修复 Grafana 组件
fix_grafana_images() {
log_info "开始修复 Grafana 组件镜像拉取问题..."
# 缓存 Loki 镜像
log_info "缓存 Loki 镜像..."
./cache-image.sh grafana/loki:latest
./cache-image.sh grafana/loki:2.6.1
# 缓存 Tempo 镜像
log_info "缓存 Tempo 镜像..."
./cache-image.sh grafana/tempo:latest
./cache-image.sh grafana/tempo:2.9.0
# 缓存 Promtail 镜像
log_info "缓存 Promtail 镜像..."
./cache-image.sh grafana/promtail:3.5.1
# 重启 Pod
log_info "重启 Loki 和 Tempo Pod..."
kubectl delete pod -n infra loki-0 2>/dev/null || log_warning "infra/loki-0 不存在或已删除"
kubectl delete pod -n infra tempo-0 2>/dev/null || log_warning "infra/tempo-0 不存在或已删除"
kubectl delete pod -n logging loki-0 2>/dev/null || log_warning "logging/loki-0 不存在或已删除"
kubectl delete pod -n tracing tempo-0 2>/dev/null || log_warning "tracing/tempo-0 不存在或已删除"
log_success "Grafana 组件镜像修复完成!"
log_info "等待 30 秒让 Pod 重新启动..."
sleep 30
# 检查状态
log_info "检查 Pod 状态..."
kubectl get pods -n infra -l app=loki 2>/dev/null || true
kubectl get pods -n infra -l app=tempo 2>/dev/null || true
kubectl get pods -n logging -l app=loki 2>/dev/null || true
kubectl get pods -n tracing -l app.kubernetes.io/name=tempo 2>/dev/null || true
}
# P1: 批量缓存镜像
cache_p1_images() {
log_info "开始批量缓存 P1 高优先级镜像..."
if [ ! -f "images-to-cache-p1.txt" ]; then
log_error "镜像列表文件 images-to-cache-p1.txt 未找到"
exit 1
fi
log_info "镜像列表文件: images-to-cache-p1.txt"
log_warning "这将花费 5-10 分钟,请耐心等待..."
./cache-image.sh -f images-to-cache-p1.txt
log_success "P1 镜像批量缓存完成!"
}
# 清理 dev 命名空间
clean_dev_namespace() {
log_info "清理 dev 命名空间失败的 Deployment..."
log_warning "将要删除以下 Deployment:"
echo " - dev/backend"
echo " - dev/frontend"
echo " - dev/quality-dashboard"
read -p "确认删除? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
kubectl delete deployment -n dev backend 2>/dev/null || log_warning "backend 不存在"
kubectl delete deployment -n dev frontend 2>/dev/null || log_warning "frontend 不存在"
kubectl delete deployment -n dev quality-dashboard 2>/dev/null || log_warning "quality-dashboard 不存在"
log_success "dev 命名空间清理完成"
else
log_info "已取消删除操作"
fi
}
# 诊断失败的 Pod
diagnose_failed_pods() {
log_info "诊断所有失败和异常的 Pod..."
echo ""
echo "=== ImagePullBackOff / ErrImagePull ==="
kubectl get pods --all-namespaces --field-selector=status.phase=Pending -o wide 2>/dev/null || log_warning "没有 Pending 状态的 Pod"
echo ""
echo "=== CrashLoopBackOff ==="
kubectl get pods --all-namespaces -o json 2>/dev/null | \
jq -r '.items[] | select(.status.containerStatuses[]? | .state.waiting?.reason == "CrashLoopBackOff") | "\(.metadata.namespace)\t\(.metadata.name)\t\(.status.containerStatuses[0].restartCount)"' || \
log_warning "jq 未安装或没有 CrashLoopBackOff Pod"
echo ""
echo "=== 高重启次数的 Pod (>100) ==="
kubectl get pods --all-namespaces -o json 2>/dev/null | \
jq -r '.items[] | select(.status.containerStatuses[]? | .restartCount > 100) | "\(.metadata.namespace)\t\(.metadata.name)\t\(.status.containerStatuses[0].restartCount)"' || \
log_warning "jq 未安装或没有高重启次数的 Pod"
}
# 检查镜像拉取错误
check_image_pull_errors() {
log_info "检查最近的镜像拉取错误事件..."
kubectl get events --all-namespaces --field-selector type=Warning 2>/dev/null | grep -i "image\|pull" | head -20 || \
log_success "没有发现镜像拉取错误事件"
}
# 全自动修复
auto_fix_all() {
log_info "开始执行全自动修复流程..."
# 1. 修复 Grafana 组件
fix_grafana_images
echo ""
# 2. 批量缓存镜像
cache_p1_images
echo ""
log_success "全自动修复完成!"
# 最终诊断
echo ""
log_info "执行最终诊断..."
diagnose_failed_pods
}
# 部署 Metrics Server
deploy_metrics_server() {
log_info "部署 Metrics Server..."
log_info "下载 Metrics Server manifests..."
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
log_info "配置 OrbStack 兼容性 (--kubelet-insecure-tls)..."
kubectl patch deployment metrics-server -n kube-system --type='json' \
-p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"}]' 2>/dev/null || \
log_warning "Patch 失败,可能 Metrics Server 已配置"
log_info "等待 Metrics Server 启动..."
sleep 20
log_info "验证 Metrics Server..."
kubectl top nodes || log_warning "Metrics Server 可能还未就绪,请稍后再试 kubectl top nodes"
log_success "Metrics Server 部署完成"
}
# 主函数
main() {
echo "Kubernetes 集群快速修复工具"
echo "================================"
check_prerequisites
if [ $# -eq 0 ]; then
# 交互式菜单
while true; do
show_menu
read -p "请选择操作 (0-7): " choice
case $choice in
1)
fix_grafana_images
;;
2)
cache_p1_images
;;
3)
clean_dev_namespace
;;
4)
diagnose_failed_pods
;;
5)
check_image_pull_errors
;;
6)
auto_fix_all
;;
7)
deploy_metrics_server
;;
0)
log_info "退出程序"
exit 0
;;
*)
log_error "无效选择,请重新输入"
;;
esac
echo ""
read -p "按回车键继续..."
done
else
# 命令行参数模式
case "$1" in
fix-grafana|1)
fix_grafana_images
;;
cache-p1|2)
cache_p1_images
;;
clean-dev|3)
clean_dev_namespace
;;
diagnose|4)
diagnose_failed_pods
;;
check-errors|5)
check_image_pull_errors
;;
auto|6)
auto_fix_all
;;
metrics|7)
deploy_metrics_server
;;
*)
echo "用法: $0 [fix-grafana|cache-p1|clean-dev|diagnose|check-errors|auto|metrics]"
echo " 或直接运行 $0 进入交互式菜单"
exit 1
;;
esac
fi
}
# 运行主函数
main "$@"