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

8.5 KiB
Raw Blame History

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 是否已安装

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

如果未安装,执行以下命令安装

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

示例:

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 的核心配置。

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 的拦截器服务。

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 配置:

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,并根据你的应用修改相应的值:

---
# 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. 应用配置

kubectl apply -f myapp-keda-scaler.yaml

6. 验证配置

# 查看 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

kubectl get ingressroute -n keda | grep myapp

如果不在,删除并重新创建:

kubectl delete ingressroute myapp-ingress -n myapp  # 删除错误的
kubectl apply -f myapp-keda-scaler.yaml  # 重新创建

2. HTTPScaledObject READY = False

查看详细错误信息:

kubectl describe httpscaledobject myapp-http-scaler -n myapp

常见错误:

  • workload already managed by ScaledObject: 删除旧的 ScaledObject
    kubectl delete scaledobject myapp-scaler -n myapp
    

3. Pod 没有自动缩容到 0

检查是否有旧的 ScaledObject 阻止缩容:

kubectl get scaledobject -n myapp

如果有,删除它:

kubectl delete scaledobject <name> -n myapp

4. 查看 KEDA 拦截器日志

kubectl logs -n keda -l app.kubernetes.io/name=keda-add-ons-http-interceptor --tail=50

5. 测试拦截器是否工作

# 获取拦截器服务 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 分钟)
scaledownPeriod: 600  # 10 分钟

调整扩容阈值

根据应用负载调整 targetValue

scalingMetric:
  requestRate:
    targetValue: 50  # 每秒 50 个请求时扩容(更敏感)

调整最大副本数

replicas:
  min: 0
  max: 20  # 根据你的资源和需求调整

监控和观察

实时监控 Pod 变化

watch -n 2 'kubectl get pods -n myapp'

查看 HTTPScaledObject 事件

kubectl describe httpscaledobject myapp-http-scaler -n myapp

查看 Deployment 副本数变化

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避免启动过慢

参考资源