Guide principal : Apache Kafka en production en 2026 : panorama complet
Tutoriels reliés : Producers et consumers idempotents · Kafka Streams 4.2 — agrégations et fenêtres
Depuis la sortie d’Apache Kafka 4.0 en mars 2025, ZooKeeper a totalement disparu du moteur. KRaft, le protocole de consensus interne hérité de Raft, gère désormais seul les métadonnées du cluster — élections de leader, configuration des topics, ACL, allocation des partitions. Pour une équipe qui découvre Kafka 4.2 en 2026, cela change deux choses concrètes : il n’y a plus de processus ZooKeeper à installer, à monitorer, à patcher ; et la procédure de bootstrap d’un cluster passe par un identifiant de cluster, des nœuds aux rôles explicites (controller, broker ou les deux) et un quorum dédié aux contrôleurs.
Ce tutoriel construit pas à pas un cluster Kafka 4.2 en mode KRaft sur trois VPS Linux : trois nœuds combinés (controller + broker) pour démarrer, suffisamment robustes pour absorber la perte d’une machine sans interruption. Les commandes ont été testées contre la documentation officielle Apache Kafka 4.2 et restent valables pour 4.x.
Prérequis
- Trois VPS Linux Ubuntu 24.04 LTS ou Debian 12 — 4 vCPU, 8 Go de RAM, 80 Go de SSD chacun (un Hetzner CX32 ou un Hostinger KVM 4 suffisent)
- OpenJDK 21 ou Java 25 — Kafka 4.2 supporte officiellement Java 17, 21 et 25
- Accès root SSH et un firewall qui laisse passer les ports 9092 (broker) et 9093 (controller) entre les trois machines
- Niveau attendu : intermédiaire, bases Linux et notions de réseau
- Temps estimé : 90 minutes pour un premier déploiement
Étape 1 — Installer Java et télécharger Kafka 4.2
Kafka tourne sur la JVM et n’a pas besoin de dépendance externe au-delà de Java. La version 4.2 a ajouté le support officiel de Java 25, mais Java 21 LTS reste le choix le plus prudent en production : il est sous support standard d’Eclipse Adoptium pendant au moins quatre ans depuis sa sortie de septembre 2023 (soit minimum septembre 2027), avec extension probable au-delà. Sur chacun des trois nœuds, on installe le JDK puis on télécharge la distribution binaire de Kafka depuis l’archive officielle Apache.
sudo apt update
sudo apt install -y openjdk-21-jdk wget
java -version
# Téléchargement de Kafka 4.2.0 — Scala 2.13 est le binaire recommandé
cd /opt
sudo wget https://downloads.apache.org/kafka/4.2.0/kafka_2.13-4.2.0.tgz
sudo tar -xzf kafka_2.13-4.2.0.tgz
sudo mv kafka_2.13-4.2.0 kafka
sudo useradd -r -d /opt/kafka -s /bin/false kafka
sudo chown -R kafka:kafka /opt/kafka
La sortie de java -version doit afficher openjdk version "21" ou plus récent. Si le binaire java est introuvable, vérifier que JAVA_HOME est exporté dans /etc/profile.d/java.sh ou laisser update-alternatives faire le travail. Le téléchargement pèse environ 120 Mo ; sur une connexion ouest-africaine, comptez deux à cinq minutes par nœud.
Étape 2 — Générer l’identifiant de cluster
En KRaft, chaque cluster a un identifiant unique de 22 caractères généré une seule fois. Toutes les machines du cluster partagent cet identifiant pour se reconnaître, et il sert également de signature pour empêcher un broker d’une autre installation de rejoindre par erreur. On le génère sur le premier nœud puis on le réutilise tel quel sur les deux autres.
sudo -u kafka /opt/kafka/bin/kafka-storage.sh random-uuid
# Exemple de sortie
# WJxR2KdLT_qV9bGq3oZc4w
L’identifiant retourné, ici WJxR2KdLT_qV9bGq3oZc4w, doit être noté dans un endroit sûr : on en aura besoin à l’étape du format du stockage. Il s’agit d’un UUID encodé en Base64 URL-safe ; sa génération est entièrement locale et ne contacte aucun serveur.
Étape 3 — Configurer server.properties pour le mode KRaft combiné
Le fichier config/server.properties de la distribution officielle est déjà préparé pour KRaft depuis la version 4.0. Trois propriétés font tout le travail : process.roles qui définit le rôle du nœud (controller, broker ou les deux), node.id qui doit être unique par nœud, et controller.quorum.bootstrap.servers qui liste les contrôleurs du quorum. Sur le premier nœud (que l’on appellera kafka1), on édite :
# /opt/kafka/config/server.properties — nœud kafka1
process.roles=controller,broker
node.id=1
controller.quorum.voters=1@kafka1.example.com:9093,2@kafka2.example.com:9093,3@kafka3.example.com:9093
listeners=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
advertised.listeners=PLAINTEXT://kafka1.example.com:9092
controller.listener.names=CONTROLLER
inter.broker.listener.name=PLAINTEXT
log.dirs=/var/lib/kafka/data
num.partitions=3
default.replication.factor=3
min.insync.replicas=2
auto.create.topics.enable=false
Quelques nuances importantes. controller.quorum.voters est le format statique historique (liste explicite des nœuds au format node-id@host:port), c’est l’approche que nous utilisons ici car la plus simple pédagogiquement. Kafka 4.x supporte également un format dynamique controller.quorum.bootstrap.servers via le KIP-853, mais les deux sont mutuellement exclusifs dans un même server.properties ; pour passer au dynamique il faut formater le cluster avec kafka-storage.sh format --initial-controllers et ne mettre que bootstrap.servers. process.roles=controller,broker est ce qu’on appelle un déploiement combiné. La documentation officielle Apache Kafka précise que ce mode est destiné au développement et aux tests, pas à la production critique — pour la production, séparer physiquement les contrôleurs des brokers est la pratique recommandée. Nous l’utilisons ici car le tutoriel vise un environnement de pré-production ou de petit cluster non critique ; la migration vers une topologie séparée se fait ensuite par rolling restart. Le port 9093 est par convention dédié au trafic interne du quorum ; il ne doit jamais être exposé sur Internet. min.insync.replicas=2 couplé à default.replication.factor=3 est le doublet qui permettra à la fois la durabilité (perte d’une machine = pas de perte de message confirmé) et la disponibilité en écriture.
Sur kafka2, on change node.id=2 et advertised.listeners=PLAINTEXT://kafka2.example.com:9092. Sur kafka3, idem avec node.id=3. La liste des voters reste strictement identique sur les trois nœuds — c’est ce qui permet au quorum de se reconnaître au premier démarrage.
Étape 4 — Formater le stockage avec l’identifiant de cluster
Avant le tout premier démarrage, chaque nœud doit initialiser ses répertoires de log avec l’UUID de cluster généré à l’étape 2. Cette opération s’effectue une seule fois et ne doit jamais être rejouée sur un cluster en production sous peine d’effacer toutes les métadonnées — d’où le mot format, choisi par les développeurs Kafka pour souligner l’analogie avec un disque que l’on prépare.
CLUSTER_ID="WJxR2KdLT_qV9bGq3oZc4w"
sudo mkdir -p /var/lib/kafka/data
sudo chown -R kafka:kafka /var/lib/kafka
sudo -u kafka /opt/kafka/bin/kafka-storage.sh format \
--config /opt/kafka/config/server.properties \
--cluster-id "$CLUSTER_ID"
La sortie attendue est Formatting metadata directory /var/lib/kafka/data with metadata.version 4.2-IV0. La version des métadonnées 4.2-IV0 indique que le cluster sera entièrement en mode KRaft natif. Cette commande crée le fichier meta.properties dans log.dirs ; si vous le supprimez par erreur, le broker refusera de démarrer.
Étape 5 — Créer le service systemd et démarrer le cluster
En production on ne lance jamais Kafka avec kafka-server-start.sh en tâche de fond. Un service systemd assure le redémarrage automatique, la journalisation centralisée et la séparation propre des permissions. Le fichier ci-dessous fonctionne sur Ubuntu 24.04 et Debian 12.
# /etc/systemd/system/kafka.service
[Unit]
Description=Apache Kafka 4.2 — KRaft mode
After=network.target
[Service]
Type=simple
User=kafka
Group=kafka
ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties
ExecStop=/opt/kafka/bin/kafka-server-stop.sh
Restart=on-failure
LimitNOFILE=100000
Environment="KAFKA_HEAP_OPTS=-Xms2G -Xmx2G"
[Install]
WantedBy=multi-user.target
On active et démarre le service sur les trois nœuds, en commençant par celui qui aura l’node.id=1 :
sudo systemctl daemon-reload
sudo systemctl enable --now kafka
sudo systemctl status kafka
sudo journalctl -u kafka -f --since "5 min ago"
Le journal doit afficher au bout de quinze à trente secondes une ligne « KafkaServer id=1 started » sur chaque nœud. Si vous voyez en boucle « Timed out waiting for connection to quorum », c’est presque toujours le firewall : ouvrir le port 9093 entre les trois machines avec UFW ou nftables règle le problème.
Étape 6 — Valider le quorum et créer le premier topic
Une fois les trois nœuds démarrés, on vérifie que le quorum de contrôleurs s’est bien constitué. L’outil kafka-metadata-quorum.sh est le diagnostic officiel de KRaft : il affiche l’état du leader, les followers à jour et le lag éventuel.
/opt/kafka/bin/kafka-metadata-quorum.sh \
--bootstrap-server kafka1.example.com:9092 \
describe --status
La sortie attendue ressemble à ClusterId, LeaderId: 1, LeaderEpoch: 4, HighWatermark: 87, MaxFollowerLag: 0, MaxFollowerLagTimeMs: 12. MaxFollowerLag: 0 signifie que les trois contrôleurs sont parfaitement synchronisés. Si la valeur grimpe et reste élevée, c’est un signal de latence réseau ou de saturation disque sur un nœud.
/opt/kafka/bin/kafka-topics.sh \
--bootstrap-server kafka1.example.com:9092 \
--create --topic ventes-mobile-money \
--partitions 6 --replication-factor 3 \
--config min.insync.replicas=2
La création doit retourner « Created topic ventes-mobile-money. » en moins d’une seconde. La vérification fine se fait avec --describe : chaque partition doit avoir trois Replicas et trois Isr (In-Sync Replicas). Si l’un des nœuds n’apparaît pas dans la liste ISR, le broker correspondant n’a pas fini son enregistrement auprès du quorum.
Étape 7 — Publier et consommer un message de test
Pour confirmer que le cluster fonctionne de bout en bout, on utilise les producers et consumers CLI fournis avec la distribution. Dans un premier terminal, on ouvre un consumer ; dans un second, on publie quelques messages.
# Terminal 1 — consumer
/opt/kafka/bin/kafka-console-consumer.sh \
--bootstrap-server kafka1.example.com:9092 \
--topic ventes-mobile-money \
--from-beginning
# Terminal 2 — producer
/opt/kafka/bin/kafka-console-producer.sh \
--bootstrap-server kafka1.example.com:9092 \
--topic ventes-mobile-money
> {"client":"+221771234567","montant":15000,"moyen":"Wave"}
> {"client":"+221771234568","montant":24500,"moyen":"Orange Money"}
Les deux lignes JSON doivent apparaître immédiatement côté consumer. Si rien ne sort, vérifier que le DNS résout bien kafka1.example.com sur la machine cliente et que le port 9092 est ouvert. C’est l’erreur n°1 des premiers déploiements : le client se connecte au bootstrap, reçoit la liste des advertised.listeners, et n’arrive plus à joindre les brokers nommés.
Erreurs fréquentes
| Erreur | Cause probable | Solution |
|---|---|---|
UnknownHostException: kafkaN.example.com |
DNS interne mal configuré côté client | Ajouter les entrées dans /etc/hosts ou pointer un DNS privé |
InvalidClusterIdException |
UUID différent entre meta.properties et --cluster-id |
Supprimer log.dirs sur le nœud fautif et reformater avec le bon UUID |
Connection to node -1 could not be established |
Port 9092 ou 9093 bloqué par le firewall | Ouvrir les ports entre nœuds avec UFW ou Security Group |
NotEnoughReplicasException |
Un broker est down et min.insync.replicas ne peut plus être satisfait |
Vérifier l’état du quorum et redémarrer le broker manquant |
InconsistentNodeIdException |
Deux nœuds partagent le même node.id |
Modifier server.properties et reformater |
Sécuriser et monitorer la suite
Le cluster fonctionne en clair sur PLAINTEXT, ce qui convient pour un environnement de pré-production isolé sur un VPC. Pour la mise en production, deux ajouts s’imposent : activer SASL/SCRAM ou mTLS sur le listener client (le listeners devient alors SASL_SSL://...), et brancher Prometheus avec l’kafka-exporter de Danielqsj pour exposer les métriques de lag, débit et état des contrôleurs. La page officielle « Operations » de Kafka 4.2 documente la configuration JMX et les broker-configs les plus utiles à monitorer.
Au Sénégal, en Côte d’Ivoire ou au Mali, un cluster auto-hébergé sur trois VPS Hetzner CX32 à Helsinki revient à environ vingt euros par mois — l’équivalent de treize mille FCFA — pour un débit largement suffisant pour une plateforme mobile money de taille moyenne. Comptez en revanche soixante à cent millisecondes de latence aller-retour depuis Dakar, ce qui exclut les usages temps réel dur (trading) mais reste très acceptable pour de l’ingestion d’événements métier ou de la synchronisation cross-services.
Ressources et références
- Documentation Apache Kafka 4.2 — section KRaft
- KIP-833 : marqueur de production-ready pour KRaft
- Annonce de release Apache Kafka 4.2.0 (17 février 2026)
- Référence complète des broker configs 4.2
Pourquoi KRaft change la donne opérationnelle
Pendant douze ans, Apache Kafka a délégué la gestion des métadonnées du cluster à Apache ZooKeeper, un service tiers maintenu par une fondation Apache distincte. Ce choix architectural des origines avait du sens en 2011 : ZooKeeper offrait déjà un service de coordination distribué éprouvé, capable de gérer les élections de leader, les configurations partagées et les abonnements aux changements. Mais avec le temps, la duplication des rôles est devenue coûteuse. Une équipe qui souhaitait administrer Kafka devait également comprendre les arcanes de ZooKeeper : znodes, observateurs, sessions, ACL spécifiques, version d’enregistrement de snapshot, paramètres tickTime et initLimit. Une montée de version Kafka exigeait parfois une montée de version ZooKeeper concomitante. Une perte de quorum ZK provoquait un cluster Kafka read-only immédiat.
KRaft, abréviation de « Kafka Raft », règle ces frictions en internalisant la coordination dans le processus Kafka lui-même. Le protocole est basé sur Raft, plus simple à raisonner que ZAB (ZooKeeper Atomic Broadcast), et il stocke ses journaux directement dans la même structure de log que les topics métier. Concrètement, le contrôleur actif conserve un topic interne __cluster_metadata qui contient l’intégralité des décisions du cluster — création de topics, configuration, assignation de partitions, ajout d’ACL. Les autres contrôleurs répliquent ce log et peuvent reprendre le rôle de leader sans relire tout l’historique : ils maintiennent en permanence une copie à jour.
Pour les équipes ouest-africaines qui démarrent un projet d’event streaming en 2026, la simplification est radicale : un seul binaire à déployer, un seul fichier de configuration à comprendre, un seul jeu de métriques à monitorer. La courbe d’apprentissage initiale tombe d’environ 40 % par rapport à un déploiement Kafka 3.5 avec ZooKeeper. C’est un gain mesurable pour une équipe de quatre à six personnes qui n’a pas le luxe d’un SRE dédié.
Comprendre les rôles : controller, broker ou combiné
Une des subtilités du mode KRaft est qu’un nœud Kafka peut endosser deux rôles techniquement distincts. Un controller participe au quorum qui maintient les métadonnées du cluster ; il vote, propose, valide les changements d’état global. Un broker reçoit les producteurs, sert les consommateurs, stocke et réplique les partitions de topics applicatifs. Sur un nœud combiné — c’est ce que nous avons configuré — les deux rôles cohabitent dans la même JVM, ce qui simplifie la topologie au prix d’un couplage entre la charge applicative et la santé du quorum.
Pour les clusters de moins de cinq nœuds, le combiné est tolérable en pré-production ou pour des charges non critiques, mais la documentation Apache Kafka indique explicitement que le mode combiné n’est pas supporté pour les workloads de production. À partir de six nœuds, ou pour toute charge de production sérieuse, séparer les deux rôles est obligatoire. La séparation prend la forme d’un quorum de trois ou cinq contrôleurs dédiés (par exemple sur des machines plus modestes, 2 vCPU et 4 Go de RAM suffisent) et de N brokers applicatifs dimensionnés pour le débit. La transition d’un déploiement combiné vers un déploiement séparé reste possible mais demande un rolling restart coordonné, un exercice qui mérite d’être répété en pré-production avant d’être tenté sur le cluster nominal.
Choisir un facteur de réplication et min.insync.replicas
Les deux paramètres les plus discutés en revue d’architecture sont default.replication.factor et min.insync.replicas. Le premier détermine combien de copies physiques chaque message aura sur disque ; le second fixe combien de ces copies doivent confirmer l’écriture avant qu’un producteur en mode acks=all reçoive un accusé de réception. Avec un facteur de 3 et un minimum de 2, on tolère la perte d’une machine sans interruption d’écriture ; avec un facteur de 3 et un minimum de 3, on garantit que toutes les répliques sont à jour, au prix d’un blocage immédiat dès qu’un nœud devient indisponible.
Le doublet recommandé pour la grande majorité des cas d’usage — paiement mobile, ingestion de logs, change data capture — est précisément RF=3, min.isr=2. Il offre la meilleure pondération entre durabilité et disponibilité. Pour des données très sensibles, comme le journal de transactions d’un wallet financier, on peut basculer ponctuellement sur RF=5, min.isr=3 via la configuration du topic, sans toucher au défaut du cluster.
Sauvegarde et rétention
Kafka n’est pas une base de données et ne propose pas de dump au sens classique. La sauvegarde s’organise autrement : pour les données chaudes, le facteur de réplication tient lieu de protection contre la perte de disque ; pour la résilience contre une corruption logique ou la perte simultanée du cluster entier, on s’appuie sur deux mécanismes complémentaires. Le tiered storage, introduit en KIP-405 et passé en GA dans Kafka 3.6, permet de déporter les segments anciens vers un object store compatible S3 — MinIO auto-hébergé ou Backblaze B2 (autour de 6 USD/To-mois) pour rester en zone européenne abordable. Le Mirror Maker 2, livré dans la distribution, réplique en permanence les topics vers un cluster secondaire dans une autre zone géographique.
La rétention par défaut sur les topics est de sept jours (paramètre log.retention.hours=168), sans plafond de taille (log.retention.bytes=-1, illimité). Pour un topic d’événements métier que l’on veut rejouer en cas de bug applicatif, on porte typiquement retention.ms à 30 jours (2592000000). Pour des données réglementaires soumises à OHADA ou à la loi 2008-12 sénégalaise sur les données personnelles, on archive les segments dans MinIO et on configure le topic en cleanup.policy=compact pour ne conserver que le dernier événement par clé.
Mise en réseau côté ouest-africain
Une question récurrente lors des audits techniques en région UEMOA : où héberger physiquement le cluster ? Trois options se dégagent en mai 2026. Hetzner Helsinki ou Falkenstein, à partir de 4,49 euros par mois pour un CX22 (ARM, 2 vCPU, 4 Go, 40 Go SSD) — la latence aller-retour vers Dakar tourne autour de 80 à 110 ms, parfaitement acceptable pour un usage event-driven asynchrone. OVH Roubaix ou Strasbourg, similaire en latence avec une présence commerciale plus visible localement. Enfin, pour les charges réglementaires qui exigent une donnée souveraine, on s’oriente vers les data centers locaux : PAIX Dakar (en construction 2025) et les opérateurs raccordés au câble sous-marin ACE pour le Sénégal ; Raxio Côte d’Ivoire, Equinix Abidjan AB1 et PAIX Abidjan pour Abidjan. Comptez deux à trois fois le prix d’un VPS européen mais une latence intra-Afrique sous les 25 ms.
Quelle que soit l’option, on veille à monter Kafka derrière un VPC privé et à n’exposer publiquement que les ports strictement nécessaires. Le port 9093 du quorum ne doit jamais quitter le sous-réseau interne ; le port 9092 est exposé soit via un load-balancer interne, soit via TLS+SASL si les producteurs sont externes au VPC.
Retour au guide principal : Apache Kafka en production en 2026 : panorama complet.