Аўтаскейлінг прыкладанняў Kubernetes пры дапамозе Prometheus і KEDA

Аўтаскейлінг прыкладанняў Kubernetes пры дапамозе Prometheus і KEDABalloon Man by Cimuanos

Маштабаванасць - ключавое патрабаванне для хмарных прыкладанняў. З Kubernetes маштабаваць дадатак гэтак жа проста, як і павялічыць колькасць рэплік для адпаведнага разгортвання або ReplicaSet - Але гэта ручны працэс.

Kubernetes дазваляе аўтаматычна маштабаваць прыкладання (гэта значыць Pod ў разгортванні або ReplicaSet) дэкларатыўным чынам з выкарыстаннем спецыфікацыі Horizontal Pod Autoscaler. Па змаўчанні крытэр для аўтаматычнага маштабавання – метрыкі выкарыстання CPU (метрыкі рэсурсаў), але можна інтэграваць карыстацкія метрыкі і метрыкі, якія прадстаўляюцца звонку.

Каманда Kubernetes aaS ад Mail.ru перавяла артыкул аб тым, як выкарыстоўваць вонкавыя метрыкі для аўтаматычнага маштабавання прыкладання Kubernetes. Каб паказаць, як усё працуе, аўтар выкарыстоўвае метрыкі запытаў HTTP-доступу, яны збіраюцца з дапамогай Prometheus.

Замест гарызантальнага аўтамаштабавання подаў, прымяняецца Kubernetes Event Driven Autoscaling (KEDA) - аператар Kubernetes з адкрытым зыходным кодам. Ён першапачаткова інтэгруецца з Horizontal Pod Autoscaler, каб забяспечыць плыўнае аўтамаштабаванне (у тым ліку да/ад нуля) для кіраваных падзеямі працоўных нагрузак. Код даступны на GitHub.

Кароткі агляд працы сістэмы

Аўтаскейлінг прыкладанняў Kubernetes пры дапамозе Prometheus і KEDA

На схеме – кароткае апісанне таго, як усё працуе:

  1. Прыкладанне дае метрыкі колькасці зваротаў да HTTP у фармаце Prometheus.
  2. Prometheus настроены на збор гэтых паказчыкаў.
  3. Скейлер Prometheus у KEDA настроены на аўтаматычнае маштабаванне прыкладання на аснове колькасці зваротаў да HTTP.

Зараз падрабязна раскажу аб кожным элеменце.

KEDA і Prometheus

Prometheus - набор інструментаў для маніторынгу і абвесткі сістэм з адкрытым зыходным кодам, частка Фонд хмарных натыўных вылічэнняў. Збірае метрыкі з розных крыніц і захоўвае ў выглядзе дадзеных часавых шэрагаў. Для візуалізацыі дадзеных можна выкарыстоўваць Графана ці іншыя інструменты візуалізацыі, якія працуюць з API Kubernetes.

KEDA падтрымлівае канцэпцыю скейлера - ён дзейнічае як мост паміж KEDA і знешняй сістэмай. Рэалізацыя скейлера спецыфічная для кожнай мэтавай сістэмы і здабывае з яе дадзеныя. Затым KEDA выкарыстоўвае іх для кіравання аўтаматычным маштабаваннем.

Скейлеры падтрымліваюць некалькіх крыніц дадзеных, напрыклад, Kafka, Redis, Prometheus. Гэта значыць KEDA можна прымяняць для аўтаматычнага маштабавання разгортванняў Kubernetes, выкарыстоўваючы ў якасці крытэрыяў метрыкі Prometheus.

Тэставы дадатак

Тэставое 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

Маніфест разгортвання Prometheus складаецца з:

  • ConfigMap - Для перадачы канфіга Prometheus;
  • Deployment - Для разгортвання Prometheus ў Kubernetes-кластары;
  • ClusterIP - сэрвіс для доступу да UI Prometheus;
  • ClusterRole, ClusterRoleBinding и ServiceAccount - Для працы аўтавызначэння сэрвісаў у Kubernetes (Auto-discovery).

Вось маніфест для запуску Prometheus.

KEDA 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), а максімальная колькасць падоў не перавышае maxReplicaCount (У дадзеным прыкладзе - дзесяць).

Можна ўсталяваць minReplicaCount роўным нулю. У гэтым выпадку KEDA актывуе разгортванне з нуля да адзінкі, а затым дае HPA для далейшага аўтаматычнага маштабавання. Магчымы і адваротны парадак, гэта значыць маштабаванне ад адзінкі да нуля. У прыкладзе мы не абралі нуль, паколькі гэта HTTP-сэрвіс, а не сістэма па запыце.

Магія ўнутры аўтамаштабавання

Парогавае значэнне выкарыстоўваюць у якасці трыгера для маштабавання разгортвання. У нашым прыкладзе запыт PromQL sum(rate (http_requests [2m])) вяртае агрэгаванае значэнне хуткасці HTTP-запытаў (колькасць запытаў у секунду), яе вымяраюць за апошнія дзве хвіліны.

Паколькі парогавае значэнне роўна тром, значыць, будзе адзін пад, пакуль значэнне sum(rate (http_requests [2m])) менш за тры. Калі ж значэнне ўзрастае, дадаецца дадатковы пад кожны раз, калі sum(rate (http_requests [2m])) павялічваецца на тры. Напрыклад, калі значэнне ад 12 да 14, то колькасць подаў - чатыры.

Цяпер давайце паспрабуем наладзіць!

Папярэдняя настройка

Усё, што вам трэба - кластар 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/

Усталюйце кубектль, Каб атрымаць доступ да кластара 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 Operator стартуе - пяройдзе ў Running State. І пасля гэтага працягвайце.

Усталёўка Redis пры дапамозе Helm

Калі ў вас не ўсталяваны Helm, скарыстайцеся гэтым кіраўніцтвам. Каманда для ўстаноўкі на Mac:

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

helm init ініцыялізуе лакальны інтэрфейс каманднага радка, а таксама ўстанаўлівае Tiller у кластар Kubernetes.

kubectl get pods -n kube-system | grep tiller

Дачакайцеся пераходу пода Tiller у стан 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 Service Discovery для Prometheus. Ён дазваляе дынамічна выяўляць поды прыкладання на аснове пазнакі службы.

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.

Больш нагрузкі!

У новым тэрмінале сачыце за колькасцю подаў прыкладання:

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

Давайце павялічым нагрузку з дапамогай каманды:

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

Праз некаторы час вы ўбачыце, што HPA маштабуе разгортванне і запускае новыя поды. Праверце 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 для Horizontal Pod Autoscaler.

Поспехаў!

Што яшчэ пачытаць:

  1. Лепшыя практыкі і рэкамендацыі для запуску кантэйнераў і Kubernetes у вытворчых асяроддзях.
  2. 90+ карысных інструментаў для Kubernetes: разгортванне, кіраванне, маніторынг, бяспека і не толькі.
  3. Наш канал Вакол Kubernetes у Тэлеграме.

Крыніца: habr.com

Дадаць каментар