На хабре уже был перевод одной из статей о KEDA. В ней автор делится делится информацией о проекте, о том как KEDA интегрируется с Prometheus, и как можно масштабировать свое демо-приложение на базе метрик получаемых с Redis, работающего внутри того же Kubernetes-кластера.
В данной статье я постараюсь быть кратким. Вместе мы познакомимся с KEDA на реальном примере всего за несколько минут. Prometheus нам не пригодится.
Немного введения
Все знают, что Kubernetes отлично работает со stateless-приложениями. Особо серьезные ребята даже запускают базы данных в кубере, а самые смелые даже в продакшне. Но чаще всего в проде используются сервисы типа RDS или же БД развернутые за пределами Kubernetes-кластера.
Для тех кто хочет масштабировать свои приложения внутри Kubernetes, но при этом использовать какие-то внешние метрики (например кол-во сообщений в AWS SQS или Kafka, соединений в PostgreSQL/MySQL/и т.д) необходимо использовать внешние (external) метрики. Чаще всего это реализуется импортом метрик в Prometheus, с помощью различных адаптеров, и последующим масштабированием приложения на основе метрик в проме.
Так вот, KEDA позволяет нам немного упростить этот процесс, не обращаясь за метриками в Prometheus. Все что нам нужно, задеплоить несколько CRD-шек, пару-тройку ямлов для описания масштабирования и доступов. В общем, сейчас покажу.
Установка KEDA
Я провожу свои эксперименты на macOS, с установленным Docker for Mac. Можете использовать все что угодно, любой кубер подойдет.
Установка KEDA простая, я использую helm:
$ helm repo add kedacore https://kedacore.github.io/charts
$ helm repo update
$ helm install keda kedacore/keda --namespace keda --create-namespace
Задеплоили чарт, смотрим что под KEDA-оператора и метрикc-сервера поднялись:
$ kubectl get po -n keda
NAME READY STATUS RESTARTS AGE
keda-operator-7fc5699d47-ng7rk 1/1 Running 0 75s
keda-operator-metrics-apiserver-57fc85685f-zqnzr 1/1 Running 0 75s
$ kubectl get apiservices v1beta1.external.metrics.k8s.io
NAME SERVICE AVAILABLE AGE
v1beta1.external.metrics.k8s.io keda/keda-operator-metrics-apiserver True 95s
Все, KEDA-оператор установлен, идем дальше.
Задеплоим "Hello World"
У Kubernetes свой "Hello World", это деплоймент nginx, давайте идти по канонам и задеплоим его:
$ kubectl create ns nginx-demo
$ kubectl apply -n nginx-demo -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/controllers/nginx-deployment.yaml
Проверим состояние подов:
$ kg po -n nginx-demo
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-2g24q 1/1 Running 0 36s
nginx-deployment-66b6c48dd5-67kgv 1/1 Running 0 36s
nginx-deployment-66b6c48dd5-fj4lq 1/1 Running 0 36s
Все хорошо, в этом деплойменте 3 пода, как и положено.
Давайте сделаем так, чтобы поды масштабировались в зависимости от количества сообщений в очереди RabbitMQ.
На данный момент KEDA поддерживает 36 различных источников, на основе которых можно масштабироваться, в моем примере я выбрал RabbitMQ, просто потому что так захотел.
Немного подготовки RabbitMQ
Как я уже упоминал ранее, свои тесты я делаю на локальной машине с Docker for Mac, поэтому я хочу сымитировать реальную ситуацию, когда RabbitMQ запускается не внутри Kubernetes, а, скажем, в другой сети. Поэтому его я буду устанавливать просто через brew-пакет. Но перед этим, давайте запишем IP-адрес моей локальной машины, он нам скоро пригодится:
$ ipconfig getifaddr en0
192.168.2.101
Все, устанавливаем RabbitMQ и стартуем его:
$ brew install rabbitmq
$ RABBITMQ_NODE_IP_ADDRESS=0.0.0.0 /usr/local/sbin/rabbitmq-server
...
## ## RabbitMQ 3.8.19
## ##
########## Copyright (c) 2007-2021 VMware, Inc. or its affiliates.
###### ##
########## Licensed under the MPL 2.0. Website: https://rabbitmq.com
...
Starting broker... completed with 6 plugins.
Убедимся что все поднялось:
$ /usr/local/sbin/rabbitmqadmin -H 127.0.0.1 -u guest -p guest \
list connections
No items
Все хорошо. Единственный момент, что доступ под стандартным пользователем guest
доступен только по адресу 127.0.0.1, поэтому нужно добавить нового пользователя, скажем (demo
/demo
), ну и создать очередь (demo_queue
) для тестирования:
$ /usr/local/sbin/rabbitmqadmin --host 127.0.0.1 -u guest -p guest \
declare user name=demo password=demo tags=administrator
user declared
$ /usr/local/sbin/rabbitmqadmin --host 127.0.0.1 -u guest -p guest \
declare permission vhost=/ user=demo configure=".*" write=".*" read=".*"
permission declared
$ /usr/local/sbin/rabbitmqadmin --host 127.0.0.1 -u guest -p guest \
declare queue name=demo_queue
queue declared
После этого мы можем подключаться по "внешнему" IP-адресу к кролику:
$ /usr/local/sbin/rabbitmqadmin -H 192.168.2.101 -u demo -p demo \
list queues
+------------+----------+
| name | messages |
+------------+----------+
| demo_queue | 0 |
+------------+----------+
Немного YAML
RabbitMQ готов, теперь нужно подключить к нему KEDA, для этого нам надо задеплоить три объекта:
-
Secret
— в нем будет храниться строка подключения к RabbitMQ, в таком виде:amqp://demo:demo@192.168.2.101:5672/
-
TriggerAuthentication
— объект для аутентификации, который использует данные из секрета выше -
ScaledObject
— собственно тот самый объект, в котором мы можем настраивать различные параметры масштабирования
Деплоим:
$ cat <<EOF | kubectl apply -n nginx-demo -f -
---
apiVersion: v1
kind: Secret
metadata:
name: keda-rabbitmq-secret
data:
host: YW1xcDovL2RlbW86ZGVtb0AxOTIuMTY4LjIuMTAxOjU2NzIv # echo -n amqp://demo:demo@192.168.2.101:5672/ | base64
---
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: keda-trigger-auth-rabbitmq-conn
spec:
secretTargetRef:
- parameter: host
name: keda-rabbitmq-secret # Имя нашего секрета
key: host
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: rabbitmq-scaledobject
spec:
scaleTargetRef:
name: nginx-deployment # Имя nginx-деплоймента который хотим масштабировать
minReplicaCount: 1 # Меньше одной реплики не хотим
maxReplicaCount: 5 # А то же время больше пяти тоже
pollingInterval: 10 # Как часто ходить за метрикой
cooldownPeriod: 120 # Сколько времени ждать для даунскейла
triggers:
- type: rabbitmq
metadata:
protocol: amqp
queueName: demo_queue # Наша демо-очередь
mode: QueueLength
value: "3" # Если в очереди три новых сообщения — добавляем под
authenticationRef:
name: keda-trigger-auth-rabbitmq-conn
EOF
Проверяем что все работает:
$ kubectl get scaledobject
NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE AGE
rabbitmq-scaledobject apps/v1.Deployment nginx-deployment 1 5 rabbitmq keda-trigger-auth-rabbitmq-conn True False 14m
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-24qp7 1/1 Running 0 3m46s
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
keda-hpa-rabbitmq-scaledobject Deployment/nginx-deployment 0/3 (avg) 1 5 1 12m
Тестируем
Давайте отправим 5 сообщений в нашу очередь в RabbitMQ:
$ for i in {1..5}; do
/usr/local/sbin/rabbitmqadmin --host 192.168.2.101 -u demo -p demo \
publish exchange=amq.default routing_key=demo_queue payload="message ${i}"
done
$ /usr/local/sbin/rabbitmqadmin -H 192.168.2.101 -u demo -p demo \
list queues
+------------+----------+
| name | messages |
+------------+----------+
| demo_queue | 5 |
+------------+----------+
Подождем 10 секунд пока KEDA сходит за метрикой и проверим наши поды (мы ожидаем увидеть 2 пода, так как скейлимся по 1 поду, на каждые 3 сообщения в очереди):
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
keda-hpa-rabbitmq-scaledobject Deployment/nginx-deployment 5/3 (avg) 1 5 1 22m
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-24qp7 1/1 Running 0 14m
nginx-deployment-66b6c48dd5-2d4w2 1/1 Running 0 66s
Давайте подбавим газку, добавим еще 7 сообщений в очередь:
$ for i in {6..12}; do
/usr/local/sbin/rabbitmqadmin --host 192.168.2.101 -u demo -p demo \
publish exchange=amq.default routing_key=demo_queue payload="message ${i}"
done
$ /usr/local/sbin/rabbitmqadmin -H 192.168.2.101 -u demo -p demo \
list queues
+------------+----------+
| name | messages |
+------------+----------+
| demo_queue | 12 |
+------------+----------+
12 сообщений в очереди, по идее уже 4 пода должно работать, проверяем:
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
keda-hpa-rabbitmq-scaledobject Deployment/nginx-deployment 12/3 (avg) 1 5 2 24m
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-24qp7 1/1 Running 1 17m
nginx-deployment-66b6c48dd5-78d54 1/1 Running 0 38s
nginx-deployment-66b6c48dd5-jxtr8 1/1 Running 0 38s
nginx-deployment-66b6c48dd5-sl4p8 1/1 Running 0 38s
Теперь очистим очередь, количество подов должно опуститься до минимального значения (что в нашем случае 1 под):
$ /usr/local/sbin/rabbitmqadmin -H 192.168.2.101 -u demo -p demo \
purge queue name=demo_queue
queue purged
$ /usr/local/sbin/rabbitmqadmin -H 192.168.2.101 -u demo -p demo \
list queues
+------------+----------+
| name | messages |
+------------+----------+
| demo_queue | 0 |
+------------+----------+
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
keda-hpa-rabbitmq-scaledobject Deployment/nginx-deployment 0/3 (avg) 1 5 1 28h
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-24qp7 1/1 Running 0 20m
Все хорошо, масштабируется и вверх и вниз, как и ожидалось.
Приберемся за собой после экспериментов:
$ helm uninstall keda -n keda
$ kubectl delete ns keda
$ kubectl delete ns nginx-demo
Как видите, Prometheus нам не пригодился, все максимально просто. Если пропустить момент с настройкой RabbitMQ, то процесс деплоя и тестирования KEDA занимает буквально несколько минут.
Комментариев нет:
Отправить комментарий