
# 使用KEDA实现事件驱动自动扩缩容
[KEDA](https://keda.sh/)是一款基于Kubernetes的开源事件驱动自动扩缩容组件。它可与集群原生的水平Pod自动扩缩器（HPA）无缝协同，不会覆盖或重复原有扩缩能力，仅做功能增强。依托KEDA，您能够依据待处理事件量，对集群内任意业务容器实现事件驱动式自动扩缩容；同时支持单独指定需要事件弹性的应用，其余业务不受影响，轻量化部署、兼容性强，可安全共存于任意Kubernetes集群与业务框架中。
本文介绍使用KEDA部署的流程，并通过一个具体的示例演示实践消息队列触发扩容的功能。
#### 工作原理
图1KEDA架构图   
![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002665783613.png "点击放大")
KEDA在Kubernetes集群中运行三个组件，每个组件都有不同的职责：
- **keda-operator**会监控KEDA资源（比如您的ScaledObjects），并管理整个HPA生命周期。它还直接负责将工作负载的实例数在"0到1"和"1到0"之间调整------当事件到达时，将空闲的Deployment恢复运行；当没有内容需要处理时，将其缩回0实例。
- **keda-metrics-apiserver**通过Kubernetes API Server向Kubernetes HPA暴露外部指标（这些指标从事件源如Kafka、RabbitMQ、Elasticsearch收集而来）。HPA查询这些指标以决定需要超过多少个工作负载实例。
- **keda-admission-webhooks**会在应用时验证每个KEDA资源（比如您的ScaledObject），及时发现配置错误（比如两个ScaledObjects针对同一Deployment），避免在运行时引发问题。
在扩缩容流程中，KEDA分为两条互补的处理过程：
- **0到1和1到0的扩缩容**由keda-operator直接处理。当事件发生时，operator会将Deployment的实例数量从0调整到1；当事件空闲时，operator将Deployment的实例数量从1调整到0。
- **1到N和N到1的扩缩容**委托给Horizontal Pod Autoscaler处理。keda-operator创建和管理HPA资源；HPA通过Kubernetes API Server（由keda-metrics-apiserver服务）查询外部指标，并相应调整运行的Pod数量。
 
#### 准备工作
- 创建一个CCE集群（需要大于等于1.30版本），并确保节点已绑定弹性公网IP（EIP），用于下载镜像和外部访问。
- 准备一台ECS服务器，绑定EIP并配置kubectl连接集群，详情请参见[通过kubectl连接集群](https://support.huaweicloud.com/usermanual-cce/cce_10_0107.html)。
- 在ECS服务器上安装Helm客户端（3.8及以上版本），具体操作请参见[通过Helm v3客户端部署应用](https://support.huaweicloud.com/usermanual-cce/cce_10_0144.html)。
 
#### 安装KEDA
1. 登录ECS服务器。
2. 通过以下命令安装KEDA（以2.20.1版本为例），您也可以前往[KEDA官网](https://keda.sh/docs/2.20/deploy/)按照指示手动安装。
   
   ```
   helm install keda kedacore/keda \
     --namespace keda \
     --create-namespace \
     --version 2.20.1 \
   ```
   
   
3. 通过以下命令查看KEDA是否安装成功。 
   ```
   kubectl get pod -n keda
   ```
   期望回显如下：
   ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002630164442.png "点击放大")
   
   
 
#### 使用Redis任务队列触发KEDA扩缩容
1. 部署单机Redis。 
   ```
   # 创建Redis Deployment
   kubectl create deployment redis --image=redis:7-alpine
   ```
   查看Redis pod是否就绪。
   ```
   kubectl get pod | grep "redis"
   ```
   ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002630165312.png "点击放大")
   
   
2. 暴露ClusterIP服务，供KEDA和消费程序访问。 
   ```
   kubectl expose deployment redis --port=6379 --target-port=6379
   ```
   则Redis的集群内访问地址为*redis:6379*。
   查看ClusterIP服务：
   ```
   kubectl get svc redis
   ```
   
   
3. 部署测试应用。 
   创建worker-deploy.yaml文件，内容如下：
   ```
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: redis-worker
   spec:
     replicas: 0  # 初始缩为0，无消息时不运行Pod
     selector:
       matchLabels:
         app: redis-worker
     template:
       metadata:
         labels:
           app: redis-worker
       spec:
         containers:
         - name: worker
           image: nginx:alpine
           ports:
           - containerPort: 80
   ```
   应用资源：
   ```
   kubectl apply -f worker-deploy.yaml
   ```
   查看此时副本数：
   ```
   kubectl get deploy redis-worker
   ```
   ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002630165326.png "点击放大")
   
   
4. 创建Redis触发器ScaledObject核心配置。 
   创建redis-scaledobject.yaml文件，内容如下：
   ```
   apiVersion: keda.sh/v1alpha1
   kind: ScaledObject
   metadata:
     name: redis-list-scaler
     namespace: default
   spec:
     scaleTargetRef:
       name: redis-worker          # 扩缩容对象
     minReplicaCount: 0            # 最小副本数
     maxReplicaCount: 10           # 最大副本数
     cooldownPeriod: 30            # 扩缩容冷却时间
     pollingInterval: 5            # 轮询间隔
     triggers:
     - type: redis
       metadata:
         address: redis:6379        # Redis访问地址
         listName: task_queue       # Redis队列名称
         listLength: "5"            # Redis队列长度阈值
   ```
   应用触发器：
   ```
   kubectl apply -f redis-scaledobject.yaml
   ```
   查看触发器状态，READY状态为True则配置成功。
   ```
   kubectl get scaledobject
   ```
   ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002660324701.png "点击放大")
   
   
5. 进入Redis客户端。 
   ```
   kubectl exec -it deploy/redis -- redis-cli
   ```
   
   
6. 往task_queue写入多条任务信息。 
   ```
   # 一次性写入8条消息，超过阈值5，触发扩容
   LPUSH task_queue task1 task2 task3 task4 task5 task6 task7 task8
   # 查看队列长度
   LLEN task_queue
   ```
   ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002660444755.png "点击放大")
   
   
7. 在另一个终端中观察应用副本自动扩容。 
   ```
   kubectl get deploy redis-worker
   ```
   ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002660324745.png "点击放大")
   副本数从0变成2，自动扩容成功。
   
   
8. 回到redis-cli窗口，弹出队列消息。 
   ```
   DEL task_queue
   ```
   ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002660444845.png "点击放大")
   
   
9. 等待30秒后，观察应用副本自动缩容。 
   ```
   kubectl get deploy redis-worker
   ```
   ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002660444851.png "点击放大")
   副本数从2变成0，自动缩容成功。
   
   
 
