一步一步教你如何擼 Dapr 之自動擴 - 縮容

  上一篇我們講到了 dapr 提供的 bindings,通過綁定可以讓我們的程序輕裝上陣,在極端情況下幾乎不需要集成任何 sdk,僅需要通過 httpclient+text.json 即可完成對外部組件的調用,這樣只需要對外暴露一個輕量級的 http 服務器提供 restapi 即可作爲一個雲函數提供對外服務。上一篇我們同時也提到了在 serverless 框架下的函數還可以按需進行自動擴容縮容的,在極端情況下甚至可以將實例縮容至 0,理想情況下 serverless 在無人訪問時不佔用系統除磁盤外的任何資源,當有訪問時通過自動化擴容快速啓動應用實例提供服務,當請求增多 / 減少時又相應的進行自動化擴容 / 縮容,當請求完全沒有時再次縮容到 0。那今天我們就看看我們如何通過 dapr+prometheus+keda 來實現一套自動化擴容縮容吧。

附錄:(如果你覺得對你有用,請給個 star)
一、電商 Demo 地址:https://github.com/sd797994/Oxygen-Dapr.EshopSample

二、通訊框架地址:https://github.com/sd797994/Oxygen-Dapr

  照例得先嘮嘮這個擴容縮容機制到底是如何實現的熟悉 k8sHPA 機制的同學請跳過,k8s 的 HPA(Horizontal Pod Autoscaler), 我們直接搬官方文檔定義吧:“Pod 水平自動擴縮(Horizontal Pod Autoscaler) 可以基於 CPU 利用率自動擴縮 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 數量。除了 CPU 利用率,也可以基於其他應程序提供的自定義度量指標 來執行自動擴縮。Pod 自動擴縮不適用於無法擴縮的對象,比如 DaemonSet。”,單靠 HPA 提供的 CPU/MEM 利用率來做自動擴縮容很難用於真實的生產環境,同時 HPA 只能作用於 1->N,N->1 的情況。而 serverless 需要涵蓋實例從 0->N,N->0 的情況,所以單靠 HPA 是無法滿足我們的訴求的。而這個時候就需要一款基於 HPA 擴展的 k8s 組件來爲我們提供相應的服務。而 Dapr 選擇微軟自家的 KEDA(已經開源並捐獻給了 CNCF 基金會)。注意 KEDA 並不是爲了覆蓋 HPA 的功能,而是作爲一個輕量化的組件集成在 k8s 裏爲 hpa 提供擴展服務。

  除了 keda,我們還需要一些指標,因爲 keda 需要某些指標來作爲其對 pod 的擴容和縮容的憑據,這部分指標目前恰好可以用 dapr 已經集成好的 prometheus 來提供。之前鏈路追蹤其實就是 dapr+zipkin,而指標同樣也可以通過 dapr+prometheus 來完成。關於指標這部分在 dapr 的官方文檔裏 monitoring 有詳細描述,使用起來和之前我們介紹的鏈路追蹤無太大差異,所以就不單開文章講解了,有訴求的同學可以直接訪問文檔來自行搭建。

  好了,接下來我們開始搭建,不過照例還是先上流程圖。注意此圖僅僅是簡易示例,真實的調用鏈會涉及更多的細節,此處不展開:

  首先我們需要將 prometheus 安裝進來,通過 Dapr 提供的指南,我們可以使用 helm 進行安裝。

kubectl create namespace dapr-monitoring
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install dapr-prom prometheus-community/prometheus -n dapr-monitoring

  tips: 由於一個詭異的 bug 導致在 windows 平臺下的 docker 環境內無法啓動 node-exporter,如果你不幸遇到了,可以使用這行代碼解決,具體的 issuse 在這裏

kubectl patch ds dapr-prom-prometheus-node-exporter  --type "json" -p '[{"op": "remove", "path" : "/spec/template/spec/containers/0/volumeMounts/2/mountPropagation"}]' -n dapr-monitoring

  檢查你的 dapr-monitoring,確保所有 pod 都能啓動,接着我們需要公開 prometheus-server 用於訪問頁面。通過 kubectl edit svc dapr-prom-prometheus-server -n dapr-monitoring 打開 svc 將 spec.service.type 從 ClusterIP 改爲 NodePort, 如果你需要固定端口,再增加 spec.ports.nodePort 即可。保存文檔後我們再查詢 kubectl get svc dapr-prom-prometheus-server -n dapr-monitoring 看看端口號是多少,然後訪問 loalhost:port,如果出現以下頁面,則說明 prometheus 部署成功:

  由於 dapr 會自動將指標寫入 prometheus,當我們操作一下我們的電商 demo 之後,我們就可以從 prometheus 查詢到對應指標的情況了,以 http 請求數的情況爲例:

  prometheus 先放一邊,接着我們安裝 KEDA,依然參考 dapr 的文檔,不過接下來我們和官方文檔有一點出入,官方文檔演示的是通過 component 讓 keda 監聽 kafka,通過流量指標來確定擴容 / 縮容訂閱器的。我們這裏的演示是讓 keda 監聽 prometheus 的特定指標 dapr_http_server_request_count 來實現擴容 / 縮的。原理都一樣,即藉助 keda 來實現。接下來依然是通過 helm 安裝 keda。

helm repo add kedacore https://kedacore.github.io/charts
helm repo update
kubectl create namespace keda
helm install keda kedacore/keda --namespace keda

  同樣安裝完畢後,觀察我們的 keda,確保兩個 pod 都已經正確 running 之後,我們嘗試對我們的網關配置 keda 的 ScaledObject 來實現自動擴容 / 縮容:首先還是編寫一個 ScaledObject,這是 keda 安裝後會自動在 k8s 裏申明的 CRD 資源符

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: prometheus-scaledobject
  namespace: dapreshop
spec:
  scaleTargetRef:
    name: apigateway
  pollingInterval: 15 #指定keda的採集頻次,單位秒
  minReplicaCount: 1  #指定默認規格
  maxReplicaCount: 10 #最大擴容規格
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://dapr-prom-prometheus-server.dapr-monitoring.svc.cluster.local   #prometheus服務的svc用於keda採集指標
      metricName: dapr_http_server_request_count  #具體的指標名
      query: sum(rate(dapr_http_server_request_count{app_id="apigateway"}[2m])) #這是prometheus特有的PromQL,這段query的意思是我們需要採集以2分鐘爲一個維度對網關的請求平均訪問速率,這裏不展開,大家可以搜PromQL中文文檔瞭解更多
      threshold: '3' #閾值

  當我們 apply 這個 yaml 之後,可以通過 kubectl get so,hpa 觀察我們的 scaleobject 和 hpa 的資源是否創建成功,一切 OK 後,我們通過 postman 的 runner 請求網關,看看 hpa 是否可以工作吧:

   可以看到請求過來後,我們的指標已經被正確的收集到了,接着我們查詢一下網關的情況,可以看到已經被正確的擴容了:

  當請求歸零後,過一段時間再次訪問會發現實例被縮容到了默認規格。這就是今天對 dapr+keda 實現動態擴容 / 縮容的介紹。當然要做到真正的雲函數那樣的從 0 實例快速冷啓動還需要一個過程,冷啓動在傳統雲商提供的雲函數環境裏是通過預熱池實現的,而本地化搭建要實現 0 實例冷啓動需要 AOT 的支持,至少就目前而言. netcore 尚未支持 AOT 編譯成本地代碼的情況下還很遙遠。但是不能說沒有實現 serverless 冷啓動做這個就沒有意義,當我們在特定場景比如做活動需要動態擴容 / 縮容時,完全可以通過 keda 去實現。當請求稀少的夜間我們完全就可以將實例縮容到 1 份繼續運行,或者類似於 dapr 官方文檔示例那樣的訂閱器平時不需要運行時完全可以縮容到 0 個實例,等待消息來觸發擴容運行消費。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Po9lxr9c3e_9gKsuxfpMyA