基于事件驅(qū)動的自動伸縮工具 KEDA 簡單使用
KEDA 是 Kubernetes 基于事件驅(qū)動的自動伸縮工具,通過 KEDA 我們可以根據(jù)需要處理的事件數(shù)量來驅(qū)動 Kubernetes 中任何容器的擴展。KEDA 可以直接部署到任何 Kubernetes 集群中和標(biāo)準(zhǔn)的組件一起工作。
在 Kubernetes 中 KEDA 有兩個關(guān)鍵的角色:
擴展客戶端:用于激活和停用 Deployments 來擴展到配置的副本,并在沒有事件的情況下將副本縮減回零。 Metrics Server:一種 Metrics 指標(biāo)服務(wù),暴露了大量與事件相關(guān)的數(shù)據(jù),例如隊列長度,允許基于事件的擴展,消耗特定類型的事件數(shù)據(jù)。
Metrics Server 與 HPA 進(jìn)行通信,以驅(qū)動 Kubernetes 部署副本的擴展。然后由 Deployments 直接從源頭消費事件。這樣可以保留豐富的事件集成,讓完成或丟棄隊列消息之類的可以立即使用。Metrics Server 是安裝 KEDA 時運行的 keda-operator-metrics-apiserver 容器的主要作用。
KEDA 有廣泛的擴展器,既可以檢測部署是否應(yīng)該被激活或停用,也可以為特定事件源提供自定義指標(biāo)。
當(dāng)我們安裝 KEDA 后,它會創(chuàng)建3個 CRD 資源,這些 CRD 可以使你能夠?qū)⑹录矗ㄒ约皩υ撌录吹恼J(rèn)證)映射到 Deployment、StatefulSet、自定義資源或 Job 上進(jìn)行縮放。
scaledobjects.keda.sh:ScaledObjects表示事件源(例如 RabbitMQ)與 Kubernetes Deployment、StatefulSet 或定義/scale子資源的任何自定義資源之間的所需映射。scaledjobs.keda.sh:ScaledJobs表示事件源和 Kubernetes Job 之間的映射。triggerauthentications.keda.sh:ScaledObject/ScaledJob也可以引用TriggerAuthentication,其中包含了監(jiān)控事件源的認(rèn)證配置或 Secret。
安裝
安裝 KEDA 有很多方式,這里我們直接使用 Helm 來進(jìn)行安裝,首先添加對應(yīng)的 Helm 倉庫:
??helm?repo?add?kedacore?https://kedacore.github.io/charts
??helm?repo?update
然后直接使用下面的命令安裝即可:
??kubectl?create?namespace?keda
??helm?install?keda?kedacore/keda?--namespace?keda
NAME:?keda
LAST?DEPLOYED:?Wed?Dec?23?11:45:02?2020
NAMESPACE:?keda
STATUS:?deployed
REVISION:?1
TEST?SUITE:?None
安裝完成后在 keda 命名空間下面會運行兩個 KEDA 相關(guān)的 Pod:
??kubectl?get?pods?-n?keda
NAME???????????????????????????????????????????????READY???STATUS????RESTARTS???AGE
keda-operator-8488964969-d4svr?????????????????????1/1?????Running???0??????????14m
keda-operator-metrics-apiserver-5b488bc7f6-zrzzm???1/1?????Running???0??????????14m
簡單示例
這里我們使用一個簡單的 golang 結(jié)合 rabbitmq 的示例進(jìn)行演示,該示例應(yīng)用將接收來自 RabbitMQ 隊列的消息并通過 KEDA 進(jìn)行擴展。接收方一次(每個實例)將收到一條消息,并 sleep 1秒鐘以模擬執(zhí)行工作,當(dāng)添加大量隊列消息時,KEDA 將驅(qū)動容器根據(jù)事件源(RabbitMQ)進(jìn)行擴展。
首先我們需要在 Kubernetes 集群上部署 RabbitMQ 隊列,同樣我們使用 Helm 來快速安裝:
??helm?repo?add?bitnami?https://charts.bitnami.com/bitnami
??helm?repo?update
??helm?install?rabbitmq?--set?auth.username=user?--set?auth.password=PASSWORD,persistence.enabled=false?bitnami/rabbitmq
??kubectl?get?pods
NAME?????????????????????????READY???STATUS????RESTARTS???AGE
rabbitmq-0???????????????????1/1?????Running???0??????????7m52s
......
“注意:對于 RabbitMQ Helm Chart 版本 6.xx 或更早版本,應(yīng)使用
”Rabbitmq.username和 rabbitmq.password` 參數(shù)指定用戶名和密碼。
安裝完成后 Clone 示例項目:
??git?clone?https://github.com/cnych/sample-go-rabbitmq.git
??cd?sample-go-rabbitmq
首先我們部署一個 consumer:
??kubectl?apply?-f?deploy/deploy-consumer.yaml
secret/rabbitmq-consumer-secret?created
deployment.apps/rabbitmq-consumer?created
scaledobject.keda.sh/rabbitmq-consumer?created
triggerauthentication.keda.sh/rabbitmq-consumer-trigger?created
其中最主要的就是 ScaledObject 這個 CRD 對象的定義:
apiVersion:?keda.sh/v1alpha1
kind:?ScaledObject
metadata:
??name:?rabbitmq-consumer
??namespace:?default
spec:
??scaleTargetRef:??#?scale?的目標(biāo)引用
????name:?rabbitmq-consumer
??pollingInterval:?5?#?可選.?默認(rèn):?30?seconds
??cooldownPeriod:?30?#?可選.?默認(rèn):?300?seconds
??maxReplicaCount:?30?#?可選.?默認(rèn):?100
??triggers:
??-?type:?rabbitmq??#?基于?rabbitmq?進(jìn)行伸縮
????metadata:
??????queueName:?hello???#?監(jiān)聽的隊列名
??????queueLength:?"5"
????authenticationRef:
??????name:?rabbitmq-consumer-trigger
---
apiVersion:?keda.sh/v1alpha1
kind:?TriggerAuthentication
metadata:
??name:?rabbitmq-consumer-trigger
??namespace:?default
spec:
??secretTargetRef:
????-?parameter:?host
??????name:?rabbitmq-consumer-secret
??????key:?RabbitMqHost
這個消費者被設(shè)置為每個實例消耗一條消息,sleep 1秒,然后確認(rèn)消息的完成。上面的 ScaledObject 被設(shè)置為在無事件的情況下最小可擴展到0個副本,最大可擴展到30個副本(優(yōu)化為每個副本5條消息的隊列長度)。在30秒的無事件后,副本將被縮減(冷卻期)。這些設(shè)置可以根據(jù)需要在 ScaledObject 上進(jìn)行更改。
上面的消費者部署完成后可以看到現(xiàn)在是0個副本,這是因為現(xiàn)在沒有任何事件產(chǎn)生,所以最小縮放到0個副本:
??kubectl?get?deploy?rabbitmq-consumer
NAME????????????????READY???UP-TO-DATE???AVAILABLE???AGE
rabbitmq-consumer???0/0?????0????????????0???????????27s
??kubectl?get?rs
NAME???????????????????????????DESIRED???CURRENT???READY???AGE
rabbitmq-consumer-5c486c869c???0?????????0?????????0???????52s
??kubectl?describe?rs?rabbitmq-consumer-5c486c869c
Name:???????????rabbitmq-consumer-5c486c869c
Namespace:??????default
Selector:???????app=rabbitmq-consumer,pod-template-hash=5c486c869c
......
Events:
??Type????Reason????????????Age???From???????????????????Message
??----????------????????????----??----???????????????????-------
??Normal??SuccessfulCreate??88s???replicaset-controller??Created?pod:?rabbitmq-consumer-5c486c869c-xnx47
??Normal??SuccessfulDelete??87s???replicaset-controller??Deleted?pod:?rabbitmq-consumer-5c486c869c-xnx47
然后接下來我們部署生產(chǎn)者來產(chǎn)生消息:
??kubectl?apply?-f?deploy/deploy-publisher-job.yaml
job.batch/rabbitmq-publish?created
上面的 Job 任務(wù)會向正在監(jiān)聽 RabbitMQ 的 "hello" 隊列發(fā)布300條消息,隨著隊列的建立,KEDA 將進(jìn)行自動水平伸縮,直到隊列在大約 2 分鐘后耗盡,并發(fā) Pod 最多 30 個。我們可以通過下面的命令來觀察消費者的變化:
??kubectl?get?deploy?-w
NAME????????????????READY???UP-TO-DATE???AVAILABLE???AGE
rabbitmq-consumer???6/30????30???????????6???????????7m6s
我們也可以看到 Pods 在開始擴容處理隊列消息了。隨著消息長度的不斷增加,更多的 Pods 將被主動創(chuàng)建出來。同樣這個時候我們也可以查看 HPA 資源對象的變化:
??kubectl?get?hpa
NAME?????????????????????????REFERENCE??????????????????????TARGETS?????????????MINPODS???MAXPODS???REPLICAS???AGE
keda-hpa-rabbitmq-consumer???Deployment/rabbitmq-consumer???/5?(avg)???1?????????30????????0??????????8m23s
??kubectl?describe?hpa?keda-hpa-rabbitmq-consumer
Name:???????????????????????????????????????keda-hpa-rabbitmq-consumer
Namespace:??????????????????????????????????default
......
Conditions:
??Type????????????Status??Reason?????????????Message
??----????????????------??------?????????????-------
??AbleToScale?????True????SucceededGetScale??the?HPA?controller?was?able?to?get?the?target's?current?scale
??ScalingActive???False???ScalingDisabled????scaling?is?disabled?since?the?replica?count?of?the?target?is?zero
??ScalingLimited??True????TooManyReplicas????the?desired?replica?count?is?more?than?the?maximum?replica?count
Events:
??Type?????Reason?????????????Age????From???????????????????????Message
??----?????------?????????????----???----???????????????????????-------
??Warning??FailedRescale??????3m47s??horizontal-pod-autoscaler??New?size:?4;?reason:?external?metric?rabbitmq-hello(&LabelSelector{MatchLabels:map[string]string{scaledObjectName:?rabbitmq-consumer,},MatchExpressions:[]LabelSelectorRequirement{},})?above?target;?error:?Operation?cannot?be?fulfilled?on?deployments.apps?"rabbitmq-consumer":?the?object?has?been?modified;?please?apply?your?changes?to?the?latest?version?and?try?again
??Normal???SuccessfulRescale??3m30s??horizontal-pod-autoscaler??New?size:?4;?reason:?external?metric?rabbitmq-hello(&LabelSelector{MatchLabels:map[string]string{scaledObjectName:?rabbitmq-consumer,},MatchExpressions:[]LabelSelectorRequirement{},})?above?target
??Normal???SuccessfulRescale??3m15s??horizontal-pod-autoscaler??New?size:?8;?reason:?external?metric?rabbitmq-hello(&LabelSelector{MatchLabels:map[string]string{scaledObjectName:?rabbitmq-consumer,},MatchExpressions:[]LabelSelectorRequirement{},})?above?target
??Normal???SuccessfulRescale??2m58s??horizontal-pod-autoscaler??New?size:?16;?reason:?external?metric?rabbitmq-hello(&LabelSelector{MatchLabels:map[string]string{scaledObjectName:?rabbitmq-consumer,},MatchExpressions:[]LabelSelectorRequirement{},})?above?target
??Normal???SuccessfulRescale??2m43s??horizontal-pod-autoscaler??New?size:?30;?reason:?external?metric?rabbitmq-hello(&LabelSelector{MatchLabels:map[string]string{scaledObjectName:?rabbitmq-consumer,},MatchExpressions:[]LabelSelectorRequirement{},})?above?target
在隊列清空和指定的冷卻期(ScaledObject 的一個屬性,默認(rèn)為300秒)后,最后一個副本將縮減為零。通過查看 HPA 的事件也可以清楚地看到縮放的過程。
?點擊屏末?|?閱讀原文?|?即刻學(xué)習(xí)

