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

347 lines
11 KiB
Bash
Executable File

#!/bin/bash
# Kubernetes 集群快速修复脚本 v2
# 用途: 清理重复部署、优化集群性能
# 更新时间: 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 集群快速修复菜单 v2"
echo "======================================"
echo "1. 🧹 删除重复部署: 清理 infra namespace 中的 loki/tempo(推荐)"
echo "2. 📦 批量缓存: 缓存所有 P1 高优先级镜像 (40+ 个)"
echo "3. 🗑️ 清理 dev: 删除 dev 命名空间失败的 Deployment"
echo "4. 📊 诊断: 查看所有失败和异常的 Pod"
echo "5. 🔍 检查: 查看镜像拉取错误事件"
echo "6. ⚡ 全自动: 执行所有修复步骤 (1 + 2 + 3)"
echo "7. 📈 部署: 安装 Metrics Server"
echo "0. 退出"
echo "======================================"
}
# P0: 删除重复的 loki/tempo 部署
delete_duplicate_deployments() {
log_info "开始删除 infra namespace 中的重复部署..."
echo ""
log_info "当前情况:"
echo " - ✅ logging namespace: loki-0 (正常运行)"
echo " - ✅ tracing namespace: tempo-0 (正常运行)"
echo " - ❌ infra namespace: loki-0, tempo-0 (重复部署,ImagePullBackOff)"
echo ""
log_warning "将要删除以下资源:"
echo " - statefulset.apps/loki (infra)"
echo " - statefulset.apps/tempo (infra)"
echo " - service/loki (infra)"
echo " - service/tempo (infra)"
echo ""
read -p "确认删除? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "已取消删除操作"
return
fi
# 删除 StatefulSet
log_info "删除 StatefulSet..."
kubectl delete statefulset -n infra loki 2>/dev/null && log_success "已删除 statefulset/loki" || log_warning "loki StatefulSet 不存在或已删除"
kubectl delete statefulset -n infra tempo 2>/dev/null && log_success "已删除 statefulset/tempo" || log_warning "tempo StatefulSet 不存在或已删除"
# 删除 Service
log_info "删除 Service..."
kubectl delete service -n infra loki 2>/dev/null && log_success "已删除 service/loki" || log_warning "loki Service 不存在或已删除"
kubectl delete service -n infra tempo 2>/dev/null && log_success "已删除 service/tempo" || log_warning "tempo Service 不存在或已删除"
echo ""
log_success "重复部署清理完成!"
# 验证正确的实例
echo ""
log_info "验证正确的实例运行状态..."
echo ""
echo "=== logging namespace ==="
kubectl get pods -n logging -l app=loki 2>/dev/null || log_warning "logging/loki 不存在"
echo ""
echo "=== tracing namespace ==="
kubectl get pods -n tracing -l app.kubernetes.io/name=tempo 2>/dev/null || log_warning "tracing/tempo 不存在"
}
# 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 (镜像不存在)"
echo ""
log_info "提示: 这些镜像需要先通过 CI/CD 构建并推送到 Harbor"
echo ""
read -p "确认删除? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
kubectl delete deployment -n dev backend 2>/dev/null && log_success "已删除 dev/backend" || log_warning "backend 不存在"
kubectl delete deployment -n dev frontend 2>/dev/null && log_success "已删除 dev/frontend" || log_warning "frontend 不存在"
kubectl delete deployment -n dev quality-dashboard 2>/dev/null && log_success "已删除 dev/quality-dashboard" || 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)"' 2>/dev/null || \
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)"' 2>/dev/null || \
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 "开始执行全自动修复流程..."
log_warning "将执行以下操作:"
echo " 1. 删除重复的 loki/tempo 部署"
echo " 2. 批量缓存 P1 高优先级镜像"
echo " 3. 清理 dev 命名空间失败的 Deployment"
echo ""
read -p "确认执行全自动修复? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "已取消全自动修复"
return
fi
# 1. 删除重复部署(自动确认)
log_info "步骤 1/3: 删除重复的 loki/tempo 部署..."
kubectl delete statefulset -n infra loki tempo 2>/dev/null || log_warning "StatefulSet 已删除或不存在"
kubectl delete service -n infra loki tempo 2>/dev/null || log_warning "Service 已删除或不存在"
log_success "重复部署清理完成"
echo ""
# 2. 批量缓存镜像
log_info "步骤 2/3: 批量缓存 P1 镜像..."
if [ -f "images-to-cache-p1.txt" ]; then
./cache-image.sh -f images-to-cache-p1.txt
log_success "镜像缓存完成"
else
log_warning "镜像列表文件不存在,跳过此步骤"
fi
echo ""
# 3. 清理 dev 命名空间(自动确认)
log_info "步骤 3/3: 清理 dev 命名空间..."
kubectl delete deployment -n dev backend frontend quality-dashboard 2>/dev/null || log_warning "dev Deployment 已删除或不存在"
log_success "dev 命名空间清理完成"
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 集群快速修复工具 v2"
echo "================================"
echo "更新: 修正了重复部署问题"
echo ""
check_prerequisites
if [ $# -eq 0 ]; then
# 交互式菜单
while true; do
show_menu
read -p "请选择操作 (0-7): " choice
case $choice in
1)
delete_duplicate_deployments
;;
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
delete-duplicates|1)
delete_duplicate_deployments
;;
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 [delete-duplicates|cache-p1|clean-dev|diagnose|check-errors|auto|metrics]"
echo " 或直接运行 $0 进入交互式菜单"
exit 1
;;
esac
fi
}
# 运行主函数
main "$@"