使用 Prometheus 和 KEDA 自動縮放 Kubernetes 應用程序

使用 Prometheus 和 KEDA 自動縮放 Kubernetes 應用程序Cimuanos 的氣球人

可擴展性是雲端應用程式的關鍵要求。 使用 Kubernetes,擴展應用程式就像增加適當部署的副本數量或 ReplicaSet ——但這是一個手動過程。

Kubernetes 允許應用程式自動擴展(即部署中的 Pod 或 ReplicaSet)使用 Horizo​​ntal Pod Autoscaler 規範以聲明方式。 自動擴展的預設標準是CPU使用率指標(資源指標),但您可以整合自訂和外部提供的指標。

團隊 Mail.ru 的 Kubernetes aaS 翻譯了一篇關於如何使用外部指標自動擴展 Kubernetes 應用程式的文章。 為了展示一切是如何運作的,作者使用了 HTTP 存取請求指標,這些指標是使用 Prometheus 收集的。

使用開源 Kubernetes 運算子 Kubernetes 事件驅動自動縮放 (KEDA),而不是 Pod 的水平自動縮放。 它與 Horizo​​ntal Pod Autoscaler 原生集成,為事件驅動的工作負載提供無縫自動縮放(包括從零到零)。 代碼可在 GitHub上.

系統簡要概述

使用 Prometheus 和 KEDA 自動縮放 Kubernetes 應用程序

該圖顯示了一切如何運作的簡要描述:

  1. 該應用程式提供 Prometheus 格式的 HTTP 命中計數指標。
  2. Prometheus 配置為收集這些指標。
  3. KEDA 中的 Prometheus 縮放器配置為根據 HTTP 命中數自動縮放應用程式。

現在我將詳細告訴您每個要素。

科達與普羅米修斯

Prometheus是一個開源系統監控和警報工具包,部分 雲原生計算基金會。 從各種來源收集指標並將其儲存為時間序列資料。 要視覺化數據,您可以使用 格拉法納 或其他與 Kubernetes API 搭配使用的視覺化工具。

KEDA 支援縮放器的概念 - 它可作為 KEDA 和外部系統之間的橋樑。 縮放器實現特定於每個目標系統並從中提取資料。 然後 KEDA 使用它們來控制自動縮放。

Scalers支援多種資料來源,例如Kafka、Redis、Prometheus。 也就是說,KEDA 可用於使用 Prometheus 指標作為標準自動擴展 Kubernetes 部署。

測試應用

Golang 測試應用程式提供透過 HTTP 的存取並執行兩個重要功能:

  1. 使用 Prometheus Go 用戶端程式庫來偵測應用程式並提供 http_requests 指標,其中包含點擊計數。 Prometheus 指標可用的端點位於 URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. 回應請求 GET 應用程式增加鍵的值(access_count)在Redis中。 這是作為 HTTP 處理程序的一部分完成工作並檢查 Prometheus 指標的簡單方法。 指標值必須與值相同 access_count 在Redis中。
    func main() {
           http.Handle("/metrics", promhttp.Handler())
           http.HandleFunc("/test", func(w http.ResponseWriter, r 
    *http.Request) {
               defer httpRequestsCounter.Inc()
               count, err := client.Incr(redisCounterName).Result()
               if err != nil {
                   fmt.Println("Unable to increment redis counter", err)
                   os.Exit(1)
               }
               resp := "Accessed on " + time.Now().String() + "nAccess count " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    

該應用程式透過以下方式部署到 Kubernetes Deployment。 也創建了一個服務 ClusterIP,它允許Prometheus伺服器獲取應用程式指標。

這裡 應用程式的部署清單.

普羅米修斯伺服器

Prometheus 部署清單包括:

  • ConfigMap — 傳輸 Prometheus 配置;
  • Deployment — 用於在 Kubernetes 叢集中部署 Prometheus;
  • ClusterIP — 存取 UI Prometheus 的服務;
  • ClusterRole, ClusterRoleBinding и ServiceAccount — 用於自動偵測 Kubernetes 中的服務(自動發現)。

這裡 運行 Prometheus 的清單.

科達 Prometheus ScaledObject

縮放器充當 KEDA 和需要從中獲取指標的外部系統之間的橋樑。 ScaledObject 是需要部署的自訂資源,以將部署與事件來源(在本例中為 Prometheus)同步。

ScaledObject 包含部署擴充資訊、事件來源元資料(例如連線機密、佇列名稱)、輪詢間隔、復原週期和其他資料。 它會產生相應的自動擴展資源(HPA 定義)來擴展部署。

當一個物體 ScaledObject 刪除後,對應的HPA定義被清除。

這是定義 ScaledObject 對於我們的範例,它使用縮放器 Prometheus:

apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
 name: prometheus-scaledobject
 namespace: default
 labels:
   deploymentName: go-prom-app
spec:
 scaleTargetRef:
   deploymentName: go-prom-app
 pollingInterval: 15
 cooldownPeriod:  30
 minReplicaCount: 1
 maxReplicaCount: 10
 triggers:
 - type: prometheus
   metadata:
     serverAddress: 
http://prometheus-service.default.svc.cluster.local:9090
     metricName: access_frequency
     threshold: '3'
     query: sum(rate(http_requests[2m]))

請考慮以下幾點:

  1. 他指 Deployment 有名字 go-prom-app.
  2. 觸發類型 - Prometheus。 Prometheus 伺服器位址以及指標名稱、閾值和 PromQL 查詢,這將被使用。 PromQL 查詢 - sum(rate(http_requests[2m])).
  3. 根據 pollingInterval,KEDA 每十五秒向 Prometheus 請求一個目標。 至少一項 (minReplicaCount),且最大 pod 數量不超過 maxReplicaCount (在本例中為十)。

可以安裝 minReplicaCount 等於零。 在這種情況下,KEDA 會啟動零到一的部署,然後公開 HPA 以進行進一步的自動擴展。 相反的順序也是可能的,即從一縮放到零。 在範例中,我們沒有選擇零,因為這是一個 HTTP 服務而不是按需系統。

自動縮放的魔力

此閾值用作擴展部署的觸發器。 在我們的範例中,PromQL 查詢 sum(rate (http_requests [2m])) 傳回過去兩分鐘內測量的聚合 HTTP 請求率(每秒請求數)。

由於閾值為 XNUMX,這表示當該值小於 XNUMX 時,就會出現 XNUMX sum(rate (http_requests [2m])) 少於三個。 如果該值增加,則每次都會增加一個額外的 sub sum(rate (http_requests [2m])) 增加三。 例如,如果該值為 12 到 14,則 Pod 數量為 XNUMX。

現在讓我們嘗試設定它!

預設

您只需要一個 Kubernetes 叢集和一個配置好的實用程式 kubectl。 本例使用集群 minikube,但您可以選擇任何其他的。 要安裝集群,有 領導.

在 Mac 上安裝最新版本:

curl -Lo minikube 
https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 
&& chmod +x minikube
sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/

Kubectl存取 Kubernetes 叢集。

在 Mac 上安裝最新版本:

curl -LO 
"https://storage.googleapis.com/kubernetes-release/release/$(curl -s
https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl version

科達安裝

您可以透過多種方式部署 KEDA,它們列於 文件。 我正在使用整體 YAML:

kubectl apply -f
https://raw.githubusercontent.com/kedacore/keda/master/deploy/KedaScaleController.yaml

KEDA 及其元件安裝到命名空間中 keda。 檢查命令:

kubectl get pods -n keda

等待 KEDA Operator 啟動並進入 Running State。 之後,繼續。

使用 Helm 安裝 Redis

如果您沒有安裝Helm,請使用這個 領導。 Mac 上安裝指令:

brew install kubernetes-helm
helm init --history-max 200

helm init 初始化本機命令列介面並安裝 Tiller 到 Kubernetes 叢集。

kubectl get pods -n kube-system | grep tiller

等待 Tiller Pod 進入 Running 狀態。

譯者註:作者使用Helm@2,需要安裝Tiller伺服器元件。 現在 Helm@3 是相關的,它不需要伺服器部分。

安裝 Helm 後,一條指令足以啟動 Redis:

helm install --name redis-server --set cluster.enabled=false --set 
usePassword=false stable/redis

驗證Redis是否啟動成功:

kubectl get pods/redis-server-master-0

等待Redis進入狀態 Running.

應用程式部署

部署命令:

kubectl apply -f go-app.yaml

//output
deployment.apps/go-prom-app created
service/go-prom-app-service created

檢查一切是否已開始:

kubectl get pods -l=app=go-prom-app

等待Redis進入狀態 Running.

部署普羅米修斯伺服器

Prometheus 清單使用 Prometheus 的 Kubernetes 服務發現。 它允許根據服務標籤動態發現應用程式 Pod。

kubernetes_sd_configs:
   - role: service
   relabel_configs:
   - source_labels: [__meta_kubernetes_service_label_run]
     regex: go-prom-app-service
     action: keep

部署:

kubectl apply -f prometheus.yaml

//output
clusterrole.rbac.authorization.k8s.io/prometheus created
serviceaccount/default configured
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
configmap/prom-conf created
deployment.extensions/prometheus-deployment created
service/prometheus-service created

檢查一切是否已開始:

kubectl get pods -l=app=prometheus-server

等待Prometheus進入狀態 Running.

使用 kubectl port-forward 存取 Prometheus 使用者介面(或 API 伺服器) http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

部署 KEDA 自動縮放配置

創建命令 ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

檢查KEDA操作員日誌:

KEDA_POD_NAME=$(kubectl get pods -n keda 
-o=jsonpath='{.items[0].metadata.name}')
kubectl logs $KEDA_POD_NAME -n keda

結果看起來像這樣:

time="2019-10-15T09:38:28Z" level=info msg="Watching ScaledObject:
default/prometheus-scaledobject"
time="2019-10-15T09:38:28Z" level=info msg="Created HPA with 
namespace default and name keda-hpa-go-prom-app"

檢查應用程式下。 一個實例必須正在運行,因為 minReplicaCount 等於 1:

kubectl get pods -l=app=go-prom-app

驗證 HPA 資源是否已成功建立:

kubectl get hpa

您應該會看到類似以下內容:

NAME                   REFERENCE                TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (avg)   1         10        1          45s

健康檢查:應用程式訪問

若要存取我們應用程式的 REST 端點,請執行:

kubectl port-forward service/go-prom-app-service 8080

現在您可以使用該地址存取您的 Go 應用程式 http://localhost:8080。 為此,請運行命令:

curl http://localhost:8080/test

結果看起來像這樣:

Accessed on 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Access count 1

此時還要檢查Redis。 你會看到關鍵 access_count 增加到1:

kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
"1"

確保度量值是 http_requests 相同:

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 1

負載創建

我們將使用 — 用於產生負載的實用程式:

curl -o hey https://storage.googleapis.com/hey-release/hey_darwin_amd64 
&& chmod a+x hey

您也可以下載該實用程式 LinuxWindows.

運行:

./hey http://localhost:8080/test

預設情況下,該實用程式會發送 200 個請求。 您可以使用 Prometheus 指標和 Redis 來驗證這一點。

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 201
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
201

驗證實際指標的值(由 PromQL 查詢傳回):

curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'
//output
{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1571734214.228,"1.686057971014493"]}]}}

在這種情況下,實際結果是 1,686057971014493 並顯示在字段中 value。 這對於縮放來說是不夠的,因為我們設定的閾值是 3。

更多負載!

在新終端機中,監控應用程式 pod 的數量:

kubectl get pods -l=app=go-prom-app -w

讓我們使用以下命令增加負載:

./hey -n 2000 http://localhost:8080/test

一段時間後,您將看到 HPA 擴充部署並啟動新的 Pod。 檢查您的 HPA 以確保:

kubectl get hpa
NAME                   REFERENCE                TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (avg)   1         10        6          4m22s

如果負載不一致,部署就會減少到只有一個 pod 運作。 如果您想檢查實際指標(由 PromQL 查詢傳回),請使用下列命令:

curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'

清潔的

//Delete KEDA
kubectl delete namespace keda
//Delete the app, Prometheus server and KEDA scaled object
kubectl delete -f .
//Delete Redis
helm del --purge redis-server

結論

KEDA 可讓您根據外部指標的資料自動擴展 Kubernetes 部署(從零到零)。 例如,基於 Prometheus 指標、Redis 中的佇列長度、Kafka 主題中的消費者延遲。

KEDA 與外部來源集成,也透過 Metrics Server 向 Horizo​​ntal Pod Autoscaler 提供其指標。

祝你好運!

還有什麼要讀的:

  1. 在生產環境中運行容器和 Kubernetes 的最佳實踐和最佳實踐.
  2. 90 多種 Kubernetes 有用工具:部署、管理、監控、安全等.
  3. 我們在 Telegram 中圍繞 Kubernetes 的頻道.

來源: www.habr.com

添加評論