クラスタインストール
大規模ワークロードのために PlantPulse を マスター + ワーカーノードクラスタ として構成する方法です。単一ノードで開始し、処理量が限界に達したときに段階的に拡張できます。
マルチノードは「水平拡張」の1つだけです
インフラ(Aster TSDB・Kafka・Spark)を複数ノードに分割する マスター / ワーカークラスタがこの ドキュメントの内容です。処理量が限界に達したときに使用します。
階層を分割するインストール(データレイクとアプリケーションを別のボックスに)は 2026-09-02 に 廃止されました。 すべてのボックスがフルインストールです。
いつクラスタに拡張しますか?
| 環境規模 | 推奨構成 | 備考 |
|---|---|---|
| タグ ~5,000 | 単一マスター | クラスタ不要 |
| タグ 5,000 ~ 50,000 | マスター + 1~2 ワーカー | 分析 / メッセージング分散 |
| タグ 50,000+ | マスター + 3+ ワーカー | 本格的な分散運用 |
クラスタトポロジー
ハードウェア要件
各ワーカーノードの推奨仕様(マスターノードはシステム要件に従います — データレイクマスター 96 GB 以上):
| 区分 | 最小 | 標準 | 大規模 |
|---|---|---|---|
| CPU | 16 vCPU | 32 vCPU | 48 vCPU |
| メモリ | 67 GB 以上 (60 GB のワーカーコンテナがホスト RAM の 90% に収まること — 64 GB は仕様未満) | 128 GB | 200+ GB |
| データディスク | 200 GB NVMe | 1 TB NVMe | 4 TB NVMe |
| ネットワーク | 1 Gbps | 10 Gbps | 10 Gbps |
ノード間ネットワーク: クラスタノード間では 10 Gbps 以上を推奨。Aster TSDB repair、Kafka replication、Spark shuffle トラフィックが大きいです。
前提条件
マスターノードとすべてのワーカーノードで以下が完了している必要があります。
- システム要件 を満たしている
- ホスト名 / 固定 IP / DNS 設定
- 時刻同期 (chronyd) — ノード間の時刻差が
100ms以下である必要があります - OS チューニング (limits / sysctl / swap off)
- ノード間のプライベートネットワーク通信 (RFC 1918 または Tailscale)
- クラスタ内部ポートの許可 (Aster TSDB 7000/7001/9042、Kafka 9092/9093、Spark 7077/8081 など)
/etc/hosts 設定 (全ノード共通)
# /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 クラスタ (推奨経路)
Docker/ワンラインインストール環境では、ワーカーを compose オーバーレイ で起動します。マスターノードに基本スタックが起動している状態で、bin/worker-add.sh がワーカーを1つずつ追加します。シークレット・証明書は下記の手順で サイドカーファイルとしてノード間コピー するため、値を手で書き写す必要はありません。
ワーカー一覧の正本 — compose/workers.roster
どのワーカーが存在するか の正本は compose/workers.roster ファイルの1つです。1行に <id> <ip> 形式で、単一ノードインストールの場合は空であるのが正常です。
# compose/workers.roster
1 10.99.0.101
| 項目 | 意味 |
|---|---|
id | PP_WORKER_ID。コンテナ名(plantpulse-worker-<id>)とボリューム名(pw-<id>-*)の接尾辞 |
ip | pp-net(10.99.0.0/24) 上の固定アドレス。.1 はゲートウェイ、.100 はデータレイクであるため、.101 から 使用します |
compose/docker-compose.worker.yml はこのファイルから 生成 され(bin/gen-worker-compose.sh)、bin/env.sh も同じファイルからワーカー IP とノード一覧を導出します。そのため compose・運用スクリプト・シークレットローテーションガードが互いに異なるワーカー集合を参照することがありません。
docker-compose.worker.yml は生成物です。手で編集すると CI の gen-worker-compose.sh --check が失敗します。ワーカーを増減させることは roster にエントリを追加・削除することではなく、下記の worker-add.sh / worker-decommission.sh + worker-remove.sh で行います — ワーカーは Aster TSDB トークンレンジと PostgreSQL レプリケーションスロットを保持しているため、一覧だけを変更しても生成も削除もされません。
ワーカー関連環境変数 (bin/env.sh)
| 変数 | デフォルト値 | 説明 |
|---|---|---|
DOCKER_PW_NAME | plantpulse-worker | ワーカーコンテナ名の接頭辞 (plantpulse-worker-1 …) |
DOCKER_PW_MEMORY | 60G、ホストが小さい場合は RAM の 90% (マスターの DOCKER_DATALAKE_MEMORY とは別に決めます) | ワーカーコンテナのメモリ上限 |
DOCKER_PW_IP_<n> · PP_WORKER_NODES | roster から導出 | 手で書きません |
ワーカーは データレイクマスターと同じイメージ を使用するため(2026-08-31 統合)、そのイメージに焼き込まれた JVM サイズもそのまま適用されます — Aster TSDB 1つが -Xms16G/-Xmx16G を要求します。ホストサイズに比例して設定する方法は誤りです。必要な量はホストではなく、サービス構成 が決定します。
2026-08-31 実測: 旧 12g デフォルト値のワーカーが Aster TSDB がリングに到達する前に OOMKilled され、コンテナは OOMKilled=true で死にましたが、ジョインは行われないまま health: starting を維持 しました。
ワーカー追加
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 が順番に実行します。
- roster に登録 (既存の id は「追加」ではないため拒否します)
- オーバーレイ compose 再生成
- ボリューム作成 → イメージ pull →
up -d - リング参加確認 — マスターの
nodetoolで直接検証
ワーカーは Aster TSDB トークンレンジ、Spark Worker 登録、PostgreSQL レプリケーションスロット、Redis レプリケーションリンクを同時に保持します。コンテナ自体の準備チェックは「マスターに到達できるか」だけを見るため、参加に失敗したワーカーも成功したワーカーとまったく同じように正常と報告します。
2026-08-31 実測: Aster TSDB が OOMKilled されたワーカーがリングは1ノードのまま health: starting を維持しました。そのため worker-add.sh はリング自体を問い合わせます。
ワーカー運用
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
ワーカー削除 — 必ずこの順序で
bin/worker-decommission.sh 3 # 데이터 이관 + 링 이탈 확인 + 복제 슬롯 정리
bin/worker-remove.sh # 그 다음에 컨테이너 제거
docker rm は削除ではなく「放置」ですAster TSDB はそのノードのトークンレンジと host id を DN として保持します。RF=3 なら QUORUM がそのまま成立するため、いかなる警告も出ません。 そしてマスターはそのワーカーの PostgreSQL 物理レプリケーションスロットを保持し続けるため、ディスクがいっぱいになるまで WAL を固定します。
worker-remove.sh はコンテナが稼働していると拒否し、worker-decommission.sh を先に呼ぶよう案内します。
worker-run.sh · worker-stop.sh · worker-update.sh · worker-bash.sh の4つは 削除されました。 手動で管理していたワーカーサービス一覧を前提に作られていたため、roster 生成方式に変更する際に名前を変えただけではなく、廃止しました。代替はそれぞれ worker-add.sh(pull 含む) · compose 動詞 · compose pull + up -d · docker exec です。
シークレットサイドカーコピー (手動コピー禁止)
マスターで生成されたサービスシークレットは /etc/kopens/plantpulse-platform.env サイドカーファイルにあります。このファイルをワーカーノードにコピーすると、ワーカーが同一の資格情報で参加します — パスワードを1つずつ書き写さないでください(2ノード分離ドキュメントの参加バンドルと同一パターン)。
# 마스터 노드에서 각 워커로
scp /etc/kopens/plantpulse-platform.env root@<worker-ip>:/etc/kopens/
共有 CA コピー → 自動 seed
ノード間 TLS 信頼は共有クラスタ CA で成立します。マスターの /etc/kopens/ca/ をワーカーにコピーすると、コンテナ起動時に pp-security ボリュームに 自動 seed され、証明書を手動配置する必要がありません。
# 마스터 노드에서 각 워커로 (컨테이너 경로 기준 자동 seed)
scp -r /etc/kopens/ca root@<worker-ip>:/etc/kopens/
platform.node.envは ノード別アイデンティティファイル のためコピーしないでください。コピー対象は上記の2項目(plantpulse-platform.env、ca/)のみです。
クラスタ検証 (Docker 環境)
# 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 탭
よく発生する問題
| 症状 | 原因 | 確認 |
|---|---|---|
| ワーカーがリングに参加しない | PP_MASTER_IP がこのボックスから到達できないアドレス | /etc/kopens/platform.node.env を修正して bin/restart-datalake.sh |
| ワーカーで Kafka クライアントがマスターにしか接続しない | 広告アドレスがループバック | PP_KAFKA_ADVERTISED_HOST をそのボックスの実際のアドレスに |
| サイドカー値がワーカーにない | 秘密ファイルを手動コピー | 上記「シークレットサイドカーコピー」の手順を使用してください — 手動コピーは権限と改行がずれます |
nodetool status にワーカーが DN | ファイアウォールで 7000 系がブロック | ポート構成 |
クラスタ削除
# 각 워커에서 — 컨테이너를 제거하고 데이터 볼륨은 남긴다
ssh root@<WORKER_IP> 'cd /opt/kopens/plantpulse-platform-docker && bin/remove.sh'
# 마스터에서
cd /opt/kopens/plantpulse-platform-docker && bin/remove.sh
remove.sh と down.sh は異なります| 動詞 | コンテナ | ボリューム |
|---|---|---|
bin/down.sh | 停止のみ — up.sh でそのまま復活します | そのまま |
bin/remove.sh | 削除 | そのまま(デフォルト) |
ボリュームまで削除するには bin/tools/remove-all-volumes.sh を別途実行します。
イメージ・ネットワークまで削除するには RM_IMAGE=1 · RM_NETWORK=1 を追加します。
bin/stop.sh という名前は ありません — コンポーズ移行時に共通動詞が
up · down · remove · restart · status · logs · update に整理されました
(スタートアップガイド)。
データディスクは別途ポリシーで管理します(必要に応じてバックアップ後に削除)。