Масштабованість - ключова вимога для хмарних програм. З 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 — набір інструментів для моніторингу та оповіщення систем з відкритим вихідним кодом, частина Фонд хмарних нативних обчислень. Збирає метрики з різних джерел та зберігає у вигляді даних часових рядів. Для візуалізації даних можна використовувати Grafana або інші інструменти візуалізації, які працюють з 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.
Скейлер діє як міст між 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.