# KEDA 自动扩缩容 ## 功能说明 KEDA (Kubernetes Event Driven Autoscaling) 为 K3s 集群提供基于事件驱动的自动扩缩容能力。 ### 核心功能 - **按需启动/停止服务**:空闲时自动缩容到 0,节省资源 - **基于指标自动扩缩容**:根据实际负载动态调整副本数 - **多种触发器支持**:CPU、内存、Prometheus 指标、数据库连接等 - **与 Prometheus 集成**:利用现有监控数据进行扩缩容决策 ## 部署方式 ```bash 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 ```bash # 应用 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 状态 ```bash # 查看所有 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 ```bash # KEDA 会自动创建 HorizontalPodAutoscaler kubectl get hpa -A ``` ## 支持的触发器类型 ### 1. Prometheus 指标 ```yaml 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/内存使用率 ```yaml triggers: - type: cpu metadata: type: Utilization value: "70" - type: memory metadata: type: Utilization value: "80" ``` ### 3. Redis 队列长度 ```yaml triggers: - type: redis metadata: address: redis.redis.svc.cluster.local:6379 listName: mylist listLength: "5" ``` ### 4. PostgreSQL 查询 ```yaml triggers: - type: postgresql metadata: connectionString: postgresql://user:pass@host:5432/db query: "SELECT COUNT(*) FROM tasks WHERE status='pending'" targetQueryValue: "10" ``` ### 5. Cron 定时触发 ```yaml triggers: - type: cron metadata: timezone: Asia/Shanghai start: 0 8 * * * # 每天 8:00 扩容 end: 0 18 * * * # 每天 18:00 缩容 desiredReplicas: "3" ``` ## 为新服务添加自动扩缩容 ### 步骤 1: 确保服务配置正确 服务的 Deployment 必须配置 `resources.requests`: ```yaml 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 ```yaml 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: 应用配置 ```bash kubectl apply -f myapp-scaler.yaml ``` ## 监控和调试 ### 查看 KEDA 日志 ```bash # 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 ``` ### 查看扩缩容事件 ```bash # 查看 HPA 事件 kubectl describe hpa -n # 查看 Pod 事件 kubectl get events -n --sort-by='.lastTimestamp' ``` ### 在 Prometheus 中查询 KEDA 指标 访问 https://prometheus.u6.net3w.com,查询: ```promql # 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:** ```bash # 1. 停止访问导航页面,等待 3 分钟 sleep 180 # 2. 检查副本数 kubectl get deployment navigation -n navigation # 预期输出:READY 0/0 ``` **测试从 0 扩容:** ```bash # 1. 访问导航页面 curl https://dh.u6.net3w.com # 2. 监控副本数变化 kubectl get deployment navigation -n navigation -w # 预期:副本数从 0 变为 1(约 10-30 秒) ``` ### 测试 Redis 服务 **测试基于连接数扩容:** ```bash # 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 服务 **测试基于连接数扩容:** ```bash # 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 状态:** ```bash kubectl describe scaledobject -n ``` **常见问题:** 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** ```yaml pollingInterval: 15 # 从 30 秒改为 15 秒 ``` 2. **降低 threshold** ```yaml threshold: "5" # 降低触发阈值 ``` 3. **使用多个触发器** ```yaml triggers: - type: prometheus # ... - type: cpu # ... ``` ## 最佳实践 ### 1. 合理设置副本数范围 - **无状态服务**:`minReplicaCount: 0`,节省资源 - **有状态服务**:`minReplicaCount: 1`,保证可用性 - **关键服务**:`minReplicaCount: 2`,保证高可用 ### 2. 选择合适的冷却期 - **快速响应服务**:`cooldownPeriod: 60-180`(1-3 分钟) - **一般服务**:`cooldownPeriod: 300`(5 分钟) - **数据库服务**:`cooldownPeriod: 600-900`(10-15 分钟) ### 3. 监控扩缩容行为 - 定期查看 Grafana 仪表板 - 设置告警规则 - 分析扩缩容历史 ### 4. 测试冷启动时间 - 测量从 0 扩容到可用的时间 - 优化镜像大小和启动脚本 - 考虑使用 `minReplicaCount: 1` 避免冷启动 ## 配置参考 ### ScaledObject 完整配置示例 ```yaml 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 ```bash # 删除所有 ScaledObject kubectl delete scaledobject --all -A # 卸载 KEDA helm uninstall keda -n keda # 删除命名空间 kubectl delete namespace keda ``` ## 参考资源 - KEDA 官方文档: https://keda.sh/docs/ - KEDA Scalers: https://keda.sh/docs/scalers/ - KEDA GitHub: https://github.com/kedacore/keda - Grafana 仪表板: https://grafana.com/grafana/dashboards/14691 --- **KEDA 让您的 K3s 集群更智能、更高效!** 🚀