Sur Kubernetes, vous pouvez scale automatiquement vos Deployments
grâce aux Horizontal Pod Autoscaler (HPA). Les HPA se basent sur la consommation en CPU et en mémoire des Pods
de votre Deployment
pour augmenter ou réduire son nombre de réplicas.
Maintenant, supposons que nous souhaitions autoscale un consumer Kafka. À la XebiCon 2018, nous vous présentions une façon d’utiliser les HPA avec les métriques personnalisées de Kubernetes pour autoscale une application kafka-streams. Aujourd’hui, je vous propose de découvrir KEDA qui s’occupera de vous abstraire des principales difficultés.
Prérequis
Pour reproduire les expérimentations de cet article, il vous faudra un cluster Kubernetes 1.18+ et Helm 3.5.x+.
Les composants de KEDA
L’opérateur KEDA est composé des éléments suivants :
- Une CRD
ScaledObject
, qu’on utilisera pour configurer l’autoscaling. - Un
Controller
, qui se base lesScaledObject
pour créer lesHPA
correspondant au scaling désiré. - Un
metrics-apiserver
, qui expose toutes les métriques utiles à notreController
.
Exemple d’un scale up avec KEDA
KEDA fonctionne avec la grande majorité des outils de file de messages.
Installer KEDA
Il existe un chart Helm KEDA officiel très simple d’utilisation. Pour tester rapidement, pas besoin de surcharger beaucoup de valeurs, vous pouvez vous contenter d’un simple :
helm repo add kedacore helm install keda kedacore/keda --namespace keda-system --version 2.1.3
On peut vérifier que tout a bien été installé :
$ kubectl get deploy -n keda-system NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/keda-operator 1/1 1 1 42s deployment.apps/keda-operator-metrics-apiserver 1/1 1 1 42s
Installer Kafka
Pour gagner du temps nous allons déployer un chart Helm Kafka sur notre cluster Kubernetes. Bien évidemment, ce cluster n’a rien de « prod-ready » et dans des conditions réelles nous lui préfererions probablement un service managé. Pour notre test, nous allons au plus simple et déployons avec les valeurs par défaut.
helm repo add bitnami helm install my-release bitnami/kafka
Une fois le chart Helm installé, toutes les informations utiles à son utilisation sont affichées. Voici ce qui va nous intéresser :
Each Kafka broker can be accessed by producers via port 9092 on the following DNS name(s) from within your cluster: my-release-kafka-0.my-release-kafka-headless.default.svc.cluster.local:9092 To create a pod that you can use as a Kafka client run the following commands: kubectl run my-release-kafka-client --restart='Never' --image docker.io/bitnami/kafka:2.8.0-debian-10-r0 --namespace default --command -- sleep infinity kubectl exec --tty -i my-release-kafka-client --namespace default -- bash PRODUCER: kafka-console-producer.sh \ --broker-list my-release-kafka-0.my-release-kafka-headless.default.svc.cluster.local:9092 \ --topic test
L’adresse du broker sera nécessaire pour notre consumer maison.
On peut dès à présent déployer le producer proposé en exemple qui nous servira à tester KEDA. La méthode proposé par le chart Helm vous fait d’abord créer un pod, lancer bash dedans puis utiliser le script kafka-console-producer.sh
pour démarrer un producer. Ensuite, vous n’avez plus qu’à écrire vos messages et appuyée sur entrée
pour qu’ils soient produits dans le topic.
Déployer un consumer
Pour que KEDA puisse autoscale une application, celle-ci doit utiliser un Deployment
. J’ai préparé pour vous une image de consumer Kafka : sapientfr/consumer
.
C’est une application très simple qui ne fait que récupérer le contenu d’un topic Kafka et le loguer.
Voici notre manifeste de Deployment
pour Kubernetes :
apiVersion: apps/v1 kind: Deployment metadata: labels: app: consumer name: consumer spec: replicas: 1 selector: matchLabels: app: consumer template: metadata: labels: app: consumer spec: containers: - image: sapientfr/consumer name: consumer env: - name: BROKER value: my-release-kafka-0.my-release-kafka-headless.default.svc.cluster.local:9092 - name: TOPIC value: test - name: GROUP_ID value: app_1
Une fois déployé, on va surveiller le nombre de réplicas que le Deployment
possède :
kubectl get deploy -w NAME READY UP-TO-DATE AVAILABLE AGE consumer 1/1 1 1 42s
On peut tester que notre consumer fonctionne bien en envoyant des messages via notre producer et en affichant les logs :
Producer Kafka
Consumer Kafka
Déployer le ScaledObject
Il ne nous reste plus qu’à déployer notre ScaledObjectDeployment
. Voici notre manifeste de ScaledObject
:
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: kafka-scaledobject namespace: default spec: maxReplicaCount: 100 minReplicaCount: 0 pollingInterval: 5 scaleTargetRef: name: consumer triggers: - type: kafka metadata: bootstrapServers: my-release-kafka-0.my-release-kafka-headless.default.svc.cluster.local:9092 consumerGroup: app_1 topic: test lagThreshold: '5'
Dans ce manifeste on définit en spec
toute la configuration de notre autoscaling :
maxReplicaCount
: le nombre maximal de réplicas souhaité, utile pour éviter de prendre toutes les ressources du cluster Kubernetes.minReplicaCount
: c’est l’inverse. KEDA vous permet de downscale jusqu’à 0 si vous le désirez quand votre file de message est vide. Attention au cold start !pollingInterval
: le nombre de secondes entre chaque vérification de l’état de la file de message.scaleTargetRef
: les informations nécessaires pour identifier la cible à autoscale. Ici, le nom duDeployment
seul suffit.triggers
:type
: le type de scalers en fonction de l’outil de file de message que l’on utilise.metadata
: les informations pour se connecter à notre source de messages.
Retrouvez sur la documentation du ScaledObject de KEDA toutes les autres configurations possibles.
Résultats
Actuellement notre application est à jour dans la file de message. Si nous attendons quelques secondes que notre ScaledObject
fasse effet, nous allons voir notre Deployment
diminuer son nombre de réplicas pour passer à 0.
kubectl get deploy -w NAME READY UP-TO-DATE AVAILABLE AGE consumer 1/1 1 1 42s # le nombre initial de réplicas est à 1 consumer 0/0 0 0 1337s # le nombre de réplicas a été mis à jour à 0
Amusez-vous à renvoyer des messages, et vous verrez votre Deployment
augmenter son nombre de réplicas tout seul !
kubectl get deploy -w NAME READY UP-TO-DATE AVAILABLE AGE consumer 1/1 1 1 42s # le nombre initial de réplicas est à 1 consumer 0/0 0 0 1337s # le nombre de réplicas a été mis à jour à 0 consumer 0/1 1 0 1350s # le nombre de réplicas a été mis à jour à 1 consumer 1/1 1 1 1355s # on a 1 pod qui est running
Vous pouvez également jouer avec les paramètres de votre ScaledObject
pour observer l’impact sur l’autoscaling.
Pour conclure
Dans cet article, nous venons donc de voir à quel point il est aisé d’autoscale une application en fonction d’une file de message (ici un topic Kafka) grâce à KEDA. Celui-ci se déploie facilement grâce à un chart Helm et propose plus d’une trentaine de connecteurs sur lesquels baser vos autoscaling. Vous pouvez retrouver tout le code source présenté dans ce repository GitHub KEDA hello world.