Autoscaling Kubernetes application gamit ang Prometheus at KEDA

Autoscaling Kubernetes application gamit ang Prometheus at KEDABalloon Man ni Cimuanos

Ang scalability ay isang pangunahing kinakailangan para sa mga cloud application. Sa Kubernetes, ang pag-scale ng isang application ay kasing simple ng pagtaas ng bilang ng mga replika para sa naaangkop na deployment o ReplicaSet — ngunit ito ay isang manu-manong proseso.

Pinapayagan ng Kubernetes ang mga application na awtomatikong mai-scale (ibig sabihin, ang mga Pod sa isang deployment o ReplicaSet) sa paraang deklaratibo gamit ang detalye ng Horizontal Pod Autoscaler. Ang default na pamantayan para sa awtomatikong pag-scale ay ang mga sukatan ng paggamit ng CPU (mga sukatan ng mapagkukunan), ngunit maaari mong isama ang mga sukatan ng custom at external na ibinigay.

Koponan Kubernetes aaS mula sa Mail.ru nagsalin ng artikulo sa kung paano gumamit ng mga panlabas na sukatan upang awtomatikong sukatin ang isang Kubernetes application. Upang ipakita kung paano gumagana ang lahat, gumagamit ang may-akda ng mga sukatan ng kahilingan sa pag-access sa HTTP, na kinokolekta gamit ang Prometheus.

Sa halip na pahalang na autoscaling ng mga pod, ginagamit ang Kubernetes Event Driven Autoscaling (KEDA), isang open source na operator ng Kubernetes. Ito ay natively na isinasama sa Horizontal Pod Autoscaler upang magbigay ng tuluy-tuloy na autoscaling (kabilang ang sa/mula sa zero) para sa mga workload na hinihimok ng kaganapan. Available ang code sa GitHub.

Maikling pangkalahatang-ideya ng system

Autoscaling Kubernetes application gamit ang Prometheus at KEDA

Ang diagram ay nagpapakita ng maikling paglalarawan kung paano gumagana ang lahat:

  1. Ang application ay nagbibigay ng HTTP hit count metrics sa Prometheus format.
  2. Naka-configure ang Prometheus para kolektahin ang mga sukatang ito.
  3. Ang Prometheus scaler sa KEDA ay na-configure upang awtomatikong sukatin ang application batay sa bilang ng mga hit ng HTTP.

Ngayon sasabihin ko sa iyo nang detalyado ang tungkol sa bawat elemento.

KEDA at Prometheus

Ang Prometheus ay isang open source system monitoring at alerting toolkit, bahagi Cloud Native Computing Foundation. Nangongolekta ng mga sukatan mula sa iba't ibang mapagkukunan at iniimbak ang mga ito bilang data ng serye ng oras. Upang mailarawan ang data na maaari mong gamitin grafana o iba pang tool sa visualization na gumagana sa Kubernetes API.

Sinusuportahan ng KEDA ang konsepto ng isang scaler - ito ay nagsisilbing tulay sa pagitan ng KEDA at ng panlabas na sistema. Ang pagpapatupad ng scaler ay partikular sa bawat target na system at kumukuha ng data mula dito. Pagkatapos ay ginagamit ng KEDA ang mga ito upang kontrolin ang awtomatikong pag-scale.

Sinusuportahan ng mga scaler ang maraming data source, halimbawa, Kafka, Redis, Prometheus. Ibig sabihin, maaaring gamitin ang KEDA para awtomatikong sukatin ang mga deployment ng Kubernetes gamit ang mga sukatan ng Prometheus bilang pamantayan.

Test application

Ang Golang test application ay nagbibigay ng access sa pamamagitan ng HTTP at gumaganap ng dalawang mahahalagang function:

  1. Gumagamit ng library ng kliyente ng Prometheus Go upang instrumento ang application at ibigay ang sukatan ng http_requests, na naglalaman ng bilang ng hit. Ang endpoint kung saan available ang mga sukatan ng Prometheus ay matatagpuan sa URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. Bilang tugon sa isang kahilingan GET dinadagdagan ng application ang halaga ng susi (access_count) sa Redis. Ito ay isang madaling paraan upang gawin ang gawain bilang bahagi ng isang HTTP handler at tingnan din ang mga sukatan ng Prometheus. Ang halaga ng sukatan ay dapat na kapareho ng halaga access_count sa 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)
       }
    

Ang application ay na-deploy sa Kubernetes sa pamamagitan ng Deployment. Ang isang serbisyo ay nilikha din ClusterIP, pinapayagan nito ang Prometheus server na makakuha ng mga sukatan ng aplikasyon.

Dito deployment manifest para sa application.

Prometheus Server

Ang Prometheus deployment manifest ay binubuo ng:

  • ConfigMap — para ilipat ang Prometheus config;
  • Deployment — para sa pag-deploy ng Prometheus sa isang Kubernetes cluster;
  • ClusterIP — serbisyo para sa pag-access sa UI Prometheus;
  • ClusterRole, ClusterRoleBinding и ServiceAccount — para sa auto-detection ng mga serbisyo sa Kubernetes (Auto-discovery).

Dito manifest para sa pagpapatakbo ng Prometheus.

KEDA Prometheus ScaledObject

Ang scaler ay nagsisilbing tulay sa pagitan ng KEDA at ng panlabas na sistema kung saan kailangang makuha ang mga sukatan. ScaledObject ay isang custom na mapagkukunan na kailangang i-deploy upang i-synchronize ang deployment sa pinagmulan ng kaganapan, sa kasong ito Prometheus.

ScaledObject naglalaman ng impormasyon sa pag-scale ng deployment, metadata ng pinagmulan ng kaganapan (gaya ng mga lihim ng koneksyon, pangalan ng queue), agwat ng botohan, panahon ng pagbawi, at iba pang data. Nagreresulta ito sa kaukulang autoscaling resource (HPA definition) upang masukat ang deployment.

Kapag ang isang bagay ScaledObject ay tinanggal, ang katumbas na kahulugan ng HPA ay na-clear.

Narito ang kahulugan ScaledObject para sa aming halimbawa, ito ay gumagamit ng isang scaler 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]))

Pakitandaan ang mga sumusunod na punto:

  1. Tinuro niya Deployment Sa pangalan go-prom-app.
  2. Uri ng trigger - Prometheus. Binanggit ang address ng server ng Prometheus kasama ng pangalan ng sukatan, threshold at Query sa PromQL, na gagamitin. PromQL Query - sum(rate(http_requests[2m])).
  3. Ayon sa pollingInterval, humihiling ang KEDA ng target mula sa Prometheus tuwing labinlimang segundo. Hindi bababa sa isa sa ilalim (minReplicaCount), at ang maximum na bilang ng mga pod ay hindi lalampas maxReplicaCount (sa halimbawang ito - sampu).

Maaaring i-install minReplicaCount katumbas ng zero. Sa kasong ito, ina-activate ng KEDA ang zero-to-one na deployment at pagkatapos ay ilantad ang HPA para sa karagdagang awtomatikong pag-scale. Posible rin ang reverse order, iyon ay, pag-scale mula isa hanggang zero. Sa halimbawa, hindi kami pumili ng zero dahil ito ay isang serbisyo ng HTTP at hindi isang on-demand na system.

Ang magic sa loob ng autoscaling

Ginagamit ang threshold bilang trigger para sukatin ang deployment. Sa aming halimbawa, ang PromQL query sum(rate (http_requests [2m])) ibinabalik ang pinagsama-samang rate ng kahilingan sa HTTP (mga kahilingan sa bawat segundo), na sinusukat sa huling dalawang minuto.

Dahil ang halaga ng threshold ay tatlo, nangangahulugan ito na magkakaroon ng isa sa ilalim habang ang halaga sum(rate (http_requests [2m])) mas mababa sa tatlo. Kung tumaas ang halaga, magdaragdag ng karagdagang sub sa bawat pagkakataon sum(rate (http_requests [2m])) tataas ng tatlo. Halimbawa, kung ang halaga ay mula 12 hanggang 14, ang bilang ng mga pod ay apat.

Ngayon subukan nating i-set up ito!

presetting

Ang kailangan mo lang ay isang Kubernetes cluster at isang naka-configure na utility kubectl. Ang halimbawang ito ay gumagamit ng isang kumpol minikube, ngunit maaari kang kumuha ng isa pa. Upang mag-install ng isang kumpol mayroong pamumuno.

I-install ang pinakabagong bersyon sa 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/

Itakda kubectlpara ma-access ang Kubernetes cluster.

I-install ang pinakabagong bersyon sa 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

Pag-install ng KEDA

Maaari mong i-deploy ang KEDA sa maraming paraan, nakalista ang mga ito dokumentasyon. Gumagamit ako ng monolithic YAML:

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

Ang KEDA at ang mga bahagi nito ay naka-install sa namespace keda. Utos na suriin:

kubectl get pods -n keda

Hintayin ang KEDA Operator na magsimula at pumunta sa Running State. At pagkatapos nito, magpatuloy.

Pag-install ng Redis gamit ang Helm

Kung wala kang Helm na naka-install, gamitin ito pamumuno. Command na i-install sa Mac:

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

helm init sinisimulan ang lokal na interface ng command line at nag-i-install din Tiller sa Kubernetes cluster.

kubectl get pods -n kube-system | grep tiller

Hintaying pumasok ang Tiller pod sa Running state.

Tala ng tagasalin: Gumagamit ang may-akda ng Helm@2, na nangangailangan ng bahagi ng server ng Tiller na mai-install. Ngayon ay may kaugnayan ang Helm@3, hindi ito nangangailangan ng bahagi ng server.

Pagkatapos i-install ang Helm, sapat na ang isang utos upang simulan ang Redis:

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

I-verify na matagumpay na nagsimula ang Redis:

kubectl get pods/redis-server-master-0

Hintayin ang Redis na pumunta sa estado Running.

Pag-deploy ng Application

Utos sa pag-deploy:

kubectl apply -f go-app.yaml

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

Suriin kung nagsimula na ang lahat:

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

Hintayin ang Redis na pumasok sa estado Running.

Pag-deploy ng Prometheus Server

Ginagamit ng Prometheus manifest Pagtuklas ng Serbisyo ng Kubernetes para sa Prometheus. Nagbibigay-daan ito sa dynamic na pagtuklas ng mga application pod batay sa label ng serbisyo.

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

Upang i-deploy:

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

Suriin kung nagsimula na ang lahat:

kubectl get pods -l=app=prometheus-server

Hintayin ang Prometheus na pumunta sa estado Running.

Gamitin kubectl port-forward upang ma-access ang Prometheus user interface (o API server) sa http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Ini-deploy ang KEDA Autoscaling Configuration

Utos na lumikha ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Suriin ang mga log ng operator ng KEDA:

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

Ang resulta ay mukhang ganito:

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"

Suriin sa ilalim ng mga application. Ang isang halimbawa ay dapat na tumatakbo dahil minReplicaCount katumbas ng 1:

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

I-verify na matagumpay na nalikha ang mapagkukunan ng HPA:

kubectl get hpa

Dapat mong makita ang isang bagay tulad ng:

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

Pagsusuri sa kalusugan: pag-access sa aplikasyon

Upang ma-access ang REST endpoint ng aming application, patakbuhin ang:

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

Maa-access mo na ngayon ang iyong Go app gamit ang address http://localhost:8080. Upang gawin ito, patakbuhin ang command:

curl http://localhost:8080/test

Ang resulta ay mukhang ganito:

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

Sa puntong ito suriin din ang Redis. Makikita mo na ang susi access_count nadagdagan sa 1:

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

Tiyaking ang sukatan na halaga ay http_requests pareho:

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

I-load ang Paglikha

Gagamitin natin hey — utility para sa pagbuo ng load:

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

Maaari mo ring i-download ang utility para sa Linux o Windows.

Patakbuhin ito:

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

Bilang default, nagpapadala ang utility ng 200 kahilingan. Maaari mong i-verify ito gamit ang Prometheus metrics pati na rin ang 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

Patunayan ang halaga ng aktwal na sukatan (ibinalik ng PromQL query):

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"]}]}}

Sa kasong ito ang aktwal na resulta ay 1,686057971014493 at ipinapakita sa field value. Ito ay hindi sapat para sa pag-scale, dahil ang threshold na itinakda namin ay 3.

Marami pang load!

Sa bagong terminal, subaybayan ang bilang ng mga application pod:

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

Dagdagan natin ang load gamit ang command:

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

Pagkaraan ng ilang sandali, makikita mo ang HPA na ini-scale ang deployment at naglulunsad ng mga bagong pod. Suriin ang iyong HPA upang matiyak na:

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

Kung ang load ay hindi pare-pareho, ang deployment ay mababawasan sa punto kung saan isang pod lang ang tumatakbo. Kung gusto mong suriin ang aktwal na sukatan (ibinalik ng PromQL query), pagkatapos ay gamitin ang command:

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

Konklusyon

Binibigyang-daan ka ng KEDA na awtomatikong sukatin ang iyong mga deployment ng Kubernetes (sa/mula sa zero) batay sa data mula sa mga panlabas na sukatan. Halimbawa, batay sa mga sukatan ng Prometheus, haba ng pila sa Redis, latency ng consumer sa paksang Kafka.

Ang KEDA ay isinasama sa isang panlabas na pinagmulan at nagbibigay din ng mga sukatan nito sa pamamagitan ng Metrics Server hanggang Horizontal Pod Autoscaler.

Good luck!

Ano pa ang dapat basahin:

  1. Pinakamahuhusay na kagawian at pinakamahuhusay na kagawian para sa pagpapatakbo ng mga container at Kubernetes sa mga kapaligiran ng produksyon.
  2. 90+ kapaki-pakinabang na tool para sa Kubernetes: deployment, pamamahala, pagsubaybay, seguridad at higit pa.
  3. Ang aming channel sa Paikot ng Kubernetes sa Telegram.

Pinagmulan: www.habr.com

Magdagdag ng komento