Автоматично мащабиране на приложения в Kubernetes с помощта на Prometheus и KEDA

Автоматично мащабиране на приложения в Kubernetes с помощта на Prometheus и KEDABalloon Man от 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 е набор от инструменти за мониторинг и оповестяване на системи с отворен код, част от Cloud Native Computing Foundation. Събира метрики от различни източници и ги съхранява под формата на времеви редове. За визуализиране на данните може да се използва Grafana или други инструменти за визуализация, работещи с 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: "брой http запитвания",
       })
    
  2. В отговор на запитването ИЗИСКВАНЕ приложението увеличава стойността на ключа (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("Не може да се увеличи броят в Redis", err)
                   os.Exit(1)
               }
               resp := "Достъпен на " + time.Now().String() + "nБрой достъпи " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    

Приложението се разгръща в Kubernetes чрез Deployment. Също така се създава услуга ClusterIP, която позволява на сървъра на Prometheus да получава метрики от приложението.

Ето манифест на разгръщането за приложението.

Сървър Prometheus

Манифестът за разгръщане на Prometheus се състои от:

  • ConfigMap — за предаване на конфигурацията на Prometheus;
  • Deployment — за разгръщане на Prometheus в Kubernetes клъстера;
  • ClusterIP — услуга за достъп до потребителския интерфейс на 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/

Установете 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 Operator стартира — премине в Работещо състояние. И след това продължете.

Инсталиране на 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 премине в състояние Работи.

Бележка на преводача: Авторът използва 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 премине в състояние В процес на изпълнение.

Разгръщане на приложението

Команда за разполагане:

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 премине в състояние В процес на изпълнение.

Разполагане на сървър 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 премине в състояние В процес на изпълнение.

Използвайте 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

Трябва да видите нещо подобно:

ИМЕ                   РЕФЕРЕНЦИЯ                ЦЕЛИ     MINPODS   MAXPODS   РЕПЛИКИ   ВЪЗРАСТ
keda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (средно)   1         10        1          45s

Проверка на работоспособността: достъп до приложението

За да получите достъп до REST крайната точка на нашето приложение, стартирайте:

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

Сега можете да получите достъп до приложението Go, използвайки адреса http://localhost:8080. За целта изпълнете командата:

curl http://localhost:8080/test

Резултатът изглежда приблизително така:

Достъпен на 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Брой на достъпите 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 брой на HTTP заявките
# TYPE http_requests counter
http_requests 1

Създаване на натоварване

Ще използваме hey — инструмент за генериране на натоварване:

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 брой на HTTP заявките
# 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
ИМЕ                   РЕФЕРЕНЦИЯ                ЦЕЛИ         MINPODS   MAXPODS   РЕПЛИКИ   ВЪЗРАСТ
keda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (средно)   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

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster