华为云kubernetes基于keda自动伸缩deployment副本(监听redis队列长度)
1 概述
KEDA(Kubernetes-based Event-Driven Autoscaler,网址是https://keda.sh)是在 Kubernetes 中事件驱动的弹性伸缩器,功能非常强大。不仅支持根据基础的CPU和内存指标进行伸缩,还支持根据各种消息队列中的长度、数据库中的数据统计、QPS、Cron 定时计划以及您可以想象的任何其他指标进行伸缩。KEDA支持的所有scaler,可从如下网址里查询:
https://keda.sh/docs/2.16/scalers
该项目于2020年3月被 CNCF 接收,并于2021年8月开始孵化,最终在2023年8月宣布毕业,目前已经非常成熟,可放心在生产环境中使用。
本文介绍在华为云kubernetes中部署keda v2.16.1,keda监听redis队列中的长度来伸缩目标deployment的副本数。
2 架构图
KEDA 并不是要替代HPA,而是作为HPA的补充或者增强。实际上,KEDA 经常与 HPA 一起协同工作。以下是 KEDA 官方的架构图

- 当要将工作负载的副本数缩到闲时副本数,或从闲时副本数开始扩容时,由KEDA通过修改工作负载的副本数实现(闲时副本数小于 minReplicaCount,包括0,即可以缩到0)。
- 其他情况下的扩缩容过程都由Kubernetes HPA实现,HPA被KEDA管理,HPA使用External Metrics作为数据源,而External Metrics实际的数据由KEDA提供。
- KEDA 各种Scalers的目的其实就是为HPA暴露External Metrics格式的数据,KEDA会将各种外部事件转换为所需的External Metrics数据,最终实现HPA读取这些External Metrics数据进行自动伸缩,因此KEDA直接复用了HPA 已有的能力,如果需要控制扩缩容的行为细节(例如快速扩容、缓慢缩容),可以直接通过配置 HPA 的 behavior 字段来实现(要求 Kubernetes 版本 ≥1.18)。
3 环境准备
3.1 华为云kubernetes集群
准备一个kubernetes集群,如下图所示:

如果你需要KEDA基于传统的CPU和内存来伸缩工作负载,则需要为kubernetes集群开启metrics插件。
如果你需要KEDA基于传统的CPU和内存来伸缩工作负载,则需要为kubernetes集群开启metrics插件。
如果你需要KEDA基于传统的CPU和内存来伸缩工作负载,则需要为kubernetes集群开启metrics插件。
开启metrics插件只需要在华为云kubernetes控制台的插件中心里安装即可,如下图:



3.2 redis服务
准备一个redis实例,如下图所示:

4 部署
4.1 部署keda
为helm添加新的repo,命令如下:
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
下载values.yaml,命令如下:
helm show values kedacore/keda > values.yaml
修改values.yaml文件中的容器镜像,方便在国内环境拉取,如下所示:
image:keda:registry: docker.iorepository: imroc/kedatag: "2.16.1"metricsApiServer:registry: docker.iorepository: imroc/keda-metrics-apiserver tag: "2.16.1"webhooks:registry: docker.iorepository: imroc/keda-admission-webhookstag: "2.16.1"
部署keda,命令如下所示:
helm upgrade --install keda kedacore/keda \
--namespace keda --create-namespace \
-f values.yaml

4.2 部署待被伸缩的目标deployment
创建一个零副本的服务,如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:name: php-apachenamespace: default
spec:replicas: 0selector:matchLabels:run: php-apachetemplate:metadata:labels:run: php-apachespec:containers:- image: deis/hpa-exampleimagePullPolicy: Alwaysname: php-apacheports:- containerPort: 80protocol: TCPresources:limits:cpu: 100mrequests:cpu: 20m
5 创建伸缩对象ScaledObject
创建如下对象:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:name: hpa-appnamespace: default
spec:scaleTargetRef: # 扩容目标对象name: php-apachekind: DeploymentapiVersion: apps/v1minReplicaCount: 1 # 最小副本数maxReplicaCount: 6 # 最大副本数triggers: # 触发规则- metadata:address: redis-****.cn-south-1.dcs.myhuaweicloud.com:6379 # Redis地址listName: keda-hpa-demo-list # Redis的列表的key名称listLength: "10" # 触发伸缩的队列长度password: "********your-redis-password********"type: redis # 事件源类型为redis

6 往redis中的队列添加元素
队列名称为keda-hpa-demo-list,往里面添加20个元素,命令如下:
RPUSH keda-hpa-demo-list value1 value2 value3 value4 value5 value6 value7 value8 value9 value10
RPUSH keda-hpa-demo-list value11 value12 value13 value14 value15 value16 value17 value18 value19 value20
LRANGE keda-hpa-demo-list 0 -1

7 伸缩现象
查看kubernetes event,可见副本数量伸缩为2了。
kubectl get event
31m Normal SuccessfulRescale horizontalpodautoscaler/keda-hpa-hpa-app New size: 2; reason: external metric s0-redis-keda-hpa-demo-list(&LabelSelector{MatchLabels:map[string]string{scaledobject.keda.sh/name: hpa-app,},MatchExpressions:[]LabelSelectorRequirement{},}) above target


仔细发现,keda自动创建了HPA对象,这个对象里的一些字段是来自,如下所示:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"keda.sh/v1alpha1","kind":"ScaledObject","metadata":{"annotations":{},"name":"hpa-app","namespace":"default"},"spec":{"maxReplicaCount":6,"minReplicaCount":1,"scaleTargetRef":{"apiVersion":"apps/v1","kind":"Deployment","name":"php-apache"},"triggers":[{"metadata":{"address":"redis-6482e5d4-6f37-4138-ab01-64f7ca6a4a6d.cn-south-1.dcs.myhuaweicloud.com:6379","listLength":"10","listName":"keda-hpa-demo-list","password":"iloveredis@2025"},"type":"redis"}]}}creationTimestamp: "2025-02-12T14:28:56Z"labels:app.kubernetes.io/managed-by: keda-operatorapp.kubernetes.io/name: keda-hpa-hpa-appapp.kubernetes.io/part-of: hpa-appapp.kubernetes.io/version: 2.16.1scaledobject.keda.sh/name: hpa-appname: keda-hpa-hpa-appnamespace: defaultownerReferences:- apiVersion: keda.sh/v1alpha1blockOwnerDeletion: truecontroller: truekind: ScaledObjectname: hpa-appuid: 795e92f1-da13-4281-a460-9cfe750ec753resourceVersion: "99768"uid: 629c14c2-b0a0-4007-8c38-eaa104dc20a2
spec:maxReplicas: 6metrics:- external:metric:name: s0-redis-keda-hpa-demo-listselector:matchLabels:scaledobject.keda.sh/name: hpa-apptarget:averageValue: "10"type: AverageValuetype: ExternalminReplicas: 1scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: php-apache
status:conditions:- lastTransitionTime: "2025-02-12T14:29:11Z"message: the HPA controller was able to get the target's current scalereason: SucceededGetScalestatus: "True"type: AbleToScale- lastTransitionTime: "2025-02-12T15:34:36Z"message: 'the HPA was unable to compute the replica count: unable to get externalmetric default/s0-redis-keda-hpa-demo-list/&LabelSelector{MatchLabels:map[string]string{scaledobject.keda.sh/name:hpa-app,},MatchExpressions:[]LabelSelectorRequirement{},}: unable to fetch metricsfrom external metrics API: rpc error: code = Unknown desc = error when gettingmetric values error getting scalers connection to redis failed: dial tcp: lookupredis-6482e5d4-6f37-4138-ab01-64f7ca6a4a6d.cn-south-1.dcs.myhuaweicloud.comon 169.254.1.1:53: no such host'reason: FailedGetExternalMetricstatus: "False"type: ScalingActive- lastTransitionTime: "2025-02-12T14:29:11Z"message: the desired count is within the acceptable rangereason: DesiredWithinRangestatus: "False"type: ScalingLimitedcurrentMetrics:- type: ""currentReplicas: 2desiredReplicas: 2lastScaleTime: "2025-02-12T14:30:11Z"
同时,还创建了external metrics对象,如下所示:

kubectl get apiservices | grep external.metrics.k8s.io

kubectl get apiservice v1beta1.external.metrics.k8s.io -o yaml
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:annotations:meta.helm.sh/release-name: kedameta.helm.sh/release-namespace: kedacreationTimestamp: "2025-02-12T07:52:48Z"labels:app.kubernetes.io/component: operatorapp.kubernetes.io/instance: kedaapp.kubernetes.io/managed-by: Helmapp.kubernetes.io/name: v1beta1.external.metrics.k8s.ioapp.kubernetes.io/part-of: keda-operatorapp.kubernetes.io/version: 2.16.1helm.sh/chart: keda-2.16.1name: v1beta1.external.metrics.k8s.ioresourceVersion: "47073"uid: 0428df85-50ed-4363-9799-f3c03dee88e9
spec:caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0************************DdBPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==group: external.metrics.k8s.iogroupPriorityMinimum: 100service:name: keda-operator-metrics-apiservernamespace: kedaport: 443version: v1beta1versionPriority: 100
status:conditions:- lastTransitionTime: "2025-02-12T13:26:19Z"message: all checks passedreason: Passedstatus: "True"type: Available
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/default/s0-redis-keda-hpa-demo-list?labelSelector=scaledobject.keda.sh%2Fname%3Dhpa-app" | jq .

可见keda namespace下的keda-operator-metrics-apiserver服务是kube-apiserver的指标类接口的后端,也是keda各个scaler的前端网关。

8 小结
通过内置很多scaler的伸缩神器keda,以redis队列的长度为依据对目标工作负载deployment进行伸缩,开箱即用,解决了以往的HPA Controller + Prometheus Adaptor + Prometheus + Exporter的自定义流程。
相关文章:
华为云kubernetes基于keda自动伸缩deployment副本(监听redis队列长度)
1 概述 KEDA(Kubernetes-based Event-Driven Autoscaler,网址是https://keda.sh)是在 Kubernetes 中事件驱动的弹性伸缩器,功能非常强大。不仅支持根据基础的CPU和内存指标进行伸缩,还支持根据各种消息队列中的长度、…...
入选TPAMI2025!傅里叶变换+目标检测新突破!
今天给大家推荐一个目标检测,好发不卷的新思路:与傅里叶变换结合! 一方面,不仅能提升检测的准确性和可靠性,还能增强模型的通用性和适应性,灵活应对复杂场景。比如TPAMI25的FSD模型,便通过该方…...
物联网智能语音控制灯光系统设计与实现
背景 随着物联网技术的蓬勃发展,智能家居逐渐成为现代生活的一部分。在众多智能家居应用中,智能灯光控制系统尤为重要。通过语音控制和自动调节灯光,用户可以更便捷地操作家中的照明设备,提高生活的舒适度与便利性。本文将介绍一…...
fastjson2学习大纲
一、基础篇 - JSON与fastjson2核心概念 JSON基础 JSON语法规范(RFC 8259)JSON数据类型与Java类型对应关系序列化/反序列化核心概念 fastjson2入门 与fastjson1的主要区别核心优势: 性能提升(JSONB二进制协议)更完善的…...
等级保护2.0|网络安全服务
等级保护2.0|网络安全服务 定义 对于国家秘密信息、法人和其他组织及公民专有信息以及公开信息的存储、传输、处理这些信息系统分等级实行安全保护,对信息系统中发生的信息安全时间分等级响应、处置。 思想 对信息安全实行等级化保护和等级化管理 目标 突出重…...
告别硬编码:用 load_dotenv 高效管理你的环境变量
前言 环境变量是开发中常见的配置工具,特别是用于存储敏感信息,如数据库连接字符串、API 密钥等。直接将这些数据写进代码,除了不安全外,还让人感到一团乱麻。为了避免这种情况,dotenv 库应运而生,它能帮我们轻松从 .env 文件中加载环境变量,避免将这些敏感信息硬编码到…...
安科瑞光伏发电防逆流解决方案——守护电网安全,提升能源效率
安科瑞 华楠 18706163979 在当今大力发展清洁能源的时代背景下,光伏发电作为一种可持续的能源解决方案, 正得到越来越广泛的应用。然而,光伏发电过程中出现的逆流问题,给电网的安全稳定 运行带来了诸多挑战。若不能有效解决&…...
Unity使用iTextSharp导出PDF-02基础结构及设置中文字体
基础结构 1.创建一个Document对象 2.使用PdfWriter创建PDF文档 3.打开文档 4.添加内容,调用文档Add方法添加内容时,内容写入到输出流中 5.关闭文档 using UnityEngine; using iTextSharp.text; using System.IO; using iTextSharp.text.pdf; using Sys…...
Web第二次作业_补充完小鹅通首页(静态)
目录 题目 index css style 解题 技术优势 html css 运营服务 html css 小鹅通 html css 咨询 html css 友情链接、公司信息 html css 效果展示 技术优势 运营服务 小鹅通 咨询 友情链接、公司信息 题目 index <!DOCTYPE html> <html lang…...
碳纤维复合材料制造的六西格玛管理实践:破解高端制造良率困局的实战密码
碳纤维复合材料制造的六西格玛管理实践:破解高端制造良率困局的实战密码 在全球碳中和与高端制造升级的双重驱动下,碳纤维复合材料行业正经历前爆发式增长。航空航天、新能源汽车、风电叶片等领域对碳纤维产品的性能稳定性提出近乎苛刻的要求࿰…...
在 Mac ARM 架构上使用 nvm 安装 Node.js 版本 16.20.2
文章目录 1. 安装 nvm(如果还没有安装的话)2. 加载 nvm 配置3. 列出特定系列的 Node.js 版本(远程):4. 安装 Node.js 16.20.25. 使用指定版本的 Node.js6. 验证安装 在 Mac ARM 架构上使用 nvm 安装 Node.js 版本 16.…...
tenda路由器WriteFacMac存在远程命令执行漏洞(CVE-2024-10697)
一、漏洞简介 tenda路由器WriteFacMac存在远程命令执行漏洞 二、漏洞影响 tenda路由器三、网络测绘: fofa: title"Tenda | LOGIN"四、复现过程 POC 1 GET /goform/WriteFacMac?macls%20%3E/webroot/1.txt HTTP/1.1 Accept: text/html,application/…...
【NLP 21、实践 ③ 全切分函数切分句子】
当无数个自己离去,我便日益坦然 —— 25.2.9 一、jieba分词器 Jieba 是一款优秀的 Python 中文分词库,它支持多种分词模式,其中全切分方式会将句子中所有可能的词语都扫描出来。 1.原理 全切分方式会找出句子中所有可能的词语组合。对于一…...
晶闸管主要参数分析与损耗计算
1. 主要参数 断态正向可重复峰值电压 :是晶闸管在不损坏的情况下能够承受的正向最大阻断电压。断态正向不可重复峰值电压 :是晶闸管只有一次可以超过的正向最大阻断电压,一旦晶闸管超过此值就会损坏,一般情况下 反向可重复峰值电压 :是指晶闸管在不损坏的情况下能够承受的…...
【Stable Diffusion部署至Google Colab】
Google Colab 中快速搭建带 GPU 加速的 Stable Diffusion WebUI from google.colab import drive drive.mount(/content/drive) !mkdir /content/drive/MyDrive/sd-webui-files !pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 torchaudio==0.13.1 --extra-index…...
mongoTemplate获取某列最大值
首先,MongoDB中获取某列的最大值通常是通过聚合框架中的$group和$max操作符来完成的。那在Spring Data中,应该怎么构建这个聚合查询呢? 首先,可能需要创建一个Aggregation对象,里面包含分组和求最大值的步骤。比如&…...
基于Java的分布式系统架构设计与实现
Java在大数据处理中的应用:基于Java的分布式系统架构设计与实现 随着大数据时代的到来,数据处理的规模和复杂性不断增加。为了高效处理海量数据,分布式系统成为了必不可少的架构之一。而Java,凭借其平台独立性、丰富的生态系统以…...
独立开发日报:从AI到本地服务,5个新颖项目的启发
今天在Hacker News上看到几个特别有意思的项目,它们都找到了不同的切入点:有的用AI解决创意问题,有的深耕本地服务,有的则回归技术本质。一起来看看这些项目背后的思路。 1. AI涂色页面生成器 - 创意与AI的完美结合 这是一个基于…...
找单独的数
问题描述 在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。 要求: 设…...
记使用AScript自动化操作ios苹果手机
公司业务需要自动化操作手机,本来以为很困难,没想到使用AScript工具出乎意料的简单,但是还有很多坑存在,写个博客记录一下。 工具信息: 手机:iphone7 系统版本:ios15 AScript官方文档链接&a…...
Android Studio集成讯飞SDK过程中在配置Project的时候有感
在配置讯飞的语音识别SDK(流式版)时候,跟着写了两个Demo,一个是YuYinTestDemo01,另一个是02,demo01比较简单,实现功能图象也比较简陋,没用讯飞SDK提供的图片,也就是没用到…...
[LLM面试题] 指示微调(Prompt-tuning)与 Prefix-tuning区别
一、提示调整(Prompt Tuning) Prompt Tuning是一种通过改变输入提示语(input prompt)以获得更优模型效果的技术。举个例子,如果我们想将一条英语句子翻译成德语,可以采用多种不同的方式向模型提问,如下图所示…...
Docker上安装Zabbix-server-mysql报错
创建新的zabbix server (mysql)容易,最后一条日志报错 cannot usedatabase"zabbix": its "users" table is empty (is this the Zabbix proxy database?) 往前还有一条关键报错信息 ERROR 1153 (08S01): Got a packe…...
c#展示网页并获取网页上触发按钮的值进行系统业务逻辑处理
日前项目上遇到需要调用一个第三方的监控接口,给对方参数后,会返回一个url地址,我方系统需要根据用户在网页上点击的不同按钮,要求如下:在打开违规提醒窗口时,需要注册Callback方法(含一个字符串…...
Flappy Bird开发学习记录
概述 为了了解一下Unity的开发过程,或者说感受?先搞简单的练练手。 工具 Unity:2022.3.51f1c1 visual studio 2022 开发过程 项目基本设置 新建2d项目,游戏画面设置为1080*1920(9:16)。 图片素材设…...
SDKMAN! 的英文全称是 Software Development Kit Manager(软件开发工具包管理器)
文章目录 SDKMAN! 的核心功能SDKMAN! 的常用命令SDKMAN! 的优势总结 SDKMAN! 的英文全称是 Software Development Kit Manager。它是一个用于管理多个软件开发工具(如 Java、Groovy、Scala、Kotlin 等)版本的工具。SDKMAN! 提供了一个简单的方式来安装、…...
?.、??、||分别是什么,又有哪些区别???
在 JavaScript 中,?.、?? 和 || 是三种不同的操作符。 1、?.:可选链操作符 ?. 是一个可选链操作符,用于安全地访问嵌套属性,而不用担心中间的某个属性可能为 null 或 undefined,从而避免运行时错误。 const use…...
7个国内能打开的AI绘画网站!新手福音!
以下是我收集的国内能打开的AI绘画网站。 1、6pen 网址:https://6pen.art/ 2、文心大模型 网址:https://wenxin.baidu.com/moduleApi/ernieVilg 3、Draft 网址:https://draft.art/ai- art/drawing 4、nightcafe 网址:https:/…...
JavaWeb学习-Mybatis(增删改查)
(一)Mybatis入门程序 1.创建springboot工程,并导入 mybatis的起步依赖、mysql的驱动包。(项目工程创建完成后,自动在pom.xml文件中,导入Mybatis依赖和MySQL驱动依赖) <dependencies> <!-- mybatis起步依赖 --> <dependency> …...
C/C++面试高频题解析与解题思路(附答案)
一、基础语法与核心概念 指针与引用的区别? 问题:指针和引用在初始化、空值、操作方式上的差异是什么? 解析: 引用必须初始化且不能指向空值,而指针可初始化为空(nullptr)。 引用是变量的别名…...
