Cluster-Installation
Anleitung zur Konfiguration von PlantPulse als Master + Worker-Node-Cluster für Workloads im großen Maßstab. Sie können mit einem einzelnen Node starten und schrittweise erweitern, sobald der Durchsatz an seine Grenzen stößt.
Zwei Arten der Mehr-Node-Konfiguration — mit unterschiedlichem Zweck
Konfiguration Zweck Dokument ① MASTER / WORKER Cluster Horizontale Skalierung der Infrastruktur (Cassandra·Kafka·Spark) — Verteilung derselben Schicht auf mehrere Nodes Dieses Dokument ② DATALAKE / APP 2-Node-Trennung Trennung von Speicher-/Verarbeitungsschicht und Konsolen-/Batch-Schicht auf unterschiedliche Boxen (vertikale Trennung) — Speicherentlastung pro Node, Lastisolierung 2-Node-Trenninstallation Verwenden Sie ①, wenn der Durchsatz nicht ausreicht und Sie die Infrastruktur erweitern möchten, und ②, wenn der Speicher einer Box nicht ausreicht oder die Batch-Last von der Konsole isoliert werden muss. Beide schließen sich nicht gegenseitig aus;
PP_MODE(Clustering) undPP_TIER(Schicht-Gate) sind orthogonal zueinander.
Wann sollte man auf ein Cluster skalieren?
| Umgebungsgröße | Empfohlene Konfiguration | Anmerkung |
|---|---|---|
| Tag ~5.000 | Einzelner Master | Cluster nicht erforderlich |
| Tag 5.000 ~ 50.000 | Master + 1~2 Worker | Verteilung von Analyse / Messaging |
| Tag 50.000+ | Master + 3+ Worker | Vollständig verteilter Betrieb |
Cluster-Topologie
Hardware-Anforderungen
Empfohlene Spezifikationen pro Worker-Node:
| Kategorie | Minimum | Standard | Groß |
|---|---|---|---|
| CPU | 16 vCPU | 32 vCPU | 48 vCPU |
| Speicher | 64 GB | 128 GB | 200+ GB |
| Daten-Festplatte | 200 GB NVMe | 1 TB NVMe | 4 TB NVMe |
| Netzwerk | 1 Gbps | 10 Gbps | 10 Gbps |
Netzwerk zwischen Nodes: Zwischen Cluster-Nodes werden 10 Gbps oder mehr empfohlen. Cassandra-Repair-, Kafka-Replikations- und Spark-Shuffle-Traffic sind erheblich.
Voraussetzungen
Auf dem Master-Node und allen Worker-Nodes müssen folgende Punkte erfüllt sein.
- Systemanforderungen erfüllt
- Hostname / feste IP / DNS-Konfiguration
- Zeitsynchronisation (chronyd) — Zeitdifferenz zwischen Nodes muss unter 100 ms liegen
- OS-Tuning (limits / sysctl / swap off)
- Kommunikation über privates Netzwerk zwischen Nodes möglich (RFC 1918 oder Tailscale)
- Interne Cluster-Ports zulassen (Cassandra 7000/7001/9042, Kafka 9092/9093, Spark 7077/8081 usw.)
/etc/hosts Konfiguration (identisch auf allen Nodes)
# /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 Docker/One-Line-Installationsumgebungen werden Worker als Compose-Overlay gestartet. Während der Basisstack auf dem Master-Node läuft, fügt bin/worker-add.sh die Worker nacheinander hinzu. Secrets und Zertifikate werden gemäß dem folgenden Verfahren als Sidecar-Dateien zwischen Nodes kopiert, sodass Werte nicht von Hand übertragen werden müssen.
Die maßgebliche Quelle der Worker-Liste — compose/workers.roster
Die maßgebliche Quelle dafür, welche Worker existieren, ist die eine Datei compose/workers.roster. Pro Zeile gilt das Format <id> <ip>; bei einer Einzel-Node-Installation ist sie normalerweise leer.
# compose/workers.roster
1 10.99.0.101
| Element | Bedeutung |
|---|---|
id | PP_WORKER_ID. Suffix des Container-Namens (plantpulse-worker-<id>) und des Volume-Namens (pw-<id>-*) |
ip | Feste Adresse auf pp-net(10.99.0.0/24). .1 ist das Gateway, .100 ist das Data Lake, daher beginnend ab .101 verwendet |
compose/docker-compose.worker.yml wird aus dieser Datei erzeugt (bin/gen-worker-compose.sh), und auch bin/env.sh leitet Worker-IPs und Node-Liste aus derselben Datei ab. So kommt es nicht dazu, dass Compose, Betriebsskripte und Secret-Rotation-Guards unterschiedliche Worker-Mengen sehen.
docker-compose.worker.yml ist ein generiertes Artefakt. Manuelle Änderungen führen dazu, dass gen-worker-compose.sh --check in der CI fehlschlägt. Worker hinzuzufügen oder zu entfernen erfolgt nicht durch Ein-/Austragen von Zeilen im Roster, sondern über worker-add.sh / worker-decommission.sh + worker-remove.sh weiter unten — Worker halten Cassandra-Token-Ranges und PostgreSQL-Replikationsslots, sodass sie durch bloßes Bearbeiten der Liste weder erzeugt noch entfernt werden.
Worker-bezogene Umgebungsvariablen (bin/env.sh)
| Variable | Standardwert | Beschreibung |
|---|---|---|
DOCKER_PW_NAME | plantpulse-worker | Präfix des Worker-Container-Namens (plantpulse-worker-1 …) |
DOCKER_PW_MEMORY | Gleicher Wert wie DOCKER_DATALAKE_MEMORY (80G, bei kleinem Host 90% des RAM) | Speicherobergrenze des Worker-Containers |
DOCKER_PW_IP_<n> · PP_WORKER_NODES | Aus Roster abgeleitet | Nicht manuell eintragen |
Da Worker dasselbe Image wie der Data-Lake-Master verwenden (vereinheitlicht am 2026-08-31), gilt auch die im Image gebackene JVM-Größe unverändert — ein einzelnes Cassandra benötigt -Xms16G/-Xmx16G. Eine Bemessung proportional zur Hostgröße ist falsch. Was benötigt wird, bestimmt nicht der Host, sondern die Dienstkonfiguration.
Messung vom 2026-08-31: Ein Worker mit dem alten 12g-Standardwert wurde OOMKilled, bevor Cassandra den Ring erreichte, der Container starb mit OOMKilled=true, blieb aber ohne Join weiterhin auf health: starting stehen.
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 der Reihe nach aus:
- Registrierung im Roster (bereits vorhandene IDs werden abgelehnt, da dies keine «Hinzufügung» ist)
- Overlay-Compose neu erzeugen
- Volume erstellen → Image pullen →
up -d - Ring-Beitritt prüfen — direkte Verifikation über
nodetoolauf dem Master
Worker tragen gemeinsam Cassandra-Token-Ranges, Spark-Worker-Registrierung, PostgreSQL-Replikationsslots und Redis-Replikationslinks. Da die Readiness-Prüfung des Containers selbst nur prüft, «ob der Master erreichbar ist», meldet ein Worker, dessen Join fehlgeschlagen ist, genauso normal wie ein erfolgreicher Worker.
Messung vom 2026-08-31: Ein Worker, dessen Cassandra OOMKilled wurde, blieb bei einem 1-Node-Ring auf health: starting stehen. Deshalb 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 an einem lebenden Worker ist kein Entfernen, sondern ein „Im-Stich-Lassen"Cassandra hält weiterhin die Token-Range und Host-ID dieses Nodes als DN fest. Bei RF=3 bleibt QUORUM weiterhin erfüllt, sodass kein Alarm ausgelöst wird. Und der Master hält weiterhin den physischen Replikationsslot dieses Workers in PostgreSQL, wodurch WAL fixiert bleibt, bis die Festplatte voll ist.
worker-remove.sh verweigert die Ausführung, solange der Container läuft, und weist an, zuerst worker-decommission.sh aufzurufen.
Die vier Skripte worker-run.sh · worker-stop.sh · worker-update.sh · worker-bash.sh wurden gelöscht. Sie waren auf Basis einer manuell verwalteten Worker-Dienstliste erstellt worden; mit der Umstellung auf die Roster-Generierung wurden sie nicht nur umbenannt, sondern entfernt. Als Ersatz dienen jeweils worker-add.sh (inkl. pull) · Compose-Verben · Compose pull + up -d · docker exec.
Kopieren des Secret-Sidecars (kein manuelles Kopieren)
Die auf dem Master erzeugten Service-Secrets befinden sich in der Sidecar-Datei /etc/kopens/plantpulse-platform.env. Wird diese Datei auf den Worker-Node kopiert, tritt der Worker mit denselben Zugangsdaten bei — kopieren Sie Passwörter nicht einzeln von Hand (dasselbe Muster wie das Join-Bundle im Dokument zur 2-Node-Trennung).
# 마스터 노드에서 각 워커로
scp /etc/kopens/plantpulse-platform.env root@<worker-ip>:/etc/kopens/
Kopieren der gemeinsamen CA → automatisches Seeding
Das TLS-Vertrauen zwischen Nodes basiert auf einer gemeinsamen Cluster-CA. Wird /etc/kopens/ca/ vom Master auf den Worker kopiert, wird es beim Containerstart automatisch in das Volume pp-security eingebracht, sodass Zertifikate nicht manuell platziert werden müssen.
# 마스터 노드에서 각 워커로 (컨테이너 경로 기준 자동 seed)
scp -r /etc/kopens/ca root@<worker-ip>:/etc/kopens/
platform.node.envist eine knotenspezifische Identitätsdatei und sollte nicht kopiert werden. Zu kopieren sind ausschließlich die beiden oben genannten Elemente (plantpulse-platform.env,ca/).
Cluster-Verifikation (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 탭
Native (Binär-)Cluster-Verfahren
Das Folgende ist ein Verfahren, das für bestehende Systeme erhalten geblieben ist, die mit einer binären Installation aufgebaut wurden. Da die aktuelle Auslieferung ausschließlich den oben beschriebenen Docker-Compose-Weg vorsieht, verwenden Sie es bitte nicht für Neuinstallationen.
1. Master-Node-Installation
Der Master-Node folgt demselben Verfahren wie bei der Einzel-Node-Installation.
1.1 Master-Installation
# 마스터 노드에서
mkdir -p /opt/kopens
cd /opt/kopens
tar -xzvf plantpulse-platform-2026.05.tgz
cd /opt/kopens/plantpulse-platform/tools
./setup.sh
# 노드 모드 입력: MASTER
# HOST IP: 192.168.0.41
# SERVICE IP: 192.168.0.41 (외부 노출 IP)
1.2 Anpassung von env.local.sh (Cluster-Optionen)
env.shist die durch Deployment überschriebene SSOT (maßgebliche Standardquelle) und darf nicht direkt bearbeitet werden. Maschinenspezifische Werte werden als Override inenv.local.shim selben Verzeichnis geschrieben (daenv.shdiese immer zuerst am Anfang sourced, haben sie stets Vorrang). Details zum Prinzip siehe Binärinstallation §4.
vi /opt/kopens/plantpulse-platform/plantpulse-startup/env.local.sh
# 마스터 노드
export PP_MODE=MASTER
export PP_HOST_IP=192.168.0.41
export PP_SERVICE_IP=192.168.0.41
export PP_MASTER_IP=192.168.0.41
export PP_PUBLIC_IP=192.168.0.41
# 클러스터 자원
export PP_CLUSTER_CORES=64 # 마스터 + 워커 코어 합 (Spark 사용)
export PP_CLUSTER_MEMORY_BY_CORE=2G
# TLS SAN 에 모든 노드 IP / 도메인 포함
export PP_TLS_SAN_IPS="192.168.0.41,192.168.0.101,192.168.0.102,192.168.0.103,127.0.0.1"
export PP_TLS_SAN_DNS="plantpulse-master,plantpulse-worker-1,plantpulse-worker-2,plantpulse-worker-3,localhost"
export PP_TLS_NODE_NAMES="master worker-1 worker-2 worker-3"
1.3 Master starten
cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin
./configure.sh
./prepare-ssl.sh
./start-daemon.sh
./status.sh
2. Worker-Node hinzufügen
2.1 Worker-Installation
Auf jedem Worker-Node wird nach demselben Verfahren installiert.
# 워커 노드 (예: 192.168.0.101) 에서
mkdir -p /opt/kopens
cd /opt/kopens
tar -xzvf plantpulse-platform-2026.05.tgz
cd /opt/kopens/plantpulse-platform/tools
./setup.sh
# 노드 모드 입력: WORKER
# HOST IP: 192.168.0.101
# SERVICE IP: 192.168.0.101
# MASTER IP: 192.168.0.41
2.2 Anpassung von env.local.sh am Worker (nur node-spezifische Werte)
Nur node-spezifische Werte wie die IP eines Nodes werden in env.local.sh geschrieben (env.sh ✗ nicht direkt bearbeiten).
vi /opt/kopens/plantpulse-platform/plantpulse-startup/env.local.sh
# 워커 노드
export PP_MODE=WORKER
export PP_HOST_IP=192.168.0.101 # 이 워커의 IP
export PP_SERVICE_IP=192.168.0.101
export PP_MASTER_IP=192.168.0.41 # 마스터의 IP
export PP_PUBLIC_IP=192.168.0.101
Passwörter/Keystore-Passwörter werden hier nicht manuell eingetragen — Synchronisation zwischen Nodes erfolgt über den unten beschriebenen Secret-Sidecar.
2.3 Kopieren des Secret-Sidecars
Service-Secrets befinden sich in der Sidecar-Datei /etc/kopens/plantpulse-platform.env des Masters. Wird diese Datei auf den Worker kopiert, tritt der Worker mit denselben Zugangsdaten bei (dasselbe Muster wie das Join-Bundle im Dokument zur 2-Node-Trennung). Kopieren Sie Passwörter nicht einzeln von Hand.
# 마스터에서 워커로 (env.sh 보다 먼저 source 되는 사이드카)
scp /etc/kopens/plantpulse-platform.env root@192.168.0.101:/etc/kopens/
2.4 Kopieren der gemeinsamen CA → automatisches Seeding
Das TLS-Vertrauen zwischen Nodes basiert auf einer gemeinsamen Cluster-CA. Wird /etc/kopens/ca/ vom Master auf den Worker kopiert, wird es beim Start bezogen auf den Container-Pfad automatisch eingebracht, sodass Zertifikate nicht manuell platziert werden müssen.
# 마스터에서 워커로 (공유 CA — 크로스노드 TLS 신뢰)
scp -r /etc/kopens/ca root@192.168.0.101:/etc/kopens/
platform.node.envist eine knotenspezifische Identitätsdatei und sollte nicht kopiert werden.
2.5 Worker starten
cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin
./configure.sh
./start-daemon.sh
./status.sh
Wenn in der status.sh-Ausgabe des Worker-Nodes Folgendes als RUNNING angezeigt wird, ist alles normal.
- Cassandra (:9042)
- Kafka (:9092)
- Spark Worker (:8081)
Hinweis: Auf dem Worker-Node werden keine Anwendungsmodule wie server / cep / batch ausgeführt. Es werden ausschließlich Infrastruktur-/verteilte Verarbeitungskomponenten geclustert.
3. Cluster-Verifikation
3.1 Cassandra-Cluster
# 마스터에서
cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin
./pd node status
Erwartete Ausgabe (Beispiel):
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns Host ID Rack
UN 192.168.0.41 45.2 GiB 256 ? <uuid> rack1
UN 192.168.0.101 44.8 GiB 256 ? <uuid> rack1
UN 192.168.0.102 45.5 GiB 256 ? <uuid> rack1
Wenn UN (Up Normal) bei allen Nodes angezeigt wird, ist alles normal.
3.2 Kafka-Cluster
cd /opt/kopens/plantpulse-platform/plantpulse-messaging/kafka/bin
./kafka-broker-api-versions.sh --bootstrap-server 192.168.0.41:9092 | head
Wenn 3 Broker angezeigt werden, ist alles normal.
3.3 Spark-Cluster
Zugriff auf die Spark UI des Masters über den Browser:
http://192.168.0.41:4440/
Prüfen Sie im Tab Workers, ob alle Worker den Status ALIVE haben.
4. Cluster-Betrieb
Worker hinzufügen (dynamische Erweiterung)
Verfahren zum Hinzufügen eines Worker-Nodes zu einem bereits laufenden Cluster:
Worker entfernen
# 1. 워커를 안전하게 비우기 (Cassandra)
ssh root@192.168.0.103 \
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node drain
# 2. 마스터에서 노드 제거
cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin
./pd node remove
# 호스트 ID 입력
# 3. 워커 정지 후 제거
ssh root@192.168.0.103 \
/opt/kopens/plantpulse-platform/plantpulse-startup/stop.sh
Node-Austausch
Beim Austausch eines ausgefallenen Nodes gegen einen neuen Node beachten Sie bitte das Verfahren Administrator: Node-Austausch. Entscheidend ist, dieselbe IP / denselben Hostnamen beizubehalten und nach dem Booten des neuen Nodes die Daten im bootstrap-Modus zu übernehmen.
5. Cluster-Backup
plantpulse-backup auf dem Master-Node ist für den gesamten Cluster verantwortlich.
cd /opt/kopens/plantpulse-platform/plantpulse-backup/bin
# Cassandra: 모든 노드에서 snapshot 수집
./backup.sh --cassandra
# PostgreSQL: 마스터에서만
./backup.sh --postgres
Siehe Backup und Wiederherstellung.
Häufig auftretende Probleme
| Symptom | Ursache | Maßnahme |
|---|---|---|
| Worker-Join funktioniert nicht | Seed-Node nicht konfiguriert | Prüfen, ob die Master-IP in seeds von cassandra.yaml enthalten ist |
| Cassandra-Token-Ungleichgewicht | Unsachgemäßer Join | pd node cleanup + Token-Neuzuweisung |
| Kafka under-replicated | Broker ausgefallen | kafka-topics.sh --describe + Replikationsfaktor prüfen |
| Spark Worker registriert sich nicht | Firewall blockiert 7077 | Port 7077, 8081 bidirektional im privaten Netzwerk zulassen |
| Zertifikat-Mismatch | Keystore-Synchronisation fehlt | prepare-ssl.sh auf dem Master erneut ausführen + Worker neu deployen |
| Zeitabweichung | NTP nicht konfiguriert | chronyc tracking prüfen, unter 100 ms halten |
Cluster entfernen
# 각 워커에서
ssh root@<WORKER_IP> /opt/kopens/plantpulse-platform/plantpulse-startup/stop.sh
ssh root@<WORKER_IP> rm -rf /opt/kopens/plantpulse-platform
# 마스터에서
cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin
./stop.sh
rm -rf /opt/kopens/plantpulse-platform
# 데이터 디스크는 별도 정책으로 관리 (필요 시 백업 후 삭제)