Ein tiefer Einblick in Kafka ZooKeeper-Verbindungsprobleme
Fehlerbehebung bei Kafka ZooKeeper-Verbindungsfehlern mit praktischen Überprüfungen von Konfiguration, Netzwerk, Timeouts, Protokollen und Broker-Last.
Ein tiefer Einblick in Kafka ZooKeeper-Verbindungsprobleme
Kafka ZooKeeper-Verbindungsprobleme betreffen hauptsächlich ältere Kafka-Cluster und Cluster, die nicht auf den KRaft-Modus umgestellt wurden. Neuere Kafka-Bereitstellungen können ohne ZooKeeper auskommen, aber viele Produktionssysteme sind noch darauf angewiesen. Wenn Ihre Broker zookeeper.connect in server.properties verwenden, ist ZooKeeper weiterhin Teil Ihrer Steuerungsebene und verdient die gleiche Aufmerksamkeit wie Kafka selbst.
Wenn ein Kafka-Broker seine ZooKeeper-Sitzung nicht aufrechterhalten kann, können die Symptome größer wirken als ein einfaches Verbindungsproblem. Broker können neu starten. Controller-Wahlen können sich wiederholen. Partitionen können nicht verfügbar werden. Protokolle können Sitzungsablauf, Controller-Rücktritt oder wiederholte Wiederverbindungsversuche zeigen. Produzenten und Konsumenten sehen möglicherweise nur die nachgelagerten Auswirkungen: Metadatenfehler, Timeouts oder instabile Leader.
Beginnen Sie mit der Rolle, die ZooKeeper spielt. In ZooKeeper-basierten Kafka-Clustern registrieren sich Broker dort, die Controller-Wahl hängt davon ab und die Koordination von Cluster-Metadaten erfolgt darüber. Wenn ein Broker seine ZooKeeper-Sitzung lange genug verliert, sodass die Sitzung abläuft, behandelt Kafka diesen Broker als aus dem Cluster entfernt. Selbst wenn der Broker-Prozess noch läuft, kann der Cluster die Führung von ihm wegnehmen.
Der erste Check ist langweilig und fängt das Problem oft ein: Überprüfen Sie zookeeper.connect auf jedem Broker.
zookeeper.connect=zk01.example.com:2181,zk02.example.com:2181,zk03.example.com:2181/kafka
zookeeper.connection.timeout.ms=18000
zookeeper.session.timeout.ms=18000
Die Verbindungszeichenfolge sollte die Ensemble-Mitglieder auflisten, die Kafka erreichen kann. Wenn Sie einen Chroot-Pfad wie /kafka verwenden, geben Sie ihn konsistent auf jedem Broker an. Konfigurieren Sie nicht die Hälfte der Broker mit /kafka und die andere Hälfte ohne; sie verhalten sich so, als ob sie mit verschiedenen Kafka-Clustern sprechen. Wenn Sie einen Chroot verwenden, erstellen Sie ihn zuerst oder bestätigen Sie seine Existenz mit ZooKeeper-Tools.
Überprüfen Sie DNS sowie den Text der Konfiguration. Ein Hostname, der von Ihrem Laptop korrekt aufgelöst wird, kann von einem Broker-Subnetz aus fehlschlagen. Führen Sie die Überprüfungen vom Kafka-Broker-Host aus durch, nicht von einer Bastion, es sei denn, die Bastion hat denselben Netzwerkpfad.
getent hosts zk01.example.com
nc -vz zk01.example.com 2181
nc -vz zk02.example.com 2181
nc -vz zk03.example.com 2181
Eine erfolgreiche TCP-Verbindung beweist nicht, dass ZooKeeper gesund ist, aber eine fehlgeschlagene Verbindung reicht aus, um weiter nach Firewalls, Sicherheitsgruppen, Routing, DNS oder Listener-Konfiguration zu suchen. Testen Sie jeden Kafka-Broker mit jedem ZooKeeper-Knoten. Teilkonnektivität ist schlimmer als ein sauberer Ausfall, da der Fehler möglicherweise nur auftritt, wenn ein Broker versucht, sich mit einem bestimmten Ensemble-Mitglied zu verbinden.
ZooKeepers Vier-Buchstaben-Befehle können helfen, wenn sie aktiviert sind. Viele Installationen schränken sie ein, also gehen Sie nicht davon aus, dass sie funktionieren. Wenn erlaubt, sollte ruok imok zurückgeben, und mntr kann nützliche Server-Statistiken anzeigen.
echo ruok | nc zk01.example.com 2181
echo mntr | nc zk01.example.com 2181
Wenn diese Befehle deaktiviert sind, verwenden Sie stattdessen die unterstützten Admin-Tools oder Ihren Monitoring-Stack. Der Punkt ist, eine einfache Frage zu beantworten: Hört ZooKeeper zu, nimmt am Ensemble teil und antwortet schnell?
Als nächstes überprüfen Sie die Gesundheit des ZooKeeper-Ensembles. Ein Drei-Knoten-Ensemble kann einen ausgefallenen ZooKeeper-Knoten tolerieren. Es kann nicht zwei tolerieren. Ein Fünf-Knoten-Ensemble kann zwei tolerieren. Vermeiden Sie Ensembles mit gerader Anzahl, da sie Kosten verursachen, ohne das Quorum in der erwarteten Weise zu verbessern. Drei und fünf sind übliche Wahlen.
Auf der ZooKeeper-Seite schauen Sie sich zoo.cfg an. Bestätigen Sie clientPort, tickTime, initLimit, syncLimit und Server-Zeilen. Stellen Sie sicher, dass die angegebenen Server-Hostnamen zwischen den ZooKeeper-Knoten erreichbar sind, nicht nur von den Kafka-Brokern. ZooKeeper-Peers benötigen ihre eigenen Quorum- und Leader-Wahl-Ports. Ein Kafka-Broker kann 2181 erreichen, während das ZooKeeper-Ensemble selbst ungesund ist, weil der Peer-Verkehr blockiert ist.
Die Anpassung des Sitzungs-Timeouts ist eine weitere häufige Fehlerquelle. Kafka fragt ZooKeeper nach einem Sitzungs-Timeout, aber ZooKeeper erzwingt Grenzen basierend auf seiner eigenen Konfiguration. In ZooKeeper beträgt das minimale Sitzungs-Timeout typischerweise 2 * tickTime und das maximale typischerweise 20 * tickTime, sofern nicht durch spezifische Servereinstellungen überschrieben. Das bedeutet, dass ein Kafka-Timeout-Wert außerhalb des zulässigen Bereichs von ZooKeeper angepasst werden kann.
Wenn tickTime=2000, liegt der übliche erlaubte Sitzungsbereich grob zwischen 4 Sekunden und 40 Sekunden. Eine Kafka-Einstellung wie zookeeper.session.timeout.ms=18000 passt in diesen Bereich. Ein sehr niedriges Timeout kann bei kurzen Netzwerkpausen oder Garbage-Collection-Pausen zu falschen Fehlern führen. Ein sehr hohes Timeout kann dazu führen, dass echte Broker-Fehler länger erkannt werden. Sie wählen zwischen Sensitivität und Stabilität.
Ändern Sie tickTime nicht leichtfertig. Es betrifft das ZooKeeper-Ensemble, nicht nur Kafka. Wenn Sie mehr Toleranz für Broker-Pausen benötigen, ist es oft besser, zunächst Kafkas zookeeper.session.timeout.ms, das JVM-Verhalten des Brokers und die Netzwerkgesundheit zu überprüfen, bevor Sie die ZooKeeper-Zeiteinstellungen ändern.
Protokolle erzählen normalerweise die Geschichte, wenn Sie sie nach Zeitstempeln ordnen. Suchen Sie auf Kafka-Brokern nach Nachrichten rund um ZooKeeper-Trennungen und Sitzungsablauf:
rg -i "zookeeper|session|expired|controller|reconnect" /var/log/kafka/server.log
Muster sind wichtiger als eine einzelne Zeile. Eine einmalige Wiederverbindung während eines geplanten ZooKeeper-Neustarts kann harmlos sein. Wiederholter Ablauf alle paar Minuten deutet auf Instabilität hin. Ablauf während der Garbage Collection deutet auf JVM-Pausen oder Broker-Überlastung hin. Ablauf zur gleichen Zeit auf vielen Brokern deutet auf ZooKeeper, das Netzwerk oder ein gemeinsames Infrastrukturereignis hin.
Überprüfen Sie auf ZooKeeper-Knoten Leader-Wechsel, fsync-Warnungen, Verbindungsdrosselung und lange Anforderungslatenz. ZooKeeper ist empfindlich gegenüber Festplattenlatenz, da es Transaktionsprotokolle schreibt. Eine langsame Festplatte kann dazu führen, dass der Dienst erreichbar erscheint, aber dennoch nicht schnell genug für stabile Sitzungen antwortet.
Netzwerklatenz und Paketverlust sind für ZooKeeper wichtiger als die reine Bandbreite. Kafka-Broker benötigen keinen großen Durchsatz zu ZooKeeper, aber sie benötigen zuverlässige, latenzarme Kommunikation. Wenn Broker und ZooKeeper über entfernte Netzwerke verteilt sind, erwarten Sie Probleme. Halten Sie sie nah beieinander. Vermeiden Sie in Cloud-Umgebungen, den Broker-zu-ZooKeeper-Verkehr durch unnötiges NAT, überlastete Firewalls oder Cross-Region-Pfade zu leiten.
Ressourcenkonflikte auf dem Kafka-Broker können genau wie ein ZooKeeper-Problem aussehen. Wenn die JVM für eine lange Garbage-Collection-Pause die Welt anhält, kann der Broker Heartbeats verpassen. Wenn die CPU ausgelastet ist, kann die Heartbeat-Verarbeitung verzögert werden. Wenn der Host in hoher I/O-Wartezeit steckt, kann Kafka möglicherweise nicht mit der Koordinationsarbeit Schritt halten. Überprüfen Sie die Broker-Metriken zu denselben Zeitstempeln wie die ZooKeeper-Trennungen.
Nützliche broker-seitige Fragen umfassen: Ist die Heap-Nutzung vor der Trennung gestiegen, ist die GC-Pausenzeit gestiegen, war die Festplatten-I/O-Wartezeit hoch, haben die Netzwerk-Retransmits zugenommen, und gab es gleichzeitig große Partitionsneuzuweisungen oder Leader-Bewegungen? Ein Broker, der unter Last leidet, benötigt möglicherweise weniger Partitions-Leader, eine bessere Festplatte, JVM-Tuning oder eine Verkehrsverschiebung. Das Erhöhen der ZooKeeper-Timeout-Werte kann das Symptom verbergen, ohne die Ursache zu beheben.
Konfigurationskonsistenz wird leicht übersehen. Alle Kafka-Broker im selben Cluster sollten dieselbe ZooKeeper-Verbindungszeichenfolge und denselben Chroot verwenden. Sie sollten auch eindeutige broker.id-Werte haben. Eine doppelte Broker-ID kann zu verwirrendem Registrierungsverhalten führen, da zwei Prozesse versuchen, denselben Broker darzustellen.
Wenn Sie kürzlich ZooKeeper-Hostnamen, Zertifikate, Firewall-Regeln oder Kafka-Broker-Konfigurationen geändert haben, vergleichen Sie den funktionierenden Broker mit dem fehlerhaften. Kleine Unterschiede sind häufig: ein alter DNS-Suffix, ein fehlender Chroot-Pfad, eine Sicherheitsgruppe, die an zwei Broker, aber nicht an den dritten angehängt ist, oder ein Tippfehler in einer systemd-Umgebungsdatei.
Die Wiederherstellung hängt davon ab, was kaputt gegangen ist. Wenn eine Firewall-Regel fehlte, beheben Sie sie und starten Sie den betroffenen Broker neu, wenn er sich nicht sauber wieder verbindet. Wenn ZooKeeper das Quorum verloren hat, stellen Sie zuerst das Quorum wieder her, bevor Sie Kafka-Broker neu starten. Wenn ein Broker aufgrund von Überlastung abgelaufen ist, kann ein Neustart ihn vorübergehend zurückbringen, aber das Problem wird zurückkehren, es sei denn, Sie beseitigen den Druck.
Verwenden Sie rollierende Neustarts. Das gleichzeitige Neustarten aller Kafka-Broker, weil ZooKeeper instabil war, kann einen Teilausfall in einen vollständigen Ausfall verwandeln. Bringen Sie die ZooKeeper-Gesundheit zurück, starten Sie dann Broker nacheinander neu oder stellen Sie sie wieder her, während Sie die Controller-Stabilität und die Partitionsführung beobachten.
Für langfristige Stabilität überwachen Sie beide Seiten. Überwachen Sie auf ZooKeeper die Anforderungslatenz, ausstehende Anforderungen, Leader-Wechsel, Follower-Synchronisationsstatus, Festplattenspeicher und Prozessneustarts. Überwachen Sie auf Kafka Controller-Wechsel, Offline-Partitionen, unter-replizierte Partitionen, Broker-Neustarts und Protokolle, die ZooKeeper-Sitzungsablauf erwähnen. Alarmieren Sie bei wiederholten Mustern, nicht nur bei vollständigem Prozess-Tod.
Die sauberste Lösung für Teams, die ein größeres Upgrade planen, könnte die Migration von ZooKeeper zu Kafkas KRaft-Modus sein. Das ist ein Projekt, kein Schritt zur Incident-Reaktion. Es erfordert Versionsplanung, Kompatibilitätsprüfungen und sorgfältige Migrationsarbeit. Behandeln Sie ZooKeeper bis dahin als Produktionsinfrastruktur. Halten Sie es klein, nah an Kafka, konsistent konfiguriert, überwacht und langweilig.
Ein praktisches Runbook-Muster ist es, während des Incidents eine kleine Matrix zu erstellen. Setzen Sie Kafka-Broker auf eine Achse und ZooKeeper-Knoten auf die andere. Füllen Sie jede Zelle mit dem Ergebnis von nc -vz host 2181 und, falls verfügbar, einer einfachen ZooKeeper-Gesundheitsprüfung. Dies verwandelt vage "Kafka kann ZooKeeper nicht erreichen"-Berichte in ein sichtbares Muster. Wenn jeder Broker zk02 nicht erreicht, untersuchen Sie zk02 oder seinen Netzwerkpfad. Wenn nur broker-4 keinen ZooKeeper-Knoten erreicht, untersuchen Sie den Host dieses Brokers, die Routingtabelle, DNS oder Firewall.
Zeitsynchronisation kann ebenfalls wichtig sein. ZooKeeper-Sitzungsmechanismen erfordern nicht perfekt identische Wanduhren für jede Operation, aber stark verschobene Uhren erschweren die Interpretation von Protokollen und können umgebende Automatisierung, Zertifikate und Überwachung stören. Halten Sie NTP oder chrony auf Kafka- und ZooKeeper-Knoten gesund. Wenn Zeitstempel während eines Ausfalls nicht übereinstimmen, verschwenden Leute Zeit damit, die falsche Ereignisreihenfolge zu verfolgen.
Seien Sie vorsichtig mit containerisierten oder orchestrierten ZooKeeper-Bereitstellungen. ZooKeeper speichert Identität und Daten auf der Festplatte. Wenn Pods verschoben werden und die persistente Identität verlieren, oder wenn die Service-Erkennung Clients auf Knoten verweist, die nicht bereit sind, kann Kafka instabiles Verbindungsverhalten sehen. StatefulSet-artige Identität, persistente Volumes, stabiles DNS und Readiness-Checks sind wichtig. Ein ZooKeeper-Ensemble sollte sich nicht wie eine Reihe von wegwerfbaren zustandslosen Web-Pods verhalten.
Sicherheitseinstellungen fügen eine weitere Ebene hinzu. Wenn SASL, TLS oder Netzwerkrichtlinien kürzlich eingeführt wurden, können Verbindungsfehler zunächst wie einfache Erreichbarkeitsprobleme aussehen. Überprüfen Sie, ob Kafka-Protokolle Authentifizierungsfehler, Handshake-Fehler oder Autorisierungsfehler anstelle von TCP-Timeouts zeigen. Ein Port kann offen sein, während die Sitzung dennoch fehlschlägt, weil der Broker sich nicht bei ZooKeeper authentifizieren kann.
Halten Sie nach dem Incident eine kurze Aufzeichnung des genauen Symptoms, der Ursache und der Behebung fest. ZooKeeper-Probleme wiederholen sich oft, weil die ursprüngliche Reparatur lokal war: eine Firewall-Regel, ein Broker-Neustart, eine Timeout-Erhöhung. Eine gute Post-Incident-Notiz sollte sagen, ob der Cluster ein Quorum hatte, welche Broker Sitzungen verloren haben, ob ISR geschrumpft ist, ob sich der Controller geändert hat und welche Überwachung es beim nächsten Mal früher erkennen wird.
Wenn Sie von Kubernetes oder einem anderen Scheduler aus Fehlerbehebung betreiben, überprüfen Sie auch, wo die Kafka- und ZooKeeper-Workloads gelandet sind. Ein netzwerkseitiges Problem auf Knotenebene, ein Festplattenproblem oder ein CPU-Engpass-Ereignis kann nur die dort geplanten Pods betreffen. Das Verschieben eines Pods kann das Problem scheinbar beheben, aber das eigentliche Problem kann der Host sein. Vergleichen Sie Ereignisse und Knotenmetriken, bevor Sie die Anwendung als repariert erklären.
Backups und Snapshots verdienen Vorsicht. ZooKeeper-Datenverzeichnisse sollten nicht leichtfertig gesnapshotet werden, während der Prozess aktiv ist, es sei denn, Ihre Backup-Methode ist dafür ausgelegt. Für Kafka-Metadaten kann ein beschädigter oder veralteter ZooKeeper-Zustand äußerst störend sein. Befolgen Sie die von ZooKeeper unterstützten Backup-Praktiken und testen Sie Wiederherstellungsverfahren außerhalb der Produktion. Ein Backup, das niemand wiederhergestellt hat, ist nur eine hoffnungsvolle Datei.
Die beste vorbeugende Maßnahme ist, ZooKeeper langweilig zu halten. Platzieren Sie es nicht zusammen mit schweren Kafka-Brokern, wenn Sie es vermeiden können. Halten Sie seine Festplatten zuverlässig. Halten Sie die Heap-Größe konservativ und überwacht. Beschränken Sie, wer die Ensemble-Mitgliedschaft ändern kann. Die meisten ZooKeeper-Vorfälle, die ich gesehen habe, wurden nicht durch exotische Fehler verursacht; sie kamen von gewöhnlicher Infrastrukturabweichung um einen kleinen Dienst, den jeder vergessen hatte, der kritisch war.