作者:馬偉,青云科技容器顧問,云原生愛好者,目前專注于云原生技術,云原生領域技術堆疊涉及 Kubernetes、KubeSphere、KubeKey 等,
2019 年,我在給很多企業部署虛擬化,介紹虛擬網路和虛擬存盤,
2023 年,這些企業都已經上了云原生了,對于高流量的 Web 應用程式,實時資料分析,大規模資料處理、移動應用程式等業務,容器比虛擬機更適合,因為它輕量級,快速回應,可輕松移植,并具有很強的彈性伸縮能力,
為什么需要彈性伸縮呢?
- 峰值負載應對:促銷活動、節假日購物季或突發事件根據需求快速擴展資源,保證應用可用性和性能,
- 提高資源利用率:根據實際資源負載動態調整資源規模,避免基礎設施資源浪費,降低 TCO,
- 應對故障和容錯:多實體部署和快速替換,提高業務連續性和可用性,
- 跟隨需求變化:匹配前端的業務需求及壓力,快速調整規模,提高事件應對能力,滿足需求和期望,
Horizontal Pod Autoscaling
Kubernetes 自身提供一種彈性伸縮的機制,包括 Vertical Pod Autoscaler (VPA)和 Horizontal Pod Autoscaler (HPA),HPA 根據 CPU 、記憶體利用率增加或減少副本控制器的 pod 數量,它是一個擴縮資源規模的功能特性,
HPA 依賴 Metrics-Server 捕獲 CPU、記憶體資料來提供資源使用測量資料,也可以根據自定義指標(如 Prometheus)進行擴縮,

由上圖看出,HPA 持續監控 Metrics-Server 的指標情況,然后計算所需的副本數動態調整資源副本,實作設定目標資源值的水平伸縮,
但也有一定局限性:
- 無外部指標支持,如不同的事件源,不同的中間件/應用程式等,業務端的應用程式變化及依賴是多樣的,不只是基于 CPU 和記憶體擴展,
- 無法 1->0,應用程式總有 0 負載的時候,此時不能不運行作業負載嗎?
所以就有了Kubernetes-based Event-Driven Autoscaling(KEDA)!
KEDA
KEDA 基于事件驅動進行自動伸縮,什么是事件驅動?我理解是對系統上的各種事件做出反應并采取相應行動(伸縮),那么 KEDA 就是一個 HPA+多種觸發器,只要觸發器收到某個事件被觸發,KEDA 就可以使用 HPA 進行自動伸縮了,并且,KEDA 可以 1-0,0-1!
架構

KEDA 自身有幾個組件:
- Agent: KEDA 激活和停止 Kubernetes 作業負載(keda-operator 主要功能)
- Metrics: KEDA 作為一個 Kubernetes 指標服務器,向 Horizontal Pod Autoscaler 提供豐富的事件資料,從源頭上消費事件,(keda-operator-metrics-apiserver 主要作用),
- Admission Webhooks: 自動驗證資源變化,以防止錯誤配置,
- Event sources: KEDA 更改 pod 數量的外部事件/觸發源,如 Prometheus、Kafka,
- Scalers: 監視事件源,獲取指標并根據事件觸發伸縮,
- Metrics adapter:從 Scalers 獲取指標并發送給 HPA,
- Controller: 根據 Adapter 提供的指標進行操作,調諧到 ScaledObject 中指定的資源狀態,Scaler 根據 ScaledObject 中設定的事件源持續監視事件,發生任何觸發事件時將指標傳遞給 Metrics Adapter,Metrics Adapter 調整指標并提供給 Controller 組件,Controller 根據 ScaledObject 中設定的縮放規則擴大或縮小 Deployment,
總的來說,KEDA 設定一個 ScaledObject,定義一個事件觸發器,可以是來自訊息佇列的訊息、主題訂閱的訊息、存盤佇列的訊息、事件網關的事件或自定義的觸發器,基于這些事件來自動調整應用程式的副本數量或處理程式的資源配置,以根據實際負載情況實作彈性伸縮,
CRD
- ScaledObjects:代表事件源(如 Rabbit MQ)和 Kubernetes, Deployment、StatefulSet 或任何定義 / 規模子資源的自定義資源之間的所需映射,
- ScaledJobs:事件源和 Kubernetes Jobs 之間的映射,根據事件觸發調整 Job 規模,
- TriggerAuthentications:觸發器的認證引數,
- ClusterTriggerAuthentications:集群維度認證,
部署 KEDA
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
kubectl create namespace keda
helm install keda kedacore/keda --namespace keda
kubectl apply -f https://github.com/kedacore/keda/releases/download/v2.10.1/keda-2.10.1.yaml
root@node-1:/# kubectl get all -n keda
NAME READY STATUS RESTARTS AGE
pod/keda-metrics-apiserver-7d89dbcb54-v22nl 1/1 Running 0 44s
pod/keda-operator-5bb9b49d7c-kh6wt 0/1 Running 0 44s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/keda-metrics-apiserver ClusterIP 10.233.44.19 <none> 443/TCP,80/TCP 45s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/keda-metrics-apiserver 1/1 1 1 45s
deployment.apps/keda-operator 0/1 1 0 45s
NAME DESIRED CURRENT READY AGE
replicaset.apps/keda-metrics-apiserver-7d89dbcb54 1 1 1 45s
replicaset.apps/keda-operator-5bb9b49d7c 1 1 0 45s
root@node-1:/# kubectl get all -n keda
NAME READY STATUS RESTARTS AGE
pod/keda-metrics-apiserver-7d89dbcb54-v22nl 1/1 Running 0 4m8s
pod/keda-operator-5bb9b49d7c-kh6wt 1/1 Running 0 4m8s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/keda-metrics-apiserver ClusterIP 10.233.44.19 <none> 443/TCP,80/TCP 4m9s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/keda-metrics-apiserver 1/1 1 1 4m9s
deployment.apps/keda-operator 1/1 1 1 4m9s
NAME DESIRED CURRENT READY AGE
replicaset.apps/keda-metrics-apiserver-7d89dbcb54 1 1 1 4m9s
replicaset.apps/keda-operator-5bb9b49d7c
# kubectl get crd | grep keda
clustertriggerauthentications.keda.sh 2023-05-11T09:26:06Z
scaledjobs.keda.sh 2023-05-11T09:26:07Z
scaledobjects.keda.sh 2023-05-11T09:26:07Z
triggerauthentications.keda.sh 2023-05-11T09:26:07Z
KubeSphere 部署 KEDA
kubectl edit cc -n kubesphere-system (kubesphere 3.4+)
spec:
···
autoscaling:
enabled: true
···
擴展作業負載 CRD
ScaledObject 資源定義,詳情引數請看 :https://keda.sh/docs/2.10/concepts/scaling-deployments/,
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: {scaled-object-name}
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}
查看 KEDA Mterics Server 暴露的指標
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1"
Demo
KEDA 目前支持 53 種 Scalers,如 Kafka,Elasticsearch,MySQL,RabbitMQ,Prometheus 等等,
此處演示一個 Prometheus 和 Kafka 的例子,
Prometheus & KEDA

部署一個 Web 應用,使用 Prometheus 監控 Web 應用 http 請求指標,
為尋求演示效果,此處部署了一個有點擊,互動的 Demo APP,地址如下:https://github.com/livewyer-ops/keda-demo/blob/v1.0.0/examples/keda/,
部署成功后通過 NodePort 訪問:

進入 KubeSphere 專案,新建一個自定義伸縮:

設定最小副本數為 1,最大副本數為 10,輪詢間隔 5 秒,等待時間為 1 分鐘:

KubeSphere 支持 Cron、Prometheus,和自定義觸發器:

觸發器設定 Prometheus,設定請求為 30s 內的增長率總和,當閾值大于 3 時事件驅動觸發縮放:

設定一些其他設定,如資源洗掉后是否恢復指本來的副本數,以及擴縮策略設定:


現在并發訪問 Web App:

可以在自定義監控看到監控指標的變化:

Web App 的副本數開始橫向擴展:

最終擴展到 ScaledObject 中定義的 10 個副本:

在訪問停止后,可以看到監控指標的數值在慢慢變小:

Deployment 開始縮容:

Kafka & KEDA
KEDA 使用 Kafka 事件源演示的整體拓撲如下:

Kafka 使用 Demo 代碼:https://github.com/ChamilaLiyanage/kafka-keda-example.git,
部署 Kafka
打開 KubeSphere 應用商店,查看 DMP 資料庫中心:

選擇 Kafka,進行安裝:




安裝好 Kafka 后,創建一個測驗的 Kafka Topic,Topic 磁區設定為 5,副本設定為 1:


創建 Kafka Producer 服務:


向主題發送訂單:


創建 Consumer 服務:


發送新訂單看 Consumer 服務是否消費:

現在可以來做自動伸縮了,創建一個 ScaledObject,設定最小副本數為 0,最大為 10,輪詢間隔為 5s,Kafka LagThreshold 為 10:
apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
name: kafka-scaledobject
namespace: default
labels:
deploymentName: kafka-consumer-deployment # Required Name of the deployment we want to scale.
spec:
scaleTargetRef:
deploymentName: kafka-consumer-deployment # Required Name of the deployment we want to scale.
pollingInterval: 5
minReplicaCount: 0 #Optional Default 0
maxReplicaCount: 10 #Optional Default 100
triggers:
- type: kafka
metadata:
# Required
BootstrapeServers: radondb-kafka-kafka-external-bootstrap.demo:9092 # Kafka bootstrap server host and port
consumerGroup: order-shipper # Make sure that this consumer group name is the same one as the one that is consuming topics
topic: test
lagThreshold: "10" # Optional. How much the stream is lagging on the current consumer group
創建自定義伸縮:







現在,讓我們向佇列提交大約 100,000 條訂單訊息,看看自動縮放的實際效果,你會看到隨著佇列中多余訊息的增長,將會產生更多的 kafka-consumer pod,

NAMESPACE NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
demo keda-hpa-kafka-consumer Deployment/kafka-consumer 5/10 (avg) 1 10 1 2m35s


此處我們看到最大到 5 個副本,沒有到 10 個副本,因為默認最大副本數不會超過 Kafka 主題磁區數量,上面設定了磁區為 5,可以激活 allowIdleConsumers: true 來禁用這個默認行為,
重新編輯自定義伸縮后,最大副本變化成 10:

在無訊息消費時,副本變化為 0:

結尾
到這里本篇就結束了,對此有需求或感興趣的小伙伴可以操練起來了,
本文由博客一文多發平臺 OpenWrite 發布!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/552844.html
標籤:其他
下一篇:返回列表
