Cluster-Installation
Hier erfahren Sie, wie Sie PlantPulse für große Workloads als Master- und Worker-Node-Cluster konfigurieren. Sie können mit einem einzelnen Node starten und bei Erreichen der Durchsatzgrenze schrittweise skalieren.
Multi-Node ist nur „horizontale Skalierung"
Dieser Artikel behandelt den Master-/Worker-Cluster, bei dem die Infrastruktur (Aster TSDB, Kafka, Spark) auf mehrere Nodes aufgeteilt wird. Er kommt zum Einsatz, wenn die Durchsatzgrenze erreicht ist.
Die Installation mit getrennten Ebenen (Datalake und Anwendung auf verschiedenen Rechnern) wurde am 02.09.2026 entfernt. Alle Rechner sind nun Komplettinstallationen.
Wann skalieren Sie auf einen Cluster?
| Umgebungsgröße | Empfohlene Konfiguration | Hinweise |
|---|---|---|
| Tags ~5.000 | Einzelner Master | Kein Cluster erforderlich |
| Tags 5.000 – 50.000 | Master + 1–2 Worker | Analyse / Messaging verteilt |
| Tags 50.000+ | Master + 3+ Worker | Vollständige verteilte Operation |
Cluster-Topologie
Hardware-Anforderungen
Empfohlene Spezifikationen für jeden Worker-Node (der Master-Node folgt den Systemanforderungen — Data-Lake-Master 96 GB oder mehr):
| Kategorie | Minimal | Standard | Groß |
|---|---|---|---|
| CPU | 16 vCPU | 32 vCPU | 48 vCPU |
| Arbeitsspeicher | 67 GB oder mehr (der 60-GB-Worker-Container muss in 90 % des Host-RAMs passen — 64 GB liegt unter der Spezifikation) | 128 GB | 200+ GB |
| Datenträger | 200 GB NVMe | 1 TB NVMe | 4 TB NVMe |
| Netzwerk | 1 Gbps | 10 Gbps | 10 Gbps |
Netzwerk zwischen Nodes: Zwischen Cluster-Nodes wird mindestens 10 Gbps empfohlen. Der Traffic für Aster TSDB-Reparatur, Kafka-Replikation und Spark-Shuffle ist umfangreich.
Voraussetzungen
Auf dem Master-Node und allen Worker-Nodes müssen folgende Punkte erfüllt sein.
- Systemanforderungen erfüllt
- Hostname / statische IP / DNS konfiguriert
- Zeitsynchronisation (chronyd) — Zeitdifferenz zwischen Nodes muss unter
100msliegen - OS-Tuning (limits / sysctl / Swap aus)
- Private Netzwerkkommunikation zwischen Nodes möglich (RFC 1918 oder Tailscale)
- Interne Cluster-Ports freigegeben (Aster TSDB 7000/7001/9042, Kafka 9092/9093, Spark 7077/8081 usw.)
/etc/hosts-Konfiguration (auf allen Nodes identisch)
# /etc/hosts — 마스터 / 워커 모든 노드에 동일하게
192.168.0.41 plantpulse-master plantpulse-master.local
192.168.0.101 plantpulse-worker-1 plantpulse-worker-1.local
192.168.0.102 plantpulse-worker-2 plantpulse-worker-2.local
192.168.0.103 plantpulse-worker-3 plantpulse-worker-3.local
Docker-Cluster (Empfohlener Weg)
In einer Docker-/One-Line-Installation werden Worker als Compose-Overlay gestartet. Wenn der Basis-Stack auf dem Master-Node läuft, fügt bin/worker-add.sh die Worker nacheinander hinzu. Secrets und Zertifikate werden gemäß der folgenden Vorgehensweise als Sidecar-Dateien zwischen den Nodes kopiert, sodass Sie Werte nicht manuell übertragen müssen.
Die maßgebliche Worker-Liste — compose/workers.roster
Die maßgebliche Quelle „welche Worker existieren" ist die Datei compose/workers.roster. Sie hat das Format <id> <ip> pro Zeile; bei einer Single-Node-Installation ist sie normalerweise leer.
# compose/workers.roster
1 10.99.0.101
| Element | Bedeutung |
|---|---|
id | PP_WORKER_ID. Suffix für Containernamen (plantpulse-worker-<id>) und Volume-Namen (pw-<id>-*) |
ip | Feste Adresse auf pp-net(10.99.0.0/24). .1 ist das Gateway, .100 das Datalake; daher werden sie ab .101 verwendet |
compose/docker-compose.worker.yml wird in dieser Datei erstellt (bin/gen-worker-compose.sh), und bin/env.sh leitet die Worker-IPs und die Node-Liste ebenfalls aus derselben Datei ab. So kommt es nicht vor, dass Compose-, Betriebsskripte und Secret-Rotation-Guards unterschiedliche Worker-Sets sehen.
docker-compose.worker.yml ist ein Artefakt. Wenn Sie es manuell bearbeiten, schlägt der gen-worker-compose.sh --check in der CI fehl. Worker werden nicht erweitert oder reduziert, indem Sie Zeilen in die Roster-Datei einfügen oder entfernen, sondern über die weiter unten beschriebenen worker-add.sh / worker-decommission.sh + worker-remove.sh — Worker halten Aster TSDB-Token-Ranges und PostgreSQL-Replikations-Slots, sodass sie allein durch Ändern der Liste weder erstellt noch entfernt werden können.
Worker-spezifische Umgebungsvariablen (bin/env.sh)
| Variable | Standardwert | Beschreibung |
|---|---|---|
DOCKER_PW_NAME | plantpulse-worker | Präfix für Worker-Containernamen (plantpulse-worker-1 …) |
DOCKER_PW_MEMORY | 60G, 90 % des RAMs bei kleinem Host (getrennt vom DOCKER_DATALAKE_MEMORY des Masters bemessen) | Speicherlimit für Worker-Container |
DOCKER_PW_IP_<n> · PP_WORKER_NODES | Aus Roster abgeleitet | Nicht manuell eintragen |
Worker verwenden dasselbe Image wie der Datalake-Master (Integration vom 31.08.2026), daher übernehmen sie auch die im Image festgelegte JVM-Größe — allein Aster TSDB benötigt -Xms16G/-Xmx16G. Der Ansatz, die Größe proportional zur Host-Größe zu wählen, ist falsch. Der Bedarf wird durch die Service-Konfiguration bestimmt, nicht durch den Host.
Messwerte vom 31.08.2026: Worker mit dem alten 12g-Standardwert wurden OOMKilled, bevor Aster TSDB den Ring erreichte; der Container starb mit OOMKilled=true, aber der Join fand nicht statt, während health: starting aktiv blieb.
Worker hinzufügen
cd /opt/kopens/plantpulse-platform-docker
bin/worker-add.sh # 빈 id·빈 주소 자동 선택
bin/worker-add.sh 3 # id 지정
bin/worker-add.sh 3 10.99.0.103 # id·주소 지정
worker-add.sh führt die Schritte in dieser Reihenfolge aus.
- In Roster eintragen (bereits vorhandene ID wird abgelehnt, da es sich nicht um „Hinzufügen" handelt)
- Overlay-Compose neu erstellen
- Volume erstellen → Image pull →
up -d - Ring-Beitritt verifizieren — direkt über
nodetooldes Masters prüfen
Ein Worker hält Aster TSDB-Token-Ranges, Spark-Worker-Registrierung, PostgreSQL-Replikations-Slots und Redis-Replikationslinks. Die Readiness-Prüfung des Containers selbst beobachtet nur „erreicht er den Master?", daher meldet auch ein Worker, der den Beitritt nicht geschafft hat, den Status „gesund" genau wie ein erfolgreicher Worker.
Messwerte vom 31.08.2026: Ein Worker, dessen Aster TSDB OOMKilled wurde, behielt health: starting bei, während der Ring bei 1 Node blieb. Daher fragt worker-add.sh den Ring selbst ab.
Worker-Betrieb
cd /opt/kopens/plantpulse-platform-docker
# 진입 (워커는 기본 스택의 서비스가 아니라 shell.sh 로는 잡히지 않습니다)
docker exec -ti plantpulse-worker-3 /bin/bash
# 정지 — compose 동사 그대로
docker compose -f compose/docker-compose.yml -f compose/docker-compose.worker.yml \
--profile worker-3 stop plantpulse-worker-3
# 이미지 갱신 (이미 도는 워커. 추가 시점의 pull 은 worker-add.sh 안에 들어 있습니다)
docker compose -f compose/docker-compose.yml -f compose/docker-compose.worker.yml \
--profile worker-3 pull plantpulse-worker-3
docker compose -f compose/docker-compose.yml -f compose/docker-compose.worker.yml \
--profile worker-3 up -d plantpulse-worker-3
Worker entfernen — unbedingt in dieser Reihenfolge
bin/worker-decommission.sh 3 # 데이터 이관 + 링 이탈 확인 + 복제 슬롯 정리
bin/worker-remove.sh # 그 다음에 컨테이너 제거
docker rm bei lebendem Worker ist kein Entfernen, sondern „Aussetzen"Aster TSDB hält den Token-Range und die Host-ID dieses Nodes als DN fest. Bei RF=3 bleibt das QUORUM bestehen, sodass keinerlei Alarm ausgelöst wird. Und der Master behält den physischen PostgreSQL-Replikationsslot des Workers, wodurch WAL gepinnt wird, bis die Platte voll ist.
worker-remove.sh verweigert die Ausführung, wenn der Container läuft, und fordert auf, zuerst worker-decommission.sh aufzurufen.
worker-run.sh · worker-stop.sh · worker-update.sh · worker-bash.sh wurden entfernt. Sie basierten auf einer manuell verwalteten Liste von Worker-Diensten; im Zuge der Umstellung auf Roster-Erzeugung wurden sie nicht umbenannt, sondern gelöscht. Die Ersatzlösungen sind: worker-add.sh (inkl. Pull) · Compose-Verb · compose pull + up -d · docker exec.
Secret-Sidecar-Kopie (keine manuelle Übertragung)
Die auf dem Master erzeugten Service-Secrets liegen in der Sidecar-Datei /etc/kopens/plantpulse-platform.env. Wenn Sie diese Datei auf den Worker-Node kopieren, tritt der Worker mit denselben Anmeldeinformationen bei — übertragen Sie Passwörter nicht einzeln von Hand (gleiches Muster wie das Join-Bundle im Dokument zur 2-Node-Trennung).
# 마스터 노드에서 각 워커로
scp /etc/kopens/plantpulse-platform.env root@<worker-ip>:/etc/kopens/
Gemeinsames CA-Kopieren → automatisches Seeding
Das TLS-Vertrauen zwischen Nodes basiert auf dem gemeinsamen Cluster-CA. Wenn Sie die /etc/kopens/ca/ des Masters auf den Worker kopieren, wird sie beim Containerstart automatisch in das pp-security-Volume geseedet; eine manuelle Zertifikatsplatzierung entfällt.
# 마스터 노드에서 각 워커로 (컨테이너 경로 기준 자동 seed)
scp -r /etc/kopens/ca root@<worker-ip>:/etc/kopens/
platform.node.envist eine node-spezifische Identitätsdatei und darf nicht kopiert werden. Kopiert werden nur die beiden oben genannten Elemente (plantpulse-platform.env,ca/).
Cluster-Validierung (Docker-Umgebung)
# Cassandra 링 — 모든 노드가 UN (Up Normal) 이어야 합니다
docker exec plantpulse-datalake \
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node status
# Spark — 워커가 ALIVE 인지
# 브라우저에서 http://<마스터IP>:4440/ 의 Workers 탭
Häufig auftretende Probleme
| Symptom | Ursache | Prüfung |
|---|---|---|
| Worker tritt dem Ring nicht bei | PP_MASTER_IP ist eine von diesem Rechner aus nicht erreichbare Adresse | /etc/kopens/platform.node.env korrigieren und bin/restart-datalake.sh |
| Kafka-Clients auf Worker verbinden sich nur mit dem Master | Anzeige-Adresse ist Loopback | PP_KAFKA_ADVERTISED_HOST auf die tatsächliche Adresse des Rechners setzen |
| Sidecar-Werte fehlen auf dem Worker | Geheimdatei manuell kopiert | Verwenden Sie die oben beschriebene Vorgehensweise „Secret-Sidecar-Kopie" — bei manueller Übertragung stimmen Berechtigungen und Zeilenumbrüche nicht |
nodetool status zeigt Worker als DN | Ports der 7000er-Serie durch Firewall blockiert | Port-Konfiguration |
Cluster entfernen
# 각 워커에서 — 컨테이너를 제거하고 데이터 볼륨은 남긴다
ssh root@<WORKER_IP> 'cd /opt/kopens/plantpulse-platform-docker && bin/remove.sh'
# 마스터에서
cd /opt/kopens/plantpulse-platform-docker && bin/remove.sh
remove.sh und down.sh sind unterschiedlich| Verb | Container | Volumes |
|---|---|---|
bin/down.sh | Nur stoppen — wird mit up.sh unverändert wiederbelebt | unverändert |
bin/remove.sh | Entfernen | unverändert (Standardwert) |
Um auch Volumes zu löschen, verwenden Sie zusätzlich bin/tools/remove-all-volumes.sh.
Um auch Images und Netzwerke zu löschen, hängen Sie RM_IMAGE=1 · RM_NETWORK=1 an.
Es gibt keinen Befehl namens bin/stop.sh — bei der Compose-Umstellung wurden die gängigen Verben zu up · down · remove · restart · status · logs · update zusammengefasst
(Erste Schritte).
Datenträger werden über eine separate Richtlinie verwaltet (bei Bedarf nach Backup löschen).