Files

KEDA 自动扩缩容

功能说明

KEDA (Kubernetes Event Driven Autoscaling) 为 K3s 集群提供基于事件驱动的自动扩缩容能力。

核心功能

  • 按需启动/停止服务:空闲时自动缩容到 0节省资源
  • 基于指标自动扩缩容:根据实际负载动态调整副本数
  • 多种触发器支持CPU、内存、Prometheus 指标、数据库连接等
  • 与 Prometheus 集成:利用现有监控数据进行扩缩容决策

部署方式

cd /home/fei/k3s/009-基础设施/007-keda
bash deploy.sh

已配置的服务

1. Navigation 导航服务

  • 最小副本数: 0空闲时完全停止
  • 最大副本数: 10
  • 触发条件:
    • HTTP 请求速率 > 10 req/min
    • CPU 使用率 > 60%
  • 冷却期: 3 分钟

配置文件: scalers/navigation-scaler.yaml

2. Redis 缓存服务

  • 最小副本数: 0空闲时完全停止
  • 最大副本数: 5
  • 触发条件:
    • 有客户端连接
    • CPU 使用率 > 70%
  • 冷却期: 5 分钟

配置文件: scalers/redis-scaler.yaml 状态: 待应用(需要先为 Redis 添加 Prometheus exporter

3. PostgreSQL 数据库

不推荐使用 KEDA 扩展 PostgreSQL

原因:

  • PostgreSQL 是有状态服务,多个副本会导致存储冲突
  • 需要配置主从复制才能安全扩展
  • 建议使用 PostgreSQL Operator 或 PgBouncer + KEDA

详细说明:scalers/postgresql-说明.md

应用 ScaledObject

部署所有 Scaler

# 应用 Navigation Scaler
kubectl apply -f scalers/navigation-scaler.yaml

# 应用 Redis Scaler需要先配置 Redis exporter
kubectl apply -f scalers/redis-scaler.yaml

# ⚠️ PostgreSQL 不推荐使用 KEDA 扩展
# 详见: scalers/postgresql-说明.md

查看 ScaledObject 状态

# 查看所有 ScaledObject
kubectl get scaledobject -A

# 查看详细信息
kubectl describe scaledobject navigation-scaler -n navigation
kubectl describe scaledobject redis-scaler -n redis
kubectl describe scaledobject postgresql-scaler -n postgresql

查看自动创建的 HPA

# KEDA 会自动创建 HorizontalPodAutoscaler
kubectl get hpa -A

支持的触发器类型

1. Prometheus 指标

triggers:
- type: prometheus
  metadata:
    serverAddress: http://kube-prometheus-stack-prometheus.monitoring.svc.cluster.local:9090
    metricName: custom_metric
    query: sum(rate(http_requests_total[1m]))
    threshold: "100"

2. CPU/内存使用率

triggers:
- type: cpu
  metadata:
    type: Utilization
    value: "70"
- type: memory
  metadata:
    type: Utilization
    value: "80"

3. Redis 队列长度

triggers:
- type: redis
  metadata:
    address: redis.redis.svc.cluster.local:6379
    listName: mylist
    listLength: "5"

4. PostgreSQL 查询

triggers:
- type: postgresql
  metadata:
    connectionString: postgresql://user:pass@host:5432/db
    query: "SELECT COUNT(*) FROM tasks WHERE status='pending'"
    targetQueryValue: "10"

5. Cron 定时触发

triggers:
- type: cron
  metadata:
    timezone: Asia/Shanghai
    start: 0 8 * * *      # 每天 8:00 扩容
    end: 0 18 * * *       # 每天 18:00 缩容
    desiredReplicas: "3"

为新服务添加自动扩缩容

步骤 1: 确保服务配置正确

服务的 Deployment 必须配置 resources.requests

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  # 不要设置 replicas由 KEDA 管理
  template:
    spec:
      containers:
      - name: myapp
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi

步骤 2: 创建 ScaledObject

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: myapp-scaler
  namespace: myapp
spec:
  scaleTargetRef:
    name: myapp
  minReplicaCount: 0
  maxReplicaCount: 10
  pollingInterval: 30
  cooldownPeriod: 300
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://kube-prometheus-stack-prometheus.monitoring.svc.cluster.local:9090
      metricName: myapp_requests
      query: sum(rate(http_requests_total{app="myapp"}[1m]))
      threshold: "50"

步骤 3: 应用配置

kubectl apply -f myapp-scaler.yaml

监控和调试

查看 KEDA 日志

# Operator 日志
kubectl logs -n keda -l app.kubernetes.io/name=keda-operator -f

# Metrics Server 日志
kubectl logs -n keda -l app.kubernetes.io/name=keda-metrics-apiserver -f

查看扩缩容事件

# 查看 HPA 事件
kubectl describe hpa -n <namespace>

# 查看 Pod 事件
kubectl get events -n <namespace> --sort-by='.lastTimestamp'

在 Prometheus 中查询 KEDA 指标

访问 https://prometheus.u6.net3w.com查询

# KEDA Scaler 活跃状态
keda_scaler_active

# KEDA Scaler 错误
keda_scaler_errors_total

# 当前指标值
keda_scaler_metrics_value

在 Grafana 中查看 KEDA 仪表板

  1. 访问 https://grafana.u6.net3w.com
  2. 导入 KEDA 官方仪表板 ID: 14691
  3. 查看实时扩缩容状态

测试自动扩缩容

测试 Navigation 服务

测试缩容到 0

# 1. 停止访问导航页面,等待 3 分钟
sleep 180

# 2. 检查副本数
kubectl get deployment navigation -n navigation

# 预期输出READY 0/0

测试从 0 扩容:

# 1. 访问导航页面
curl https://dh.u6.net3w.com

# 2. 监控副本数变化
kubectl get deployment navigation -n navigation -w

# 预期:副本数从 0 变为 1约 10-30 秒)

测试 Redis 服务

测试基于连接数扩容:

# 1. 连接 Redis
kubectl run redis-client --rm -it --image=redis:7-alpine -- redis-cli -h redis.redis.svc.cluster.local

# 2. 在另一个终端监控
kubectl get deployment redis -n redis -w

# 预期:有连接时副本数从 0 变为 1

测试 PostgreSQL 服务

测试基于连接数扩容:

# 1. 创建多个数据库连接
for i in {1..15}; do
  kubectl run pg-client-$i --image=postgres:16-alpine --restart=Never -- \
    psql -h postgresql-service.postgresql.svc.cluster.local -U postgres -c "SELECT pg_sleep(60);" &
done

# 2. 监控副本数
kubectl get statefulset postgresql -n postgresql -w

# 预期:连接数超过 10 时,副本数从 1 增加到 2

故障排查

ScaledObject 未生效

检查 ScaledObject 状态:

kubectl describe scaledobject <name> -n <namespace>

常见问题:

  1. Deployment 设置了固定 replicas

    • 解决:移除 Deployment 中的 replicas 字段
  2. 缺少 resources.requests

    • 解决:为容器添加 resources.requests 配置
  3. Prometheus 查询错误

    • 解决:在 Prometheus UI 中测试查询语句

服务无法缩容到 0

可能原因:

  1. 仍有活跃连接或请求

    • 检查:查看 Prometheus 指标值
  2. cooldownPeriod 未到

    • 检查:等待冷却期结束
  3. minReplicaCount 设置错误

    • 检查:确认 minReplicaCount: 0

扩容速度慢

优化建议:

  1. 减少 pollingInterval

    pollingInterval: 15  # 从 30 秒改为 15 秒
    
  2. 降低 threshold

    threshold: "5"  # 降低触发阈值
    
  3. 使用多个触发器

    triggers:
    - type: prometheus
      # ...
    - type: cpu
      # ...
    

最佳实践

1. 合理设置副本数范围

  • 无状态服务minReplicaCount: 0,节省资源
  • 有状态服务minReplicaCount: 1,保证可用性
  • 关键服务minReplicaCount: 2,保证高可用

2. 选择合适的冷却期

  • 快速响应服务cooldownPeriod: 60-1801-3 分钟)
  • 一般服务cooldownPeriod: 3005 分钟)
  • 数据库服务cooldownPeriod: 600-90010-15 分钟)

3. 监控扩缩容行为

  • 定期查看 Grafana 仪表板
  • 设置告警规则
  • 分析扩缩容历史

4. 测试冷启动时间

  • 测量从 0 扩容到可用的时间
  • 优化镜像大小和启动脚本
  • 考虑使用 minReplicaCount: 1 避免冷启动

配置参考

ScaledObject 完整配置示例

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: example-scaler
  namespace: example
spec:
  scaleTargetRef:
    name: example-deployment
    kind: Deployment                    # 可选Deployment, StatefulSet
    apiVersion: apps/v1                 # 可选
  minReplicaCount: 0                    # 最小副本数
  maxReplicaCount: 10                   # 最大副本数
  pollingInterval: 30                   # 轮询间隔(秒)
  cooldownPeriod: 300                   # 缩容冷却期(秒)
  idleReplicaCount: 0                   # 空闲时的副本数
  fallback:                             # 故障回退配置
    failureThreshold: 3
    replicas: 2
  advanced:                             # 高级配置
    restoreToOriginalReplicaCount: false
    horizontalPodAutoscalerConfig:
      behavior:
        scaleDown:
          stabilizationWindowSeconds: 300
          policies:
          - type: Percent
            value: 50
            periodSeconds: 60
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus:9090
      metricName: custom_metric
      query: sum(rate(metric[1m]))
      threshold: "100"

卸载 KEDA

# 删除所有 ScaledObject
kubectl delete scaledobject --all -A

# 卸载 KEDA
helm uninstall keda -n keda

# 删除命名空间
kubectl delete namespace keda

参考资源


KEDA 让您的 K3s 集群更智能、更高效! 🚀