🐇 RabbitMQ dans AKS : le messaging sans dépendance
Intégrez RabbitMQ dans AKS pour un messaging flexible, performant, résilient, et multi-cloud

Introduction
Dans un environnement Kubernetes tel qu’AKS, les micro-services communiquent souvent via des systèmes de messaging. Azure Service Bus est une solution robuste, mais elle reste fortement liée à l’écosystème Azure. Pour des architectures plus agnostiques ou multi-cloud, RabbitMQ s’impose comme une alternative crédible.
RabbitMQ est un broker open-source, léger et performant, qui supporte plusieurs protocoles de communication. Son intégration dans AKS est facilitée par l’usage de Helm charts, permettant un déploiement rapide et configurable.
Dans mon cas, j’ai opté pour RabbitMQ afin de garantir une meilleure portabilité de nos micro-services, tout en conservant un haut niveau de fiabilité. Le déploiement dans AKS inclut des considérations de sécurité (authentification TLS, gestion des secrets), de persistance (volumes persistants) et de scalabilité (horizontal pod autoscaler).
Limitations d’Azure Service Bus dans un contexte multi-cloud ou agnostique
Azure Service Bus est une solution de messaging robuste et bien intégrée à l’écosystème Azure. Toutefois, dans des architectures orientées micro-services déployées sur AKS (Azure Kubernetes Service), et surtout dans des contextes multi-cloud ou agnostiques, certaines limitations deviennent rapidement contraignantes.
Couplage fort à Azure
Azure Service Bus repose sur des services managés et des configurations spécifiques à Azure. Cela implique un verrouillage technologique qui rend difficile la portabilité vers d’autres environnements cloud ou on-premise. Les micro-services deviennent dépendants d’un fournisseur, ce qui limite la flexibilité stratégique et technique.
Coût et flexibilité
Le modèle de tarification d’Azure Service Bus, basé sur le nombre de messages, les connexions et les opérations, peut devenir difficile à maîtriser dans des architectures à forte volumétrie. De plus, certaines fonctionnalités avancées (comme les topics ou les sessions) sont limitées à des niveaux de service premium, ce qui restreint la flexibilité pour les équipes techniques souhaitant expérimenter ou évoluer progressivement.
Limitations de personnalisation
Azure Service Bus est une solution managée, ce qui signifie que Microsoft en contrôle l’infrastructure, les mises à jour et les fonctionnalités. Si cela simplifie la maintenance, cela limite aussi les possibilités de personnalisation pour les équipes techniques qui souhaitent adapter le comportement du broker à des besoins spécifiques.
Contrairement à des solutions comme RabbitMQ ou Apache Kafka, il n’est pas possible de modifier ou d’étendre le fonctionnement interne d’Azure Service Bus.
Par exemple :
Impossible d’ajouter des plugins ou des extensions personnalisées.
Pas de gestion fine des priorités de messages ou des politiques de retry.
Pas de configuration avancée des dead-letter queues ou des mécanismes de routage.
# Politique spécifique pour les queues critiques apiVersion: rabbitmq.com/v1beta1 kind: Policy metadata: name: critical-queue-policy spec: name: critical-queue-policy pattern: "^critical\\..*" # Queues commençant par "critical." applyTo: queues definition: # Configuration Dead Letter Exchange pour queues critiques dead-letter-exchange: deadletter.exchange dead-letter-routing-key: deadletter.rejected # TTL plus long pour les queues critiques (48 heures) message-ttl: 172800000 # Plus de tentatives pour les queues critiques max-delivery-attempts: 5 # Haute disponibilité ha-mode: exactly ha-params: 3 ha-sync-mode: automatic priority: 10 # Priorité plus élevée que la politique générale rabbitmqClusterReference: name: rabbitmq
Pourquoi RabbitMQ ?
Dans une architecture de micro-services déployée sur AKS, le choix du système de messaging est stratégique. RabbitMQ s’impose comme une solution agnostique, performante et flexible, particulièrement adaptée aux environnements cloud hybrides ou multi-cloud.

Open-source, mature et largement adopté
RabbitMQ est un broker open-source basé sur Erlang, reconnu pour sa stabilité et sa robustesse. Il est utilisé dans des milliers d’organisations à travers le monde, ce qui garantit :
Une communauté active et une documentation riche, Une évolution continue sans dépendance à un fournisseur cloud, Une interopérabilité forte avec les outils DevOps et les frameworks modernes. Cette maturité en fait un choix rassurant pour les équipes techniques souhaitant une solution éprouvée et indépendante.
Support de multiples protocoles
RabbitMQ supporte plusieurs protocoles de communication, ce qui le rend particulièrement flexible :
AMQP 0.9.1 : le protocole natif, fiable et performant,
MQTT : idéal pour les architectures IoT ou les communications légères,
STOMP, HTTP, WebSockets : pour des cas d’usage spécifiques ou des intégrations front-end.
Cette diversité permet de connecter facilement des micro-services hétérogènes, sans imposer un protocole unique ou propriétaire.
Facilité d’intégration avec des micro-services
RabbitMQ s’intègre naturellement dans des architectures Kubernetes :
Déploiement via Helm charts ou opérateurs,
Intégration avec des frameworks comme .Net, Spring Boot, NestJS, Node.js, Go, etc.
Compatibilité avec des outils de monitoring comme Prometheus, Grafana, ou Datadog.
Il permet également une gestion fine des files d’attente, des stratégies de retry, du routing dynamique et des dead-letter queues, offrant une grande souplesse pour orchestrer les échanges entre micro-services.
Exemple simplifié en C
Secret Kubernetes
apiVersion: v1 kind: Secret metadata: name: rabbitmq-credentials namespace: default type: Opaque stringData: RABBITMQ_HOST: rabbitmq.default.svc.cluster.local RABBITMQ_USER: myuser RABBITMQ_PASSWORD: mypasswordPublisher
using RabbitMQ.Client; using System; using System.Text; class Publisher { static void Main(string[] args) { var host = Environment.GetEnvironmentVariable("RABBITMQ_HOST"); var user = Environment.GetEnvironmentVariable("RABBITMQ_USER"); var password = Environment.GetEnvironmentVariable("RABBITMQ_PASSWORD"); var factory = new ConnectionFactory() { HostName = host, UserName = user, Password = password, VirtualHost = "/", Port = 5672, Ssl = new SslOption { Enabled = false // mettre à true si TLS est activé } }; using var connection = factory.CreateConnection(); using var channel = connection.CreateModel(); channel.QueueDeclare(queue: "my-queue", durable: true, exclusive: false, autoDelete: false, arguments: null); string message = "Hello RabbitMQ!"; var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish(exchange: "", routingKey: "my-queue", basicProperties: null, body: body); Console.WriteLine($"[x] Sent: {message}"); } }Consumer
using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; using System.Text; class Consumer { static void Main(string[] args) { var host = Environment.GetEnvironmentVariable("RABBITMQ_HOST"); var user = Environment.GetEnvironmentVariable("RABBITMQ_USER"); var password = Environment.GetEnvironmentVariable("RABBITMQ_PASSWORD"); var factory = new ConnectionFactory() { HostName = host, UserName = user, Password = password, VirtualHost = "/", Port = 5672, Ssl = new SslOption { Enabled = false // mettre à true si TLS est activé } }; using var connection = factory.CreateConnection(); using var channel = connection.CreateModel(); channel.QueueDeclare(queue: "my-queue", durable: true, exclusive: false, autoDelete: false, arguments: null); var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) => { var body = ea.Body.ToArray(); var message = Encoding.UTF8.GetString(body); Console.WriteLine($"[x] Received: {message}"); }; channel.BasicConsume(queue: "my-queue", autoAck: true, consumer: consumer); Console.WriteLine("Press [enter] to exit."); Console.ReadLine(); } }Déploiement dans AKS, injectez les variables d’environnement à partir du secret :
env: - name: RABBITMQ_HOST valueFrom: secretKeyRef: name: rabbitmq-credentials key: RABBITMQ_HOST - name: RABBITMQ_USER valueFrom: secretKeyRef: name: rabbitmq-credentials key: RABBITMQ_USER - name: RABBITMQ_PASSWORD valueFrom: secretKeyRef: name: rabbitmq-credentials key: RABBITMQ_PASSWORD
Architecture proposée dans AKS
Dans une approche agnostique du messaging, RabbitMQ s’intègre parfaitement dans un cluster AKS (Azure Kubernetes Service). L’architecture proposée repose sur un déploiement maîtrisé, sécurisé et évolutif, adapté aux environnements de production.

Déploiement de RabbitMQ via Helm
RabbitMQ peut être déployé dans AKS à l’aide du Helm chart officiel, ce qui facilite la configuration, la mise à jour et la gestion du cycle de vie.
Chart utilisé :
bitnami/rabbitmqourabbitmq/rabbitmqCommandes typiques :
helm repo add bitnami https://charts.bitnami.com/bitnamihelm install rabbitmq bitnami/rabbitmq --namespace rabbitmq --create-namespaceAvantages :
Déploiement rapide et reproductible
Paramétrage via
values.yamlpour la persistance, la sécurité, les ressourcesIntégration native avec Kubernetes (services, secrets, configmaps)
Configuration des services
L’architecture repose sur une séparation claire des rôles :
RabbitMQ : déployé comme StatefulSet avec un service interne (
ClusterIP) pour les communications internes.Micro-services : communiquent avec RabbitMQ via des producers/consumers, en utilisant des bibliothèques comme
RabbitMQ.Client(C#),amqplib(Node.js), oupika(Python).Service Mesh (optionnel) : Istio ou Linkerd peuvent être utilisés pour gérer les communications, la sécurité et l’observabilité.
Les échanges sont orchestrés via des queues et des exchanges configurés dynamiquement ou via des scripts d’initialisation.
Sécurité
La sécurité est assurée à plusieurs niveaux :
Authentification : RabbitMQ utilise des credentials stockés dans des
Kubernetes Secrets.Chiffrement :
TLS pour les connexions entre micro-services et RabbitMQ
Possibilité d’activer TLS entre les nœuds RabbitMQ
Réseau :
Utilisation de
NetworkPoliciespour limiter les accèsIntégration possible avec Azure Private Link ou Azure Firewall
Persistance
RabbitMQ peut être configuré pour utiliser un PersistentVolumeClaim (PVC) afin de garantir la durabilité des messages et des métadonnées :
Stockage Azure Disk ou Azure Files
Exemple de configuration :
--- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: rabbitmq-azurefile-premium provisioner: file.csi.azure.com parameters: skuName: Premium_LRS # available values: Standard_LRS, Premium_LRS, Standard_GRS, Standard_RAGRS protocol: smb # available values: smb, nfs resourceGroup: {{ .Values.resourceGroup }} # e.g. myresourcegroup storageAccount: {{ .Values.storageAccount }} # e.g. mystorageaccount server: {{ .Values.storageAccount }}.privatelink.file.core.windows.net reclaimPolicy: Delete volumeBindingMode: Immediate allowVolumeExpansion: true mountOptions: - dir_mode=0777 - file_mode=0777 - mfsymlinks - cache=strict # https://linux.die.net/man/8/mount.cifs - nosharesock # reduce probability of reconnect race - actimeo=30 # reduce latency for metadata-heavy workload ---
Scalabilité
RabbitMQ peut être scalé horizontalement et verticalement :
Verticale : ajustement des ressources CPU/mémoire via les
resourcesdans le chart Helm.Horizontale :
Utilisation du mode cluster de RabbitMQ (avec plusieurs nœuds)
Déploiement en HA avec des policies de mirroring
Intégration avec des outils comme KEDA pour scaler les consumers en fonction du nombre de messages
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: rabbitmq-consumer-scaler namespace: default spec: scaleTargetRef: name: rabbitmq-consumer-deployment # Nom du Deployment à scaler pollingInterval: 30 # Intervalle de vérification (en secondes) cooldownPeriod: 300 # Temps avant de réduire le nombre de pods minReplicaCount: 1 maxReplicaCount: 10 triggers: - type: rabbitmq metadata: queueName: my-queue # Nom de la file RabbitMQ à surveiller host: RabbitMQConnection # Nom du secret contenant la connexion protocol: amqp mode: QueueLength # Mode de déclenchement basé sur la longueur de la file value: "5" # Seuil de messages pour déclencher le scaling
Performance
La performance d’un système de messaging comme RabbitMQ dépend fortement de son dimensionnement initial et de sa capacité à évoluer en fonction de la charge. Dans un environnement AKS, plusieurs leviers permettent d’optimiser les performances tout en garantissant la stabilité du système.
Facteurs influençant la performance
Volume de messages
Taille moyenne des messages : les messages volumineux (> 1 Mo) peuvent impacter la latence.
Fréquence d’envoi : un pic de plusieurs milliers de messages par seconde nécessite un sizing adapté.
Complexité des échanges
Nombre de queues et exchanges : plus ils sont nombreux, plus la charge CPU/mémoire augmente.
Routing dynamique : les exchanges de type
topicouheaderssont plus coûteux que lesdirect.
Mode de consommation
AutoAck vs ManualAck : le mode manuel permet un meilleur contrôle mais consomme plus de ressources.
Prefetch count : un réglage fin permet d’optimiser le débit sans surcharger les consumers.
Sizing recommandé dans AKS
CPU : 1 à 2 vCPU minimum par nœud RabbitMQ
Mémoire : 2 à 4 Go RAM par instance pour des charges moyennes
Stockage : Azure Disk (Premium SSD) avec persistance activée (
8–32 Giselon le volume)
Optimisations mises en œuvre
Activation du clustering RabbitMQ : pour répartir la charge et améliorer la tolérance aux pannes.
Utilisation de
lazy queues: pour les files à forte volumétrie, stockées sur disque plutôt qu’en mémoire.Monitoring des métriques clés : taux de delivery, latence, saturation des queues, via Datadog ou Prometheus.
Réglage du
prefetchcôté consumer : pour éviter les surcharges et optimiser le débit.
Utiliser l’outil pivotalrabbitmq/perf-test
Pour valider les capacités de traitement de RabbitMQ dans notre cluster AKS, j’ai utilisé l’outil https://github.com/rabbitmq/rabbitmq-perf-test, qui permet de simuler des charges réalistes et de mesurer précisément le débit, la latence et la stabilité du système dans différents scénarios.
docker run -it --rm pivotalrabbitmq/perf-test:latest \
--uri amqp://user:pass@host.docker.internal:5672 \
--producers 8 --consumers 8 \
--rate 75 --consumer-rate 75 \
--time 180 --size 1024 \
--queue-pattern 'scale-test-%d' \
--queue-pattern-from 1 --queue-pattern-to 5
--uri: URI de connexion à RabbitMQ (peut être injectée via des variables d’environnement ou des secrets Kubernetes).--producers/--consumers: nombre de producteurs et consommateurs simulés.--rate: nombre de messages par seconde à produire.--size: taille des messages en octets.--queue: nom de la file cible.--time: durée du test en secondes.
Retour d’expérience / bénéfices observés
La mise en place de RabbitMQ dans AKS a permis de répondre efficacement aux besoins de messaging dans un environnement agnostique et distribué. Voici les principaux bénéfices constatés après plusieurs mois d’exploitation en production.
Performance
Le déploiement de RabbitMQ dans AKS a démontré une excellente réactivité dans le traitement des messages :
Latence faible : les échanges entre micro-services sont quasi instantanés, même en cas de forte charge.
Débit élevé : le système a supporté plusieurs milliers de messages par seconde sans saturation, grâce à une configuration optimisée des queues et des exchanges.
Scalabilité maîtrisée : l’ajout de nœuds RabbitMQ dans le cluster permet d’absorber les pics de trafic sans interruption de service.
Ces performances ont été rendues possibles par l’utilisation de Persistent Volumes, de ressources Kubernetes ajustées et d’un monitoring proactif.
Monitoring
L’intégration de RabbitMQ avec Datadog a permis de mettre en place un monitoring centralisé et granulaire, adapté aux environnements distribués.
Métriques RabbitMQ : grâce à l’agent Datadog déployé dans le cluster AKS, les métriques clés (nombre de messages, taux d’erreur, temps de traitement, saturation des queues) sont collectées et visualisées dans des dashboards personnalisés.
Logs centralisés : les logs des pods RabbitMQ sont collectés via l’agent Datadog et envoyés vers la plateforme, permettant une corrélation directe entre logs et métriques. Cela facilite les analyses post-mortem et le diagnostic en temps réel.
Alerting intelligent : des alertes ont été configurées dans Datadog pour détecter les anomalies (latence élevée, erreurs de connexion, queues bloquées), avec envoi de notifications vers Slack ou Microsoft Teams.
Traces distribuées (optionnel) : pour les micro-services intégrés avec OpenTelemetry, Datadog permet de suivre les traces de bout en bout, incluant les interactions avec RabbitMQ.
Cette solution offre une visibilité complète sur le comportement du système, tout en s’intégrant naturellement dans les workflows DevOps existants.

Résilience
La résilience du système a été validée dans plusieurs scénarios :
Redémarrage de pods RabbitMQ sans perte de messages, grâce à la persistance activée.
Failover automatique entre nœuds RabbitMQ en cas de panne, avec maintien de la disponibilité.
Retry intelligent côté consommateurs, avec gestion des dead-letter queues pour les messages non traitables.
Ces mécanismes ont permis de garantir une haute disponibilité et une continuité de service, même en cas de défaillance partielle du cluster AKS.
Conclusion
La mise en œuvre de RabbitMQ dans AKS s’est révélée être une solution robuste, flexible et agnostique, parfaitement adaptée aux architectures micro-services modernes. Ce choix a permis de répondre aux exigences de performance, de résilience et de visibilité, tout en s’affranchissant des limitations des solutions managées comme Azure Service Bus.
Résumé des avantages
Performance : traitement rapide et fluide des messages, même en forte charge.
Scalabilité : adaptation dynamique du nombre de consumers grâce à KEDA.
Monitoring : visibilité complète via Datadog, avec alerting et corrélation des logs.
Résilience : haute disponibilité assurée par la persistance et le clustering RabbitMQ.
Flexibilité : support de multiples protocoles et intégration facile avec les micro-services C#.
Prochaines étapes
Dans une logique d’amélioration continue, plusieurs évolutions sont envisagées :
Migration du monitoring vers Prometheus & Grafana : afin de renforcer l’indépendance vis-à-vis des solutions SaaS et de centraliser les métriques dans une stack open-source.
Optimisation du clustering RabbitMQ : pour améliorer la tolérance aux pannes et la répartition de la charge.
Automatisation des dashboards et des alertes : via des templates Grafana et des règles Prometheus, pour faciliter le déploiement multi-environnement.
Ces évolutions permettront de consolider l’architecture tout en gardant une maîtrise complète de l’infrastructure et des outils de supervision.






