可伸缩性是云原生应用程序的关键要求。使用Kubernetes,扩展应用程序就像增加相应Deployment或ReplicaSet的副本数一样简单-但这是一个手动过程。 Kubernetes使得可以使用Horizontal Pod Autoscaler规范以声明的方式自动缩放应用程序(即Deployment或ReplicaSet中的Pod)。默认情况下,支持使用CPU利用率(资源指标)作为自动缩放的条件,但是也可以集成自定义指标和外部提供的指标。
该博客将演示如何使用外部指标自动缩放Kubernetes应用程序。例如,我们将使用通过Prometheus公开的HTTP访问请求指标。与其直接使用Horizontal Pod Autoscaler,我们将利用Kubernetes Event Driven Autoscaling aka KEDA-一种开源Kubernetes运算符,它与Horizontal Pod Autoscaler本机集成在一起,可为事件驱动的工作负载提供细粒度的autoscaling(包括从零到零的自动缩放)。
该代码可在GitHub上获得
总览
这是端到端工作方式的摘要-本节将详细讨论其中的每一项
https://res.cloudinary.com/practicaldev/image/fetch/s–gYKsLRyr–/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/tir8k2lrgjldxktf30ie.jpg
该应用程序以Prometheus格式公开HTTP访问计数指标
Prometheus配置为抓取这些指标
KEDA中的Prometheus缩放器已配置并部署为基于HTTP访问计数指标自动缩放应用程序
科达和普罗米修斯
Prometheus是一个开源系统监视和警报工具包,它是Cloud Native Computing Foundation的一部分。 Prometheus从各种来源抓取指标并将其存储为时间序列数据,并且可以使用Grafana等工具或其他API使用者来可视化所收集的数据。
KEDA支持缩放器的概念,它是KEDA与外部系统之间的桥梁。 Scaler实现特定于目标系统,并从目标系统中获取相关数据,然后由KEDA用来帮助驱动自动扩展。支持包括Prometheus在内的多个缩放器(包括Kafka,Redis等)。这意味着您可以使用Prometheus指标作为标准来利用KEDA自动扩展Kubernetes部署。
样品申请
Golang应用示例展示了一个HTTP端点,并做了两件重要的事情:
使用Prometheus Go客户端库对应用进行检测,并公开由Counter支持的http_requests指标。 Prometheus度量标准端点可从/ metrics获得。
1 2 3 4 |
var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{ Name: "http_requests", Help: "number of http requests", }) |
作为对GET请求的响应,它还增加了Redis中的密钥(access_count)-这是一种完成某些“工作”作为HTTP处理程序一部分的简单方法,并且还有助于验证Prometheus指标(应该相同 作为Redis中access_count的值)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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) } |
该应用程序作为Deployment部署到Kubernetes,并且还创建了ClusterIP服务以允许Prometheus服务器抓取app / metrics端点。
Prometheus服务器
Prometheus部署清单包括:
ConfigMap捕获Prometheus配置
Prometheus服务器本身的部署
ClusterIP服务访问Prometheus UI
使用ClusterRole,ClusterRoleBinding和ServiceAccount允许Kubernetes服务发现起作用
KEDA普罗米修斯ScaledObject
如前所述,Scaler实现充当KEDA与需要从中获取指标的外部系统之间的桥梁。 ScaledObject是一个自定义资源,需要部署该资源才能将Deployment与事件源(在这种情况下为Prometheus)同步。 它包含有关要扩展的Deployment,事件源上的元数据(例如,连接字符串密钥,队列名称),轮询间隔,冷却时间等信息。ScaledObject将产生相应的自动扩展资源(HPA定义)以扩展Deployment
删除ScaledObject时,将清除相应的HPA定义。
这是使用Prometheus缩放器的示例的ScaledObject定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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])) |
请注意以下几点:
它针对名为go-prom-app的部署
触发类型为prometheus。提到了Prometheus serverAddress以及要使用的metricName,阈值和PromQL查询(sum(rate(http_requests [2m])))
根据pollingInterval,KEDA将每隔15秒轮询一次Prometheus目标。最少维护一个Pod(minReplicaCount),最大Pod数量不超过maxReplicaCount(在此示例中为10)
可以将minReplicaCount设置为零。在这种情况下,KEDA会将部署从零“激活”到一个部署,然后将其留给HPA进一步自动扩展(反之亦然,即从一扩展为零)。我们没有选择零,因为这是HTTP服务,而不是按需系统,例如消息队列/主题使用者
自动缩放背后的魔力
阈值计数用作触发扩展部署的触发器。在此示例中,PromQL查询sum(rate(http_requests [2m]))返回最近2分钟内测量的HTTP请求每秒速率的聚合值。由于阈值计数为3,因此如果sum(rate(http_requests [2m]))的值小于3,则将有一个Pod。如果上升,则总和(rate(http_requests [2m]))每增加3例如如果值介于12到14之间,则Pod的数量将为4
好了,是时候动手尝试了!
先决条件
您只需要一个Kubernetes集群和Kubectl
Kubernetes集群-此示例使用minikube,但可以随意使用其他任何库。您可以使用本指南进行安装。
要在Mac上安装最新版本:
1 2 3 4 |
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上安装最新版本:
1 2 3 4 |
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来完成工作
1 |
kubectl apply -f https://raw.githubusercontent.com/kedacore/keda/master/deploy/KedaScaleController.yaml |
KEDA及其组件安装在keda名称空间中
确认:
1 |
kubectl get pods -n keda |
在继续之前,请等待KEDA操作员Pod启动(运行状态)
使用helm设置Redis
如果您没有安装头盔,只需使用本指南。 在Mac上,您可以使用以下方法快速完成此操作
1 2 |
brew install kubernetes-helm helm init --history-max 200 |
helm init是初始化本地CLI并将Tiller安装到Kubernetes集群中
1 |
kubectl get pods -n kube-system | grep tiller |
等待分tiller pod换到运行状态
设置了一个Helm,获取Redis服务器就像运行一样简单:
1 |
helm install --name redis-server --set cluster.enabled=false --set usePassword=false stable/redis |
确认redis状态:
1 |
kubectl get pods/redis-server-master-0 |
等待Redis服务器Pod启动(运行状态),然后继续
部署应用:
1 2 3 4 5 6 7 |
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 |
部署Prometheus服务器
Prometheus清单使用Kubernetes Service Discovery for Prometheus来基于服务标签动态检测应用程序Pod
1 2 3 4 5 6 |
kubernetes_sd_configs: - role: service relabel_configs: - source_labels: [__meta_kubernetes_service_label_run] regex: go-prom-app-service action: keep |
部署:
1 2 3 4 5 6 7 8 9 |
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 |
1 |
kubectl get pods -l=app=prometheus-server |
使用kubectl port-forward访问Prometheus UI-您将能够通过以下地址访问Prometheus UI(或API服务器):http:// localhost:9090
1 |
kubectl port-forward service/prometheus-service 9090 |
部署KEDA自动缩放配置
您需要创建ScaledObject
1 2 3 4 5 6 7 |
kubectl apply -f keda-prometheus-scaledobject.yaml #Check KEDA operator logs 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" |
检查应用程序Pod-自minReplicaCount为1起,应该运行一个实例
1 |
kubectl get pods -l=app=go-prom-app |
确认还创建了HPA资源
1 2 3 4 |
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端点,只需运行:
1 |
kubectl port-forward service/go-prom-app-service 8080 |
访问:http://localhost:8080
1 2 3 |
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
1 2 3 |
kubectl exec -it redis-server-master-0 -- redis-cli get access_count //output "1" |
确认http_requests指标计数也相同
1 2 3 4 5 |
curl http://localhost:8080/metrics | grep http_requests //output # HELP http_requests number of http requests # TYPE http_requests counter http_requests 1 |
产生负载
我们将使用hey,一个实用程序来生成负载
1 |
curl -o hey https://storage.googleapis.com/hey-release/hey_darwin_amd64 && chmod a+x hey |
1 |
./hey http://localhost:8080/test |
默认情况下,该实用程序发送200个请求。 您应该能够使用Prometheus指标以及Redis进行确认
1 2 3 4 5 6 7 8 9 |
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查询返回)
1 2 3 |
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(值)。 由于我们设置的阈值为3,这还不足以触发横向扩展
摩尔负载!
在新的终端中,跟踪应用程序Pod
1 |
kubectl get pods -l=app=go-prom-app -w |
让我们用以下命令模拟重负载:
1 |
./hey -n 2000 http://localhost:8080/test |
在某些时候,您会看到HPA会扩展部署,并且会旋转新的Pod。
检查HPA以确认相同,
1 2 3 4 |
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查询返回)
1 |
curl -g 'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))' |
清理
1 2 3 4 5 6 7 8 9 10 |
//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允许您基于来自外部指标(例如Prometheus指标,Redis中的队列长度,Kafka主题的使用者滞后等)的数据,自动将Kubernetes部署(从零扩展/从零扩展)。它完成了与 外部资源,并通过Metrics服务器公开其指标,以供Horizontal Pod Autoscaler编织其魔力!
这就是本博客的全部内容。 另外,如果您发现本文有用,请喜欢并关注
原文:https://dev.to/azure/how-to-auto-scale-your-kubernetes-apps-with-prometheus-and-keda-39km
github地址:https://github.com/abhirockzz/kubernetes-keda-prometheus