Le modèle side-car : extension des microservices sans modification du code
Dans les systèmes cloud natifs modernes, les microservices devraient faire bien plus que simplement exécuter une logique métier. Ils doivent gérer la journalisation, gérer les certificats SSL/TLS, collecter des métriques, mettre en œuvre des mécanismes de nouvelle tentative et coordonner les communications sécurisées avec d’autres services.
Si nous intégrons toutes ces fonctionnalités transversales directement dans la base de code de chaque application, nous nous retrouvons avec une surcharge de code, un couplage étroit et un verrouillage linguistique.
C’est là que le Sidecar Pattern entre en jeu. Dans ce guide, nous expliquerons ce qu’est le modèle Sidecar, pourquoi il est essentiel pour les architectures de microservices modernes et comment il fonctionne à l’aide d’analogies simples et d’exemples de configuration Kubernetes.
L’analogie avec le monde réel : le side-car de la moto
La façon la plus simple de comprendre ce modèle est de penser à une moto avec un side-car.
Imaginez que vous possédez une moto haute performance. Il est conçu pour faire une chose exceptionnellement bien : transporter rapidement un passager. Supposons maintenant que vous deviez transporter les bagages d’un passager ou ajouter un siège supplémentaire.
Vous pouvez complètement repenser le cadre, le moteur et les roues de la moto pour la transformer en voiture. Cependant, cela demande des efforts considérables, ruine la simplicité du vélo et le rend difficile à entretenir.
Au lieu de cela, vous attachez un side-car.
Le side-car est une unité séparée et autonome qui se connecte à la moto. Il partage le voyage de la moto, l’accompagne partout où elle va et fonctionne en tandem étroit. Pourtant, le moteur principal de la moto reste intact.
En architecture logicielle :
- La Motorcycle est votre conteneur d’application principal (exécutant votre logique métier principale, comme le paiement ou l’authentification de l’utilisateur).
- Le Sidecar est un conteneur d’assistance distinct (exécutant des tâches utilitaires, telles que la terminaison SSL, la surveillance ou l’envoi de journaux).
- Le parcours est le cycle de vie du déploiement (par exemple, un pod Kubernetes).
Le problème : préoccupations transversales et surcharge du code
Avant les side-cars, les développeurs devaient inclure des bibliothèques d’assistance directement dans le code de leur application. Par exemple, si vous souhaitez envoyer des journaux à un serveur central, vous avez importé une bibliothèque de journalisation. Si vous aviez besoin de métriques, vous avez ajouté un SDK de métriques.
Cette approche basée sur les bibliothèques a créé plusieurs défis importants :
- Language Lock-in : si une bibliothèque de surveillance est uniquement écrite en Go, vous ne pouvez pas facilement l’utiliser dans un microservice Python ou Java. Vous devez trouver ou créer une bibliothèque pour chaque langue de votre pile.
- Pollution du code : la logique métier est encombrée de code spécifique à l’infrastructure pour les tentatives, la découverte de services, le chiffrement et la journalisation.
- Mises à niveau complexes : si une vulnérabilité de sécurité est détectée dans la bibliothèque de communication, chaque microservice doit mettre à jour sa dépendance, recompiler et redéployer.
- Conflit de ressources : le code d’assistance s’exécute dans le même processus d’exécution que l’application principale, ce qui signifie qu’une fuite de mémoire dans l’enregistreur peut faire planter l’ensemble de votre application principale.
La solution : le modèle side-car
Le Sidecar Pattern résout ces problèmes en déplaçant les tâches d’assistance hors du processus d’application principal et en les plaçant dans un processus distinct et indépendant s’exécutant juste à côté de l’application.
Dans les environnements conteneurisés comme Kubernetes, le conteneur d’application et le conteneur side-car s’exécutent dans le même Pod. Parce qu’ils partagent le même Pod :
- Même espace de noms réseau : ils partagent la même adresse IP et les mêmes ports réseau. Ils peuvent se parler instantanément via
localhostavec une latence pratiquement nulle. - Volumes de stockage partagés : ils peuvent accéder exactement au même stockage sur disque, permettant au side-car de lire les fichiers journaux ou de charger les fichiers de configuration écrits par l’application principale.
- Cycle de vie identique : le side-car est déployé, démarré, arrêté et mis à l’échelle parallèlement à l’application principale.
Cas d’utilisation clés du modèle Sidecar
Les side-cars sont incroyablement polyvalents. Certaines des applications les plus courantes incluent :
1. Proxy de service Mesh (par exemple, Envoy, Linkerd)
Au lieu que votre application effectue des appels HTTP directs vers d’autres services, elle envoie des requêtes à son proxy side-car local. Le proxy side-car gère le routage, les tentatives, l’équilibrage de charge, la coupure de circuit et le chiffrement TLS mutuel (mTLS), puis transmet la demande. L’application reste totalement ignorante de ces complexités du réseau.
2. Collecte et transfert de journaux (par exemple, Fluent Bit)
Votre application écrit simplement ses instructions de journal sur la sortie standard ou dans un fichier journal local. Un conteneur side-car surveille ce fichier, analyse les journaux et les transmet à un moteur d’analyse central comme Elasticsearch ou Datadog.
3. Configuration et rechargement secret
Un side-car peut surveiller un serveur distant (comme Consul ou Vault) pour les mises à jour de configuration ou les rotations de clés cryptographiques. Lorsqu’un changement est détecté, il télécharge les nouveaux fichiers sur un volume partagé et signale à l’application principale de les recharger, sans avoir besoin de redémarrer.
Exemple d’implémentation de Kubernetes
La configuration d’un side-car est simple dans Kubernetes. Voici une configuration YAML simple montrant un conteneur d’application écrivant des journaux sur un volume partagé, et un conteneur side-car Fluent Bit lisant et expédiant ces journaux :
apiVersion: v1
kind: Pod
metadata:
name: app-with-logging-sidecar
labels:
app: billing-service
spec:
containers:
# 1. Primary Application Container
- name: web-app
image: node:18-alpine
command: ["/bin/sh", "-c"]
args:
- >
while true; do
echo "$(date) [INFO] Transaction processed successfully" >> /var/log/app/output.log;
sleep 5;
done
volumeMounts:
- name: shared-logs
mountPath: /var/log/app
# 2. Sidecar Container (Log Shipper)
- name: log-shipper
image: fluent/fluent-bit:latest
volumeMounts:
- name: shared-logs
mountPath: /var/log/app
# In a real setup, Fluent Bit config would read /var/log/app/output.log
# and forward it to an external logging system.
# Shared disk storage accessible by both containers
volumes:
- name: shared-logs
emptyDir: {}
Avantages et inconvénients du modèle side-car
Comme tout modèle de conception, les side-cars comportent des compromis :
| Avantage (Pro) | Inconvénient (Con) |
|---|---|
| Agnostique du langage : le side-car s’exécute dans son propre environnement. Vous pouvez utiliser le même assistant side-car à côté des applications Go, Java, Python ou Ruby. | Surcharge de ressources : l’exécution de plusieurs conteneurs par pod augmente la consommation du processeur et de la mémoire. |
| Cycle de vie découplé : les équipes d’infrastructure peuvent mettre à jour les correctifs de sécurité du side-car sans toucher au code de l’application. | Complexité accrue : la gestion de deux fois plus de conteneurs complique les configurations de déploiement, le débogage et la planification. |
| Isolement indépendant des pannes : si le conteneur side-car tombe en panne, Kubernetes peut le redémarrer automatiquement sans supprimer l’application principale. | Légère latence du réseau : le routage du trafic via un side-car proxy local ajoute un petit saut, bien qu’il soit généralement négligeable (< 1ms). |
Conclusion
Le modèle Sidecar est un élément fondamental des architectures cloud natives modernes. En isolant les préoccupations transversales, telles que le proxy réseau, la sécurité, la journalisation et la gestion de la configuration, dans un processus complémentaire distinct, il permet aux développeurs de se concentrer uniquement sur la création de valeur commerciale.
Bien qu’il entraîne une surcharge de ressources supplémentaire et nécessite une gestion efficace des plates-formes d’orchestration de conteneurs telles que Kubernetes, les avantages de bases de code plus propres, de flexibilité linguistique et de mise à l’échelle indépendante en font un modèle indispensable pour les microservices d’entreprise.