381 lines
8.5 KiB
Markdown
381 lines
8.5 KiB
Markdown
# 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/
|