使用 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

您还可以下载该实用程序 Linux или Windows.

运行:

./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 的频道.

来源: habr.com

添加评论