Files
k3s/009-基础设施/007-keda/scalers/KEDA-自动缩容到0-配置指南.md
2026-02-05 00:11:05 +08:00

381 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# KEDA HTTP Add-on 自动缩容到 0 配置指南
本指南说明如何使用 KEDA HTTP Add-on 实现应用在无流量时自动缩容到 0有访问时自动启动。
## 前提条件
1. K3s 集群已安装
2. KEDA 已安装
3. KEDA HTTP Add-on 已安装
4. Traefik 作为 Ingress Controller
### 检查 KEDA HTTP Add-on 是否已安装
```bash
kubectl get pods -n keda | grep http
```
应该看到类似输出:
```
keda-add-ons-http-controller-manager-xxx 1/1 Running
keda-add-ons-http-external-scaler-xxx 1/1 Running
keda-add-ons-http-interceptor-xxx 1/1 Running
```
### 如果未安装,执行以下命令安装
```bash
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
helm install http-add-on kedacore/keda-add-ons-http --namespace keda
```
## 配置步骤
### 1. 准备应用的基础资源
确保你的应用已经有以下资源:
- Deployment
- Service
- Namespace
示例:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: myapp
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: your-image:tag
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: myapp
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 80
```
### 2. 创建 HTTPScaledObject
这是实现自动缩容到 0 的核心配置。
```yaml
apiVersion: http.keda.sh/v1alpha1
kind: HTTPScaledObject
metadata:
name: myapp-http-scaler
namespace: myapp # 必须与应用在同一个 namespace
spec:
hosts:
- myapp.example.com # 你的域名
pathPrefixes:
- / # 匹配的路径前缀
scaleTargetRef:
name: myapp # Deployment 名称
kind: Deployment
apiVersion: apps/v1
service: myapp # Service 名称
port: 80 # Service 端口
replicas:
min: 0 # 空闲时缩容到 0
max: 10 # 最多扩容到 10 个副本
scalingMetric:
requestRate:
granularity: 1s
targetValue: 100 # 每秒 100 个请求时扩容
window: 1m
scaledownPeriod: 300 # 5 分钟300秒无流量后缩容到 0
```
**重要参数说明:**
- `hosts`: 你的应用域名
- `scaleTargetRef.name`: 你的 Deployment 名称
- `scaleTargetRef.service`: 你的 Service 名称
- `scaleTargetRef.port`: 你的 Service 端口
- `replicas.min: 0`: 允许缩容到 0
- `scaledownPeriod`: 无流量后多久缩容(秒)
### 3. 创建 Traefik IngressRoute
**重要IngressRoute 必须在 keda namespace 中创建**,因为它需要引用 keda namespace 的拦截器服务。
```yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: myapp-ingress
namespace: keda # 注意:必须在 keda namespace
spec:
entryPoints:
- web # HTTP 入口
# - websecure # 如果需要 HTTPS添加这个
routes:
- match: Host(`myapp.example.com`) # 你的域名
kind: Rule
services:
- name: keda-add-ons-http-interceptor-proxy
port: 8080
```
**如果需要 HTTPS添加 TLS 配置:**
```yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: myapp-ingress
namespace: keda
spec:
entryPoints:
- websecure
routes:
- match: Host(`myapp.example.com`)
kind: Rule
services:
- name: keda-add-ons-http-interceptor-proxy
port: 8080
tls:
certResolver: letsencrypt # 你的证书解析器
```
### 4. 完整配置文件模板
将以下内容保存为 `myapp-keda-scaler.yaml`,并根据你的应用修改相应的值:
```yaml
---
# HTTPScaledObject - 实现自动缩容到 0
apiVersion: http.keda.sh/v1alpha1
kind: HTTPScaledObject
metadata:
name: myapp-http-scaler
namespace: myapp # 改为你的 namespace
spec:
hosts:
- myapp.example.com # 改为你的域名
pathPrefixes:
- /
scaleTargetRef:
name: myapp # 改为你的 Deployment 名称
kind: Deployment
apiVersion: apps/v1
service: myapp # 改为你的 Service 名称
port: 80 # 改为你的 Service 端口
replicas:
min: 0
max: 10
scalingMetric:
requestRate:
granularity: 1s
targetValue: 100
window: 1m
scaledownPeriod: 300 # 5 分钟无流量后缩容
---
# Traefik IngressRoute - 路由流量到 KEDA 拦截器
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: myapp-ingress
namespace: keda # 必须在 keda namespace
spec:
entryPoints:
- web
routes:
- match: Host(`myapp.example.com`) # 改为你的域名
kind: Rule
services:
- name: keda-add-ons-http-interceptor-proxy
port: 8080
```
### 5. 应用配置
```bash
kubectl apply -f myapp-keda-scaler.yaml
```
### 6. 验证配置
```bash
# 查看 HTTPScaledObject 状态
kubectl get httpscaledobject -n myapp
# 应该看到 READY = True
# NAME TARGETWORKLOAD TARGETSERVICE MINREPLICAS MAXREPLICAS AGE READY
# myapp-http-scaler apps/v1/Deployment/myapp myapp:80 0 10 10s True
# 查看 IngressRoute
kubectl get ingressroute -n keda
# 查看当前 Pod 数量
kubectl get pods -n myapp
```
## 工作原理
1. **有流量时**
- 用户访问 `myapp.example.com`
- Traefik 将流量路由到 KEDA HTTP 拦截器
- 拦截器检测到请求,通知 KEDA 启动 Pod
- Pod 启动后5-10秒拦截器将流量转发到应用
- 用户看到正常响应(首次访问可能有延迟)
2. **无流量时**
- 5 分钟scaledownPeriod无请求后
- KEDA 自动将 Deployment 缩容到 0
- 不消耗任何计算资源
## 常见问题排查
### 1. 访问返回 404
**检查 IngressRoute 是否在 keda namespace**
```bash
kubectl get ingressroute -n keda | grep myapp
```
如果不在,删除并重新创建:
```bash
kubectl delete ingressroute myapp-ingress -n myapp # 删除错误的
kubectl apply -f myapp-keda-scaler.yaml # 重新创建
```
### 2. HTTPScaledObject READY = False
**查看详细错误信息:**
```bash
kubectl describe httpscaledobject myapp-http-scaler -n myapp
```
**常见错误:**
- `workload already managed by ScaledObject`: 删除旧的 ScaledObject
```bash
kubectl delete scaledobject myapp-scaler -n myapp
```
### 3. Pod 没有自动缩容到 0
**检查是否有旧的 ScaledObject 阻止缩容:**
```bash
kubectl get scaledobject -n myapp
```
如果有,删除它:
```bash
kubectl delete scaledobject <name> -n myapp
```
### 4. 查看 KEDA 拦截器日志
```bash
kubectl logs -n keda -l app.kubernetes.io/name=keda-add-ons-http-interceptor --tail=50
```
### 5. 测试拦截器是否工作
```bash
# 获取拦截器服务 IP
kubectl get svc keda-add-ons-http-interceptor-proxy -n keda
# 直接测试拦截器
curl -H "Host: myapp.example.com" http://<CLUSTER-IP>:8080
```
## 调优建议
### 调整缩容时间
根据你的应用特点调整 `scaledownPeriod`
- **频繁访问的应用**:设置较长时间(如 600 秒 = 10 分钟)
- **偶尔访问的应用**:设置较短时间(如 180 秒 = 3 分钟)
- **演示/测试环境**:可以设置很短(如 60 秒 = 1 分钟)
```yaml
scaledownPeriod: 600 # 10 分钟
```
### 调整扩容阈值
根据应用负载调整 `targetValue`
```yaml
scalingMetric:
requestRate:
targetValue: 50 # 每秒 50 个请求时扩容(更敏感)
```
### 调整最大副本数
```yaml
replicas:
min: 0
max: 20 # 根据你的资源和需求调整
```
## 监控和观察
### 实时监控 Pod 变化
```bash
watch -n 2 'kubectl get pods -n myapp'
```
### 查看 HTTPScaledObject 事件
```bash
kubectl describe httpscaledobject myapp-http-scaler -n myapp
```
### 查看 Deployment 副本数变化
```bash
kubectl get deployment myapp -n myapp -w
```
## 完整示例navigation 应用
参考 `navigation-complete.yaml` 文件,这是一个完整的工作示例。
## 注意事项
1. **首次访问延迟**Pod 从 0 启动需要 5-10 秒,用户首次访问会有延迟
2. **数据库连接**:确保应用能够快速重新建立数据库连接
3. **会话状态**:不要在 Pod 中存储会话状态,使用 Redis 等外部存储
4. **健康检查**:配置合理的 readinessProbe确保 Pod 就绪后才接收流量
5. **资源限制**:设置合理的 resources limits避免启动过慢
## 参考资源
- KEDA 官方文档: https://keda.sh/
- KEDA HTTP Add-on: https://github.com/kedacore/http-add-on
- Traefik IngressRoute: https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/