使用Prometheus和KEDA自动缩放Kubernetes应用程序

Cimuanos的Balloon Man



可伸缩性是云应用程序的关键要求。使用Kubernetes,扩展应用程序就像增加适当部署的副本数一样容易,或者ReplicaSet-但这是手动过程。



Kubernetes允许应用程序ReplicaSet使用Horizo​​ntal Pod Autoscaler规范以声明的方式自动缩放(即部署中的Pod)。自动缩放的默认标准是CPU使用率指标(资源指标),但是可以集成自定义指标和外部提供的指标。 Mail.ru的Kubernetes aaS



团队翻译了一篇有关如何使用外部指标自动缩放Kubernetes应用程序的文章。为了显示一切工作原理,作者使用HTTP访问请求指标,这些指标是使用Prometheus收集的。



Kubernetes Event Driven Autoscaling(KEDA)并不是开源的水平Pod,而是开源的Kubernetes运营商。它与Horizo​​ntal Pod Autoscaler本机集成,可为事件驱动的工作负载提供平滑的自动缩放(包括从零到零)。该代码可在GitHub上获得



系统操作简介







该图简要描述了所有工作原理:



  1. 该应用程序以Prometheus格式提供HTTP请求数量的度量。
  2. Prometheus已设置为收集这些指标。
  3. KEDA中的Prometheus缩放器配置为根据HTTP请求的数量自动缩放应用程序。


现在,我将详细介绍每个元素。



科达和普罗米修斯



Prometheus是一个开源系统监视和警报工具包,属于Cloud Native Computing Foundation从各种来源收集指标并将其另存为时间序列数据。要可视化数据,可以使用Grafana或其他与Kubernetes API配合使用的可视化工具。



KEDA支持定标器概念-它充当KEDA与外部系统之间的桥梁。定标器实现特定于每个目标系统,并从中提取数据。然后,KEDA使用它们来控制自动缩放。



定标器支持多个数据源,例如Kafka,Redis和Prometheus。也就是说,可以使用KEDA以Prometheus指标为标准来自动扩展Kubernetes部署。



测试申请



Golang测试应用程序提供HTTP访问并具有两个重要功能:



  1. 使用Prometheus Go客户端库来检测应用程序并提供包含命中计数器的http_requests指标。普罗米修斯度量标准可用的端点通过URI定位/metrics



    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. 响应该请求,GET应用程序增加access_countRedis中的key(这是完成作为HTTP处理程序一部分的工作并检查Prometheus指标的简便方法。指标值必须与access_countRedis中的值相同



    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服务器



Prometheus部署清单包括:



  • ConfigMap -传输Prometheus配置;
  • Deployment -在Kubernetes集群中部署P​​rometheus;
  • ClusterIP -用于访问UI Prometheus的服务;
  • ClusterRoleClusterRoleBinding以及ServiceAccount-用于在Kubernetes中自动检测服务(自动发现)。


这是运行Prometheus清单



KEDA普罗米修斯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. 根据pollingIntervalKEDA的说法,它每隔15秒就从Prometheus请求一个目标。支持至少一个pod(minReplicaCount),并且pod的最大数量不超过maxReplicaCount(在本示例中为10个)。


可以设置minReplicaCount为零。在这种情况下,KEDA将激活零对一部署,然后提供HPA进行进一步的自动扩展。相反的顺序也是可能的,即从1缩放到0。在该示例中,我们没有选择零,因为这是HTTP服务而不是按需系统。



自动缩放的魔力



该阈值用作触发扩展部署的触发器。在我们的示例中,PromQL查询sum(rate (http_requests [2m]))返回在最近两分钟内测得的HTTP请求速率的汇总值(每秒请求数)。



由于阈值是3,因此只要该值sum(rate (http_requests [2m]))小于3,就会存在1以下。如果该值增加,则每sum(rate (http_requests [2m]))增加3就会添加一个额外的底数。例如,如果该值为12到14,则吊舱数为4。



现在让我们尝试配置!



预置位



您只需要一个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



您可以通过多种方式部署KEDA,它们在文档中列出我正在使用整体式YAML:



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


KEDA及其组件安装在名称空间中keda检查命令:



kubectl get pods -n keda


等待,当在KEDA下操作员启动时,转到Running State然后继续。



使用Helm安装Redis



如果您尚未安装Helm,请使用本教程在Mac上安装的命令:



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


helm init初始化本地CLI并安装Tiller到Kubernetes集群中。



kubectl get pods -n kube-system | grep tiller


等待分iller荚进入运行状态。



译者注:作者使用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清单使用Prometheus的Kubernetes服务发现它使您可以基于服务标签动态发现应用程序容器。



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


等待普罗米修斯进入状态Running



使用kubectl port-forward在访问普罗米修斯用户界面(API或服务器)的http://本地主机: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


您现在可以使用地址http:// localhost:8080访问Go应用为此,请运行以下命令:



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


负载创建



我们将使用hey实用程序生成负载:



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。



更多的负荷!



在新终端中,跟踪应用程序容器的数量:



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


如果负载不是恒定的,则部署将减少到只有一个吊舱工作的地步。如果要检查实际指标(由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. 适用于Kubernetes的90多种有用工具:部署,管理,监视,安全性等
  3. 我们在Telegram中围绕Kubernetes的频道



All Articles