文章目录
- 为什么需要 KEDA ?
- KEDA 的原理
- 哪些场景适合使用 KEDA ?
- 微服务多级调用
- 任务执行(生产者与消费者)
- 周期性规律
- 配置实践
- KEDA安装
- helm 方式安装
- 策略配置
- scaledobject 对象说明
- 问题记录
为什么需要 KEDA ?
HPA 是 Kubernetes 自带的 Pod 水平自动伸缩器,只能根据监控指标对工作负载自动扩缩容,指标主要是工作负载的 CPU 和内存的利用率(Resource Metrics),如果需要支持其它自定义指标,一般是安装 prometheus-adapter 来作为 HPA 的 Custom Metrics 和 External Metrics 的实现来将 Prometheus 中的监控数据作为自定义指标提供给 HPA。理论上,用 HPA + prometheus-adapter 也能实现 KEDA 的功能,但实现上会非常麻烦,比如想要根据数据库中任务表里记录的待执行的任务数量统计进行伸缩,就需要编写并部署 Exporter 应用,将统计结果转换为 Metrics 暴露给 Prometheus 进行采集,然后 prometheus-adapter 再从 Prometheus 查询待执行的任务数量指标来决定是否伸缩。
KEDA 的出现主要是为了解决 HPA 无法基于灵活的事件源进行伸缩的这个问题,内置了几十种常见的 Scaler ,可直接跟各种第三方应用对接,比如各种开源和云托管的关系型数据库、时序数据库、文档数据库、键值存储、消息队列、事件总线等,也可以使用 Cron 表达式进行定时自动伸缩,常见的伸缩常见基本都涵盖了,如果发现有不支持的,还可以自己实现一个外部 Scaler 来配合 KEDA 使用。
KEDA 的原理
KEDA 并不是要替代 HPA,而是作为 HPA 的补充或者增强,事实上很多时候 KEDA 是配合 HPA 一起工作的,这是 KEDA 官方的架构图:
哪些场景适合使用 KEDA ?
下面罗列下适合使用 KEDA 的场景。
微服务多级调用
在微服务中,基本都存在多级调用的业务场景,压力是逐级传递的,下面展示了一个常见的情况:
如果使用传统的 HPA 根据负载扩缩容,用户流量进入集群后:
- Deploy A 负载升高,指标变化迫使 Deploy A 扩容。
- A 扩容之后,吞吐量变大,B 受到压力,再次采集到指标变化,扩容 Deploy B。
- B 吞吐变大,C 受到压力,扩容 Deploy C。
这个逐级传递的过程不仅缓慢,还很危险:每一级的扩容都是直接被 CPU 或内存的飙高触发的,被 “冲垮” 的可能性是普遍存在的。这种被动、滞后的方式,很明显是有问题的。
此时,我们可以利用 KEDA 来实现多级快速扩容:
- Deploy A 可根据自身负载或网关记录的 QPS 等指标扩缩容。
- Deploy B 和 Deploy C 可根据 Deploy A 副本数扩缩容(各级服务副本数保持一定比例)。
任务执行(生产者与消费者)
如果有需要长时间执行的计算任务,如数据分析、ETL、机器学习等场景,从消息队列或数据库中取任务进行执行,需要根据任务数量来伸缩,使用 HPA 不太合适,用 KEDA 就非常方便,可以让 KEDA 根据排队中的任务数量对工作负载进行伸缩,也可以自动创建 Job 来消费任务。
周期性规律
如果业务有周期性的波峰波谷特征,可以使用 KEDA 配置定时伸缩,在波峰来临之前先提前扩容,结束之后再缓慢缩容。
配置实践
KEDA安装
helm 方式安装
helm方式安装过程中发现镜像不存在,时间紧迫暂时没去解决,后续再说吧。
# 添加Helm存储库
helm repo add kedacore https://kedacore.github.io/charts
# 更新 Helm 仓库
helm repo update
# 安装kedaHelm chart
helm install keda kedacore/keda --namespace keda --create-namespace
# 卸载
kubectl delete $(kubectl get scaledobjects.keda.sh,scaledjobs.keda.sh -A \
-o jsonpath='{"-n "}{.items[*].metadata.namespace}{" "}{.items[*].kind}{"/"}{.items[*].metadata.name}{"\n"}')
helm uninstall keda -n keda
如果kubernetes服务托管在公有云服务,则可以直接通过各公有云容器应用直接安装
策略配置
这里通过对nginx-deployment服务的请求qps作为指标对服务下发弹性策略, 配置如下:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: prometheus-scaledobject
namespace: default
spec:
minReplicaCount: 1
scaleTargetRef:
name: nginx-deployment
triggers:
- type: prometheus
metadata:
serverAddress: http://<prometheus-host>:9090
threshold: '10'
query: sum(rate(nginx_ingress_controller_request_size_count{service="nginx-deployment-ceshi"}[2m]))
metricName: nginx_ingress_controller_request_size_count
通过观察发现生成了对应的HPA策略:
相关信息在的status中也可以看到:
scaledobject 对象说明
scaledobject 对象可配置的参数参考如下:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: {scaled-object-name}
annotations:
scaledobject.keda.sh/transfer-hpa-ownership: "true" # Optional. Use to transfer an existing HPA ownership to this ScaledObject
validations.keda.sh/hpa-ownership: "true" # Optional. Use to disable HPA ownership validation on this ScaledObject
autoscaling.keda.sh/paused: "true" # Optional. Use to pause autoscaling of objects explicitly
spec:
scaleTargetRef:
apiVersion: {api-version-of-target-resource} # Optional. Default: apps/v1
kind: {kind-of-target-resource} # Optional. Default: Deployment
name: {name-of-target-resource} # Mandatory. Must be in the same namespace as the ScaledObject
envSourceContainerName: {container-name} # Optional. Default: .spec.template.spec.containers[0]
pollingInterval: 30 # Optional. Default: 30 seconds
cooldownPeriod: 300 # Optional. Default: 300 seconds
idleReplicaCount: 0 # Optional. Default: ignored, must be less than minReplicaCount
minReplicaCount: 1 # Optional. Default: 0
maxReplicaCount: 100 # Optional. Default: 100
fallback: # Optional. Section to specify fallback options
failureThreshold: 3 # Mandatory if fallback section is included
replicas: 6 # Mandatory if fallback section is included
advanced: # Optional. Section to specify advanced options
restoreToOriginalReplicaCount: true/false # Optional. Default: false
horizontalPodAutoscalerConfig: # Optional. Section to specify HPA related options
name: {name-of-hpa-resource} # Optional. Default: keda-hpa-{scaled-object-name}
behavior: # Optional. Use to modify HPA's scaling behavior
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 100
periodSeconds: 15
triggers:
# {list of triggers to activate scaling of the target resource}
也可以通过kubectl命令方式来查看支持的参数。
kubectl explain ScaledObject
注意:默认minReplicaCount为0, 使用默认值会导致没流量时缩减为0, 可能会导致业务异常,使用前尽量配置关键参数,不要使用默认值。
问题记录
问题排查通过查看keda-operator 的日志来定位问题。
- HPA策略未生成,status 显示 “KEDA ScaledObject Failed to ensure HPA is correctly created for ScaledObject Error”
通过查看keda-operator日志发现确实关键参数导致解析数据失败,增加metricName
后恢复。