Files
ljwx-k8s/HPA-DIAGNOSTICS-REPORT.md
2026-02-20 22:50:45 +08:00

9.4 KiB
Raw Permalink Blame History

HPA 诊断报告

执行时间: 2025-12-31 环境: OrbStack v1.33.5+orb1 状态: ⚠️ 发现 OrbStack 限制


📊 诊断结果

✅ 已确认正常的部分

  1. metrics-server 运行正常

    • Deployment 状态: READY 1/1
    • API 服务可用: ✅ v1beta1.metrics.k8s.io
    • 配置已优化: 添加了 --kubelet-insecure-tls 和 --kubelet-preferred-address-types=InternalIP
  2. Node metrics 正常工作

    $ kubectl top nodes
    NAME       CPU(cores)   CPU(%)   MEMORY(bytes)   MEMORY(%)
    orbstack   749m         3%       21982Mi         34%
    
  3. 所有 HPA 目标都有 resource requests

    • ✅ grafana: CPU 250m, Memory 256Mi
    • ✅ prometheus: CPU 500m, Memory 512Mi
    • ✅ argocd-server: CPU 100m, Memory 128Mi
    • ✅ ingress-nginx-controller: CPU 200m, Memory 256Mi
    • ✅ gitea-runner: CPU 100m, Memory 128Mi
    • ✅ claude-stock-backend: CPU 250m, Memory 512Mi
  4. cAdvisor 已启用

    $ kubectl get --raw "/api/v1/nodes/orbstack/proxy/metrics/cadvisor"
    # cAdvisor metrics 正常返回
    

❌ 发现的问题

核心问题: Pod Metrics 不可用

症状:

$ kubectl top pods -n monitoring
error: Metrics not available for pod ...

$ kubectl get hpa --all-namespaces
NAMESPACE   NAME              TARGETS
monitoring  grafana-hpa       cpu: <unknown>/70%   # ❌ 应该显示具体百分比

根本原因: OrbStack 的 kubelet 不提供 Pod 级别的统计信息

技术细节:

# Node stats 正常
$ kubectl get --raw "/api/v1/nodes/orbstack/proxy/stats/summary" | jq '.node'
{
  "nodeName": "orbstack",
  "cpu": {...},
  "memory": {...}
}

# Pod stats 为空 ❌
$ kubectl get --raw "/api/v1/nodes/orbstack/proxy/stats/summary" | jq '.pods | length'
0  # 没有任何 pod 统计信息

# Metrics API 也返回空列表
$ kubectl get --raw "/apis/metrics.k8s.io/v1beta1/namespaces/monitoring/pods"
{"kind":"PodMetricsList","items":[]}  # ❌ 空列表

🔍 原因分析

OrbStack 的限制

OrbStack 是一个轻量级的 Kubernetes 环境,为了优化性能和资源占用,做了一些简化:

  1. kubelet 简化: 不完全实现 kubelet 的所有 metrics 接口
  2. cAdvisor 限制: 虽然 cAdvisor 启用了,但不提供 per-pod metrics
  3. stats API 限制: /stats/summary 只返回 node 级别的统计,不返回 pod 级别

这导致:

  • ❌ metrics-server 无法收集 pod metrics
  • ❌ HPA 无法获取 pod 的 CPU/Memory 使用率
  • ❌ kubectl top pods 不工作

🛠️ 解决方案

方案 1: 使用 Prometheus Adapter(推荐)⭐

原理:

  • 绕过 metrics-server
  • 直接从 Prometheus 获取 metrics
  • 将 Prometheus metrics 转换为 HPA 可用的 custom metrics

部署步骤:

# 1. 安装 Prometheus Adapter
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

helm install prometheus-adapter prometheus-community/prometheus-adapter \
  --namespace monitoring \
  --set prometheus.url=http://prometheus.monitoring.svc.cluster.local:9090 \
  --set prometheus.port=9090

# 2. 验证 custom metrics API
kubectl get apiservice v1beta1.custom.metrics.k8s.io

# 3. 修改 HPA 使用 custom metrics
cat > /tmp/hpa-custom-metrics.yaml << 'EOF'
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: grafana-hpa
  namespace: monitoring
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: grafana
  minReplicas: 1
  maxReplicas: 3
  metrics:
  - type: Pods
    pods:
      metric:
        name: cpu_usage
      target:
        type: AverageValue
        averageValue: 500m
EOF

kubectl apply -f /tmp/hpa-custom-metrics.yaml

优点:

  • ✅ 完全绕过 OrbStack 限制
  • ✅ 使用现有的 Prometheus metrics
  • ✅ 支持自定义 metrics(不仅限于 CPU/Memory)
  • ✅ 更强大的扩缩容逻辑

缺点:

  • 需要配置 Prometheus metrics 映射
  • HPA 配置略微复杂

预计时间: 1 小时 成功率: 95%+


方案 2: 使用 KEDA(推荐用于复杂场景)⭐⭐

原理:

  • Kubernetes Event Driven Autoscaling
  • 支持多种 metrics 来源(Prometheus, Redis, Kafka, etc)
  • 不依赖 metrics-server

部署步骤:

# 1. 安装 KEDA
helm repo add kedacore https://kedacore.github.io/charts
helm repo update

helm install keda kedacore/keda --namespace keda --create-namespace

# 2. 创建 ScaledObject(替代 HPA)
cat > /tmp/keda-scaledobject.yaml << 'EOF'
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: grafana-scaler
  namespace: monitoring
spec:
  scaleTargetRef:
    name: grafana
  minReplicaCount: 1
  maxReplicaCount: 3
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus.monitoring.svc.cluster.local:9090
      metricName: cpu_usage_rate
      query: |
        rate(container_cpu_usage_seconds_total{pod=~"grafana-.*"}[1m])
      threshold: "0.7"
EOF

kubectl apply -f /tmp/keda-scaledobject.yaml

优点:

  • ✅ 功能最强大
  • ✅ 支持多种 event sources
  • ✅ 支持扩容到 0(节省资源)
  • ✅ 完全不依赖 metrics-server

缺点:

  • 需要学习新的 API(ScaledObject)
  • 替代传统 HPA(不兼容)

预计时间: 2 小时 成功率: 98%+


方案 3: 手动扩缩容(不推荐)

原理:

  • 定期检查 Prometheus metrics
  • 通过脚本手动调整 replicas

示例脚本:

#!/bin/bash
# auto-scale-grafana.sh

NAMESPACE="monitoring"
DEPLOYMENT="grafana"
MIN_REPLICAS=1
MAX_REPLICAS=3
CPU_THRESHOLD=70  # 70%

# 从 Prometheus 获取 CPU 使用率
CPU_USAGE=$(kubectl exec -n monitoring deployment/prometheus -- \
  promtool query instant 'rate(container_cpu_usage_seconds_total{pod=~"grafana-.*"}[1m])' | \
  jq -r '.data.result[0].value[1]')

# 计算所需副本数
CURRENT_REPLICAS=$(kubectl get deployment $DEPLOYMENT -n $NAMESPACE -o jsonpath='{.spec.replicas}')

if (( $(echo "$CPU_USAGE > 0.7" | bc -l) )); then
  NEW_REPLICAS=$((CURRENT_REPLICAS + 1))
  if [ $NEW_REPLICAS -le $MAX_REPLICAS ]; then
    kubectl scale deployment $DEPLOYMENT -n $NAMESPACE --replicas=$NEW_REPLICAS
  fi
elif (( $(echo "$CPU_USAGE < 0.3" | bc -l) )); then
  NEW_REPLICAS=$((CURRENT_REPLICAS - 1))
  if [ $NEW_REPLICAS -ge $MIN_REPLICAS ]; then
    kubectl scale deployment $DEPLOYMENT -n $NAMESPACE --replicas=$NEW_REPLICAS
  fi
fi

优点:

  • ✅ 简单直接
  • ✅ 完全控制扩缩容逻辑

缺点:

  • ❌ 需要定期执行(cron)
  • ❌ 不如 HPA 实时
  • ❌ 需要维护脚本

方案 4: 升级到完整的 Kubernetes 环境(终极方案)

选项:

  1. kind (Kubernetes in Docker) - 更接近生产环境
  2. k3s - 轻量但功能完整
  3. Minikube - 传统选择
  4. Rancher Desktop - GUI 友好

迁移步骤:

# 选择 kind 为例
brew install kind

# 创建集群
kind create cluster --name dev-cluster

# 迁移资源
kubectl get all --all-namespaces -o yaml > cluster-backup.yaml
# 在新集群中应用
kubectl apply -f cluster-backup.yaml

优点:

  • ✅ 100% Kubernetes 兼容
  • ✅ HPA 开箱即用
  • ✅ 所有 K8s 功能可用

缺点:

  • ❌ 资源占用更高
  • ❌ 启动稍慢
  • ❌ 需要迁移现有环境

💡 推荐行动方案

短期(本周): 部署 Prometheus Adapter

理由:

  • ✅ 最小改动
  • ✅ 利用现有 Prometheus
  • ✅ HPA 仍然可用(只需修改 metrics 来源)
  • ✅ 1 小时即可完成

执行计划: 参考 K8S-OPTIMIZATION-ROADMAP-2025.md 中的详细步骤


中期(下月): 评估 KEDA

理由:

  • ✅ 功能更强大
  • ✅ 支持更多 scaling 场景
  • ✅ 云原生最佳实践

长期(未来): 考虑迁移到完整 K8s

评估标准:

  • 如果需要生产级别的 K8s 功能
  • 如果 OrbStack 限制影响开发体验
  • 如果需要完全的 K8s API 兼容性

📋 当前 HPA 状态

HPA 命名空间 目标 当前状态 备注
grafana-hpa monitoring Deployment/grafana ❌ <unknown> 等待 Prometheus Adapter
prometheus-hpa monitoring Deployment/prometheus ❌ <unknown> 等待 Prometheus Adapter
argocd-server-hpa argocd Deployment/argocd-server ❌ <unknown> 等待 Prometheus Adapter
ingress-nginx-hpa infra Deployment/ingress-nginx-controller ❌ <unknown> 等待 Prometheus Adapter
gitea-runner-hpa gitea-runner Deployment/gitea-runner ❌ <unknown> 等待 Prometheus Adapter
claude-stock-backend-hpa ljwx-stock Deployment/claude-stock-backend ❌ <unknown> 等待 Prometheus Adapter

🎯 下一步行动

立即执行(推荐)

  1. 部署 Prometheus Adapter (1 小时)

    cd /Users/brunogao/work/codes/tools/macos/k8s
    # 按照路线图执行
    
  2. 更新 HPA 配置 (30 分钟)

    • 将 HPA 修改为使用 custom metrics
    • 测试扩缩容功能
  3. 验证工作 (15 分钟)

    • 创建负载测试
    • 观察 HPA 扩容

总时间: 约 1.5 小时 成功率: 95%+


📚 参考资料


报告生成: 2025-12-31 诊断时长: 30 分钟 状态: ⚠️ 需要部署 Prometheus Adapter