Маштабаванасць - ключавое патрабаванне для хмарных прыкладанняў. З 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.
Кароткі агляд працы сістэмы
На схеме – кароткае апісанне таго, як усё працуе:
Прыкладанне дае метрыкі колькасці зваротаў да HTTP у фармаце Prometheus.
Prometheus настроены на збор гэтых паказчыкаў.
Скейлер Prometheus у KEDA настроены на аўтаматычнае маштабаванне прыкладання на аснове колькасці зваротаў да HTTP.
Зараз падрабязна раскажу аб кожным элеменце.
KEDA і Prometheus
Prometheus - набор інструментаў для маніторынгу і абвесткі сістэм з адкрытым зыходным кодам, частка Фонд хмарных натыўных вылічэнняў. Збірае метрыкі з розных крыніц і захоўвае ў выглядзе дадзеных часавых шэрагаў. Для візуалізацыі дадзеных можна выкарыстоўваць Графана ці іншыя інструменты візуалізацыі, якія працуюць з API Kubernetes.
KEDA падтрымлівае канцэпцыю скейлера - ён дзейнічае як мост паміж KEDA і знешняй сістэмай. Рэалізацыя скейлера спецыфічная для кожнай мэтавай сістэмы і здабывае з яе дадзеныя. Затым KEDA выкарыстоўвае іх для кіравання аўтаматычным маштабаваннем.
Скейлеры падтрымліваюць некалькіх крыніц дадзеных, напрыклад, Kafka, Redis, Prometheus. Гэта значыць KEDA можна прымяняць для аўтаматычнага маштабавання разгортванняў Kubernetes, выкарыстоўваючы ў якасці крытэрыяў метрыкі Prometheus.
Тэставы дадатак
Тэставое Golang-дадатак дае доступ па HTTP і выконвае дзве важныя функцыі:
Выкарыстоўвае кліенцкую бібліятэку Prometheus Go для інструментавання прыкладання і прадастаўлення метрыкі http_requests, якая змяшчае лічыльнік зваротаў. Канчатковая кропка, па якой даступныя метрыкі Prometheus, размешчана па URI /metrics.
var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
Name: "http_requests",
Help: "number of http requests",
})
У адказ на запыт GET дадатак павялічвае значэнне ключа (access_count) у Redis. Гэта просты спосаб выканаць працу як частка апрацоўшчыка HTTP, а таксама праверыць метрыкі Prometheus. Значэнне метрыкі павінна быць такім жа, як значэнне access_count у Redis.
Дадатак разгортваецца ў Kubernetes праз Deployment. Таксама ствараецца служба ClusterIP, яна дазваляе серверу Prometheus атрымліваць метрыкі прыкладання.
Скейлер дзейнічае як мост паміж KEDA і знешняй сістэмай, з якой трэба атрымліваць метрыкі. ScaledObject - Наладжвальны рэсурс, яго неабходна разгарнуць для сінхранізацыі разгортвання з крыніцай падзей, у дадзеным выпадку з Prometheus.
ScaledObject змяшчае інфармацыю аб маштабаванні разгортвання, метададзеныя аб крыніцы падзеі (напрыклад, сакрэты для падлучэння, імя чаргі), інтэрвал апытання, перыяд аднаўлення і іншыя дадзеныя. Ён прыводзіць да які адпавядае рэсурсу аўтамаштабавання (вызначэнне HPA) для маштабавання разгортвання.
Калі аб'ект ScaledObject выдаляецца, якое адпавядае яму вызначэнне HPA чысціцца.
Вось вызначэнне ScaledObject для нашага прыкладу, у ім выкарыстоўваецца скейлер Prometheus:
Тып трыгера - Prometheus. Адрас сервера Prometheus згадваецца разам з імем метрыкі, парогавым значэннем і запытам PromQL, Які будзе выкарыстоўвацца. Запыт PromQL - sum(rate(http_requests[2m])).
Згодна з 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, Але вы можаце ўзяць любы іншы. Для ўстаноўкі кластара ёсць кіраўніцтва.
helm init ініцыялізуе лакальны інтэрфейс каманднага радка, а таксама ўстанаўлівае Tiller у кластар Kubernetes.
kubectl get pods -n kube-system | grep tiller
Дачакайцеся пераходу пода Tiller у стан Running.
Заўвага перакладчыка: Аўтар выкарыстоўвае Helm@2, які патрабуе ўстаноўкі сервернага кампанента Tiller. Цяпер актуальны Helm@3, для яго серверная частка не патрэбна.
Пасля ўстаноўкі Helm для запуску Redis дастаткова адной каманды:
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.
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 нашага прыкладання, запусціце:
Цяпер вы можаце атрымаць доступ да дадатку 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
Стварэнне нагрузкі
Мы будзем выкарыстоўваць эй - утыліту для генерацыі нагрузкі:
У гэтым выпадку фактычны вынік роўны 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), то выкарыстоўвайце каманду:
//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.