diff --git a/content/best-practices/autoscaling/keda/cron.md b/content/best-practices/autoscaling/keda/cron.md new file mode 100644 index 0000000..93032ff --- /dev/null +++ b/content/best-practices/autoscaling/keda/cron.md @@ -0,0 +1,67 @@ +# 定时水平伸缩 (Cron 触发器) + +## Cron 触发器 + +KEDA 支持 Cron 触发器,即使用 Cron 表达式来配置周期性的定时扩缩容,用法参考 [KEDA Scalers: Cron](https://keda.sh/docs/latest/scalers/cron/)。 + +Cron 触发器适用于有周期性特征的业务,比如业务流量有固定的周期性波峰和波谷特征。 + +## 案例:每天固定时间点的秒杀活动 + +秒杀活动的特征是时间比较固定,可以在活动开始前提前扩容,以下展示了 `ScaledObject` 配置示例。 + +```yaml showLineNumbers +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: seckill +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: seckill + pollingInterval: 15 + minReplicaCount: 2 # 至少保留 2 个副本 + maxReplicaCount: 1000 + advanced: + horizontalPodAutoscalerConfig: + behavior: # 控制扩缩容行为,使用比较保守的策略,快速扩容,缓慢缩容 + scaleDown: # 缓慢缩容:至少冷却 10 分钟才能缩容 + stabilizationWindowSeconds: 600 + policies: + - type: Percent + value: 100 + periodSeconds: 15 + scaleUp: # 快速扩容:每 15s 最多允许扩容 5 倍 + policies: + - type: Percent + value: 500 + periodSeconds: 15 + triggers: + # highlight-start + - type: cron # 每天早上 10 点秒杀活动,确保前后半小时内至少有 200 个副本 + metadata: + timezone: Asia/Shanghai + start: 30 9 * * * + end: 30 10 * * * + desiredReplicas: "200" + - type: cron # 每天晚上 6 点秒杀活动,确保前后半小时内至少有 200 个副本 + metadata: + timezone: Asia/Shanghai + start: 30 17 * * * + end: 30 18 * * * + desiredReplicas: "200" + # highlight-end + - type: memory # CPU 利用率超过 60% 扩容 + metricType: Utilization + metadata: + value: "60" + - type: cpu # 内存利用率超过 60% 扩容 + metricType: Utilization + metadata: + value: "60" +``` + +## 注意事项 + +通常触发器不能只配置 Cron,还需和其它触发器一起配合使用,因为如果在 cron 的 start 和 end 区间之外的时间段,如果没有其它触发器活跃,副本数就会降到 `minReplicaCount`,可能并不是我们想要的。 diff --git a/content/best-practices/autoscaling/keda/install.md b/content/best-practices/autoscaling/keda/install.md new file mode 100644 index 0000000..b3cfe84 --- /dev/null +++ b/content/best-practices/autoscaling/keda/install.md @@ -0,0 +1,79 @@ +# 使用 helm 部署 KEDA + +## 添加 helm repo + +```bash +helm repo add kedacore https://kedacore.github.io/charts +helm repo update +``` + +## 准备 values.yaml + +先查看默认的 values.yaml (看看有哪些可以自定义的配置项) + +```bash +helm show values kedacore/keda +``` + +默认的依赖镜像在国内环境拉取不了,可以替换为使用 docker hub 上的 mirror 镜像,配置 `values.yaml`: + +```yaml +image: + keda: + repository: docker.io/imroc/keda + metricsApiServer: + repository: docker.io/imroc/keda-metrics-apiserver + webhooks: + repository: docker.io/imroc/keda-admission-webhooks +``` + +> 以上 mirror 镜像长期自动同步,可放心使用和更新版本。 + +## 安装 + +```bash +helm upgrade --install keda kedacore/keda \ + --namespace keda --create-namespace \ + -f values.yaml +``` + +## 版本与升级 + +每个 KEDA 的版本都有对应适配的 K8S 版本区间,如果你的 TKE 集群版本不是特别新,安装最新版的 KEDA 可能无法兼容,可查看 [KEDA Kubernetes Compatibility](https://keda.sh/docs/latest/operate/cluster/#kubernetes-compatibility) 来确认当前集群版本能兼容的 KEDA 版本。 + +比如 TKE 集群版本是 1.26,对应能兼容的 KEDA 最新版本是 v2.12,再查询到 KEDA v2.12 (APP VERSION) 对应的 Chart 版本 (CHART VERSION) 最高版本是 2.12.1: + +```bash +$ helm search repo keda --versions +NAME CHART VERSION APP VERSION DESCRIPTION +kedacore/keda 2.13.2 2.13.1 Event-based autoscaler for workloads on Kubernetes +kedacore/keda 2.13.1 2.13.0 Event-based autoscaler for workloads on Kubernetes +kedacore/keda 2.13.0 2.13.0 Event-based autoscaler for workloads on Kubernetes +# highlight-next-line +kedacore/keda 2.12.1 2.12.1 Event-based autoscaler for workloads on Kubernetes +kedacore/keda 2.12.0 2.12.0 Event-based autoscaler for workloads on Kubernetes +kedacore/keda 2.11.2 2.11.2 Event-based autoscaler for workloads on Kubernetes +kedacore/keda 2.11.1 2.11.1 Event-based autoscaler for workloads on Kubernetes +``` + +安装 KEDA 时指定版本: + +```bash +helm upgrade --install keda kedacore/keda \ + --namespace keda --create-namespace \ + # highlight-next-line + --version 2.12.1 \ + -f values.yaml +``` + +后续升级版本时可复用上面的安装命令,只需修改下版本号即可。 + +**注意**:在升级 TKE 集群前也用这里的方法先确认下升级后的集群版本能否兼容当前版本的 KEDA,如果不能,请提前升级 KEDA 到当前集群版本所能兼容的最新 KEDA 版本。 + +## 卸载 + +参考 [官方卸载说明](https://keda.sh/docs/latest/deploy/#uninstall)。 + +## 参考资料 + +* [KEDA 官方文档:Deploying KEDA](https://keda.sh/docs/latest/deploy/) diff --git a/content/best-practices/autoscaling/keda/overview.md b/content/best-practices/autoscaling/keda/overview.md new file mode 100644 index 0000000..1af6bff --- /dev/null +++ b/content/best-practices/autoscaling/keda/overview.md @@ -0,0 +1,58 @@ +# 认识 KEDA + +## 什么是 KEDA ? + +KEDA (Kubernetes-based Event-Driven Autoscaler) 是在 Kubernetes 中事件驱动的弹性伸缩器,功能非常强大。不仅支持根据基础的 CPU 和内存指标进行伸缩,还支持根据各种消息队列中的长度、数据库中的数据统计、QPS、Cron 定时计划以及您可以想象的任何其他指标进行伸缩,甚至还可以将副本缩到 0。 + +该项目于 2020.3 被 CNCF 接收,2021.8 开始孵化,最后在 2023.8 宣布毕业,目前已经非常成熟,可放心在生产环境中使用。 + +## 为什么需要 KEDA ? + +HPA 是 Kubernetes 自带的 Pod 水平自动伸缩器,只能根据监控指标对工作负载自动扩缩容,指标主要是工作负载的 CPU 和内存的利用率(Resource Metrics),如果需要支持其它自定义指标,一般是安装 [prometheus-adapter](https://github.com/kubernetes-sigs/prometheus-adapter) 来作为 HPA 的 Custom Metrics 和 External Metrics 的实现来将 Prometheus 中的监控数据作为自定义指标提供给 HPA。理论上,用 HPA + prometheus-adapter 也能实现 KEDA 的功能,但实现上会非常麻烦,比如想要根据数据库中任务表里记录的待执行的任务数量统计进行伸缩,就需要编写并部署 Exporter 应用,将统计结果转换为 Metrics 暴露给 Prometheus 进行采集,然后 prometheus-adapter 再从 Prometheus 查询待执行的任务数量指标来决定是否伸缩。 + +KEDA 的出现主要是为了解决 HPA 无法基于灵活的事件源进行伸缩的这个问题,内置了几十种常见的 [Scaler](https://keda.sh/docs/latest/scalers/) ,可直接跟各种第三方应用对接,比如各种开源和云托管的关系型数据库、时序数据库、文档数据库、键值存储、消息队列、事件总线等,也可以使用 Cron 表达式进行定时自动伸缩,常见的伸缩常见基本都涵盖了,如果发现有不支持的,还可以自己实现一个外部 Scaler 来配合 KEDA 使用。 + +## KEDA 的原理 + +KEDA 并不是要替代 HPA,而是作为 HPA 的补充或者增强,事实上很多时候 KEDA 是配合 HPA 一起工作的,这是 KEDA 官方的架构图: + +![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/2024%2F04%2F07%2F20240407153149.png) + +* 当要将工作负载的副本数缩到闲时副本数,或从闲时副本数扩容时,由 KEDA 通过修改工作负载的副本数实现(闲时副本数小于 `minReplicaCount`,包括 0,即可以缩到 0)。 +* 其它情况下的扩缩容由 HPA 实现,HPA 由 KEDA 自动管理,HPA 使用 External Metrics 作为数据源,而 External Metrics 后端的数据由 KEDA 提供。 +* KEDA 各种 Scalers 的核心其实就是为 HPA 暴露 External Metrics 格式的数据,KEDA 会将各种外部事件转换为所需的 External Metrics 数据,最终实现 HPA 通过 External Metrics 数据进行自动伸缩,直接复用了 HPA 已有的能力,所以如果还想要控制扩缩容的行为细节(比如快速扩容,缓慢缩容),可以直接通过配置 HPA 的 `behavior` 字段来实现 (要求 Kubernetes 版本 >= 1.18)。 + +除了工作负载的扩缩容,对于任务计算类场景,KEDA 还可以根据排队的任务数量自动创建 Job 来实现对任务的及时处理: + +![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/2024%2F04%2F08%2F20240408083135.png) + +## 哪些场景适合使用 KEDA ? + +下面罗列下适合使用 KEDA 的场景。 + +### 微服务多级调用 + +在微服务中,基本都存在多级调用的业务场景,压力是逐级传递的,下面展示了一个常见的情况: + +![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/2024%2F04%2F08%2F20240408084514.png) + +如果使用传统的 HPA 根据负载扩缩容,用户流量进入集群后: +1. `Deploy A` 负载升高,指标变化迫使 `Deploy A` 扩容。 +2. A 扩容之后,吞吐量变大,B 受到压力,再次采集到指标变化,扩容 `Deploy B`。 +3. B 吞吐变大,C 受到压力,扩容 `Deploy C`。 + +这个逐级传递的过程不仅缓慢,还很危险:每一级的扩容都是直接被 CPU 或内存的飙高触发的,被 “冲垮” 的可能性是普遍存在的。这种被动、滞后的方式,很明显是有问题的。 + +此时,我们可以利用 KEDA 来实现多级快速扩容: +* `Deploy A` 可根据自身负载或网关记录的 QPS 等指标扩缩容。 +* `Deploy B` 和 `Deploy C` 可根据 `Deploy A` 副本数扩缩容(各级服务副本数保持一定比例)。 + +### 任务执行(生产者与消费者) + +如果有需要长时间执行的计算任务,如数据分析、ETL、机器学习等场景,从消息队列或数据库中取任务进行执行,需要根据任务数量来伸缩,使用 HPA 不太合适,用 KEDA 就非常方便,可以让 KEDA 根据排队中的任务数量对工作负载进行伸缩,也可以自动创建 Job 来消费任务。 + +![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/2024%2F04%2F09%2F20240409172007.png) + +### 周期性规律 + +如果业务有周期性的波峰波谷特征,可以使用 KEDA 配置定时伸缩,在波峰来临之前先提前扩容,结束之后再缓慢缩容。 diff --git a/content/best-practices/autoscaling/keda/workload.md b/content/best-practices/autoscaling/keda/workload.md new file mode 100644 index 0000000..e7cf749 --- /dev/null +++ b/content/best-practices/autoscaling/keda/workload.md @@ -0,0 +1,97 @@ +# 多级服务同步水平伸缩 (Workload 触发器) + +## Workload 触发器 + +KEDA 支持 Kubernetes Workload 触发器,即可以根据的一个或多个工作负载的 Pod 数量来扩缩容,在多级服务调用的场景下很有用,具体用法参考 [KEDA Scalers: Kubernetes Workload](https://keda.sh/docs/2.13/scalers/kubernetes-workload/)。 + +## 案例:多级服务同时扩容 + +比如下面这种多级微服务调用: + +![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/2024%2F04%2F08%2F20240408084514.png) + +* A、B、C 这一组服务通常有比较固定的数量比例。 +* A 的压力突增,迫使扩容,B 和 C 也可以用 KEDA 的 Kubernetes Workload 触发器实现与 A 几乎同时扩容,而无需等待压力逐级传导才缓慢迫使扩容。 + +首先配置 A 的扩容,根据 CPU 和内存压力扩容: + +```yaml showLineNumbers +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: a +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: a + pollingInterval: 15 + minReplicaCount: 10 + maxReplicaCount: 1000 + triggers: + - type: memory + metricType: Utilization + metadata: + value: "60" + - type: cpu + metricType: Utilization + metadata: + value: "60" +``` + +然后配置 B 和 C 的扩容,假设固定比例 A:B:C = 3:3:2。 + + + + + ```yaml showLineNumbers + apiVersion: keda.sh/v1alpha1 + kind: ScaledObject + metadata: + name: b + spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: b + pollingInterval: 15 + minReplicaCount: 10 + maxReplicaCount: 1000 + triggers: + # highlight-start + - type: kubernetes-workload + metadata: + podSelector: 'app=a' # 选中 A 服务 + value: '1' # A/B=3/3=1 + # highlight-end + ``` + + + + + + ```yaml showLineNumbers + apiVersion: keda.sh/v1alpha1 + kind: ScaledObject + metadata: + name: c + spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: c + pollingInterval: 15 + minReplicaCount: 3 + maxReplicaCount: 340 + triggers: + # highlight-start + - type: kubernetes-workload + metadata: + podSelector: 'app=a' # 选中 A 服务 + value: '3' # A/C=3/2=1.5 + # highlight-end + ``` + + + + diff --git a/content/best-practices/sidebars.ts b/content/best-practices/sidebars.ts index 992dbfd..e7e1e9c 100644 --- a/content/best-practices/sidebars.ts +++ b/content/best-practices/sidebars.ts @@ -71,6 +71,21 @@ const sidebars: SidebarsConfig = { items: [ 'autoscaling/hpa-velocity', 'autoscaling/hpa-with-custom-metrics', + { + type: 'category', + label: '事件驱动弹性伸缩(KEDA)', + collapsed: true, + link: { + type: 'generated-index', + slug: '/autoscaling/keda' + }, + items: [ + 'autoscaling/keda/overview', + 'autoscaling/keda/install', + 'autoscaling/keda/cron', + 'autoscaling/keda/workload', + ] + } ], }, {