🎯 OBJECTIF
Comprendre comment :
connect-configs, connect-offsets, connect-status) coordonnent le clustertasks.max selon la nature du travail🧠 MODÈLE MENTAL
Connect est un pool de workers JVM qui exécutent des connectors sous forme de tasks. Tu configures en JSON, le framework gère transport, offsets, retries, rebalance, DLQ. Ce n'est pas un moteur de transformation — c'est du transport + transformations stateless. Enrichissement, agrégation, join → Kafka Streams ou Flink.
La distinction fondamentale : un worker n'appartient pas à un connector. C'est un pool partagé. Les tasks de tous les connectors se répartissent sur tous les workers disponibles. Ajouter un worker bénéficie à l'ensemble du cluster, pas à un seul connector.
Prérequis : kafka-core-model (topics, partitions, offsets, consumer groups).
Connect déplace des données entre Kafka et le reste du monde dans les deux directions.
flowchart LR
PG["Postgres SIE\n(WAL)"] -->|Debezium Source| K["Kafka\nsie.stock.stock"]
K -->|JDBC Sink| REP["Postgres reporting\n(UPSERT)"]mermaidsie.stock.stock.sie.stock.stock et fait des UPSERT dans une table de reporting.Source et sink sont indépendants — leur seul point de rendez-vous est le topic Kafka. Plusieurs sinks peuvent lire le même topic sans coordination.
Confusion fréquente — trois outils, trois rôles distincts.
| Outil | Rôle | Quand l'utiliser |
|---|---|---|
| Connect | Transport Kafka ↔ systèmes externes + SMT stateless | "Je veux que les changements de ma table arrivent dans un topic" |
| Kafka Streams | Librairie Java embarquée dans ton appli pour transformer topics → topics (stateful) | Enrichissement, agrégation, windowing, join. Dans ton jar Spring Boot. |
| Flink | Runtime de stream processing autonome, multi-langage | Même besoin que Streams mais avec state énorme, scalabilité horizontale forte, SQL/Python, exactly-once bout en bout |
🚨 Connect n'est pas un ETL
Si tu chaînes 10 SMT avec des conditions complexes, tu es dans le mauvais outil. Les SMT sont stateless — un message en entrée, un message en sortie, sans mémoire. Pour de l'enrichissement ou du join → Kafka Streams ou Flink.
Trois notions à ne pas confondre.
sie-stock-source). Décide combien de tasks créer selon le travail disponible.flowchart TB
subgraph Cluster["Cluster Connect — 3 workers"]
W1["Worker A"]
W2["Worker B"]
W3["Worker C"]
end
C1["sie-stock-source\n(Debezium, 1 task)"] -.-> W1
C2["reporting-sink\n(JDBC Sink, 3 tasks)"] -.-> W1
C2 -.-> W2
C2 -.-> W3
C3["es-search-sink\n(Elastic Sink, 2 tasks)"] -.-> W2
C3 -.-> W3mermaidLe Worker A exécute la task Debezium et une task JDBC Sink. Pas de pod dédié par connector — les tasks se distribuent sur le pool. Ajouter un worker bénéficie à tous les connectors simultanément.
Les workers ne se parlent pas directement. Toute coordination passe par trois topics Kafka compacted partagés par tout le cluster.
| Topic | Contenu | Pourquoi compacted |
|---|---|---|
connect-configs |
Config JSON de tous les connectors | On veut la version courante, pas l'historique |
connect-offsets |
Dernier offset source par task (LSN Debezium, binlog pos…) | On veut le dernier offset, pas l'historique |
connect-status |
État de chaque task (RUNNING / FAILED / PAUSED) | On veut l'état actuel |
Séquence d'un POST de nouvelle config :
POST /connectors envoyé sur Worker A.connect-configs.Séquence de démarrage d'un worker :
connect-configs → connaît tous les connectors.connect-offsets → sait où reprendre les sources.connect-status → sait quelles tasks doivent tourner.🔑 Conclusion clé
Aucun état critique sur disque local. Un worker tout neuf devient opérationnel en lisant uniquement ces 3 topics. Un worker qui crashe et revient n'a rien perdu.
La source de vérité du cluster est connect-configs, pas ton Git. Si tu modifie le JSON dans Git sans faire le PUT correspondant, le topic ne change pas, les workers ne voient rien.
🚨 Drift silencieux
Git affiche v2, le cluster tourne v1. Aucune erreur, aucun log. Le drift silencieux est le pire scénario ops — découvert uniquement lors d'un incident.
Trois patterns pour synchroniser Git → cluster :
Option A — Script CI (correct)
for f in connectors/*.json; do
curl -X PUT -H "Content-Type: application/json" \
"$CONNECT_URL/connectors/$(basename $f .json)/config" \
--data "@$f"
donebashDéclenché par GitHub Actions / GitLab CI sur chaque merge dans main.
Option B — GitOps avec Strimzi (recommandé sur k8s)
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnector
metadata:
name: sie-stock-source
labels:
strimzi.io/cluster: connect-sie
spec:
class: io.debezium.connector.postgresql.PostgresConnector
tasksMax: 1
config:
database.hostname: pg-sie.prod.internal
# …yamlkubectl apply ou ArgoCD. L'opérateur Strimzi réconcilie : toute modification manuelle via API REST est écrasée au cycle suivant. Git devient officiellement la source de vérité.
tasks.max est un plafond, pas le parallélisme réel. Le connector décide au démarrage combien de tasks il peut réellement créer selon le parallélisme naturel du travail.
flowchart TD
Q{"Nature du travail ?"}
Q -->|"Flux séquentiel unique\nWAL, binlog"| A["1 task\n(Debezium PG)"]
Q -->|"N sources indépendantes\nN tables à poll"| B["min(tasks.max, N tables)\n(JDBC Source)"]
Q -->|"Consumer d'un topic\nà P partitions"| C["min(tasks.max, P partitions)\n(tous les sinks)"]mermaidCas Debezium Postgres : toujours tasks.max=1. Le WAL est strictement séquentiel — un seul curseur possible. Mettre 2 ne crée pas 2 tasks.
Cas JDBC Sink : min(tasks.max, nombre de partitions). Avec 12 partitions et 20 tasks → 12 tasks actives, 8 oisives. Gâchis.
Un connector Debezium capture N tables avec 1 seule task — pas un connector par table. "table.include.list": "stock.stock,stock.movement,client.client" → 1 connector, 1 task, 1 replication slot.
⚡ TL;DR — chaque concept en une ligne
Workers / Connectors / Tasks
✓ Pool JVM partagé qui distribue les tasks de tous les connectors — pas un pod par connector.
⚠ tasks.max est un plafond — le connector décide le parallélisme réel selon le travail disponible.
3 topics internes
✓ connect-configs, connect-offsets, connect-status — tout l'état du cluster dans Kafka.
⚠ Aucun état critique sur disque local : un worker peut crasher et reprendre sans rien perdre.
Source de vérité = connect-configs, pas Git ✓ Le cluster vit dans le topic — Git n'est que la bibliothèque des artefacts désirés. ⚠ Commit sans PUT = drift silencieux. Anti-drift : pipeline CI ou GitOps Strimzi.
tasks.max ✓ Plafond de parallélisme — 1 pour CDC séquentiel, min(tasks.max, N) pour JDBC Source et sinks. ⚠ Pour Debezium Postgres, un seul slot/WAL séquentiel — mettre tasks.max=4 ne crée pas 4 tasks.
🎓 À retenir