> For the complete documentation index, see [llms.txt](https://kopens.gitbook.io/plantpulse-platform/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kopens.gitbook.io/plantpulse-platform/installation/build-deploy.md).

# 클러스터 설치

대규모 워크로드를 위해 PlantPulse 를 **마스터 + 워커 노드 클러스터** 로 구성하는 방법입니다. 단일 노드로 시작했다가 처리량이 한계에 도달했을 때 점진적으로 확장할 수 있습니다.

## 언제 클러스터로 확장하나요?

```mermaid
flowchart TD
  A[단일 노드 운영] --> B{지표 확인}
  B -->|CPU > 80% 지속| C[클러스터 확장 필요]
  B -->|메시지 lag 증가| C
  B -->|Cassandra 디스크 70%+ | C
  B -->|모두 정상| D[단일 노드 유지]
  C --> E[워커 노드 추가]
  E --> F[Kafka replication 상향]
  E --> G[Cassandra 노드 join]
  E --> H[Spark Worker 등록]
```

| 환경 규모              | 권장 구성         | 비고          |
| ------------------ | ------------- | ----------- |
| 태그 \~5,000         | 단일 마스터        | 클러스터 불필요    |
| 태그 5,000 \~ 50,000 | 마스터 + 1\~2 워커 | 분석 / 메시징 분산 |
| 태그 50,000+         | 마스터 + 3+ 워커   | 본격 분산 운영    |

## 클러스터 토폴로지

```mermaid
graph TB
  subgraph MASTER["마스터 노드 (192.168.0.41)"]
    M_SVR[server :80]
    M_CASS[Cassandra seed]
    M_PG[PostgreSQL]
    M_KAFKA[Kafka controller + broker]
    M_SPARK_M[Spark Master :7077]
    M_TS[Time-Series Engine]
    M_CEP[CEP]
  end

  subgraph W1["워커 1 (192.168.0.101)"]
    W1_CASS[Cassandra]
    W1_KAFKA[Kafka broker]
    W1_SPARK_W[Spark Worker]
  end

  subgraph W2["워커 2 (192.168.0.102)"]
    W2_CASS[Cassandra]
    W2_KAFKA[Kafka broker]
    W2_SPARK_W[Spark Worker]
  end

  M_CASS <--> W1_CASS
  M_CASS <--> W2_CASS
  W1_CASS <--> W2_CASS
  M_KAFKA <--> W1_KAFKA
  M_KAFKA <--> W2_KAFKA
  M_SPARK_M --> W1_SPARK_W
  M_SPARK_M --> W2_SPARK_W
```

## 하드웨어 요구사항

각 워커 노드 사양 권장:

| 구분      | 최소          | 표준        | 대규모       |
| ------- | ----------- | --------- | --------- |
| CPU     | 16 vCPU     | 32 vCPU   | 48 vCPU   |
| 메모리     | 64 GB       | 128 GB    | 200+ GB   |
| 데이터 디스크 | 200 GB NVMe | 1 TB NVMe | 4 TB NVMe |
| 네트워크    | 1 Gbps      | 10 Gbps   | 10 Gbps   |

> **노드 간 네트워크**: 클러스터 노드들 간에는 **10 Gbps 이상** 권장. Cassandra repair, Kafka replication, Spark shuffle 트래픽이 큽니다.

## 사전 요건

마스터 노드와 모든 워커 노드에서 다음이 완료되어야 합니다.

* [ ] [시스템 요구사항](/plantpulse-platform/installation/requirements.md) 충족
* [ ] 호스트명 / 고정 IP / DNS 설정
* [ ] 시간 동기화 (chronyd) — **노드 간 시간차 100ms 이하 필수**
* [ ] OS 튜닝 (limits / sysctl / swap off)
* [ ] 노드 간 사설망 통신 가능 (RFC 1918 또는 Tailscale)
* [ ] 클러스터 내부 포트 허용 (Cassandra 7000/7001/9042, Kafka 9092/9093, Spark 7077/8081 등)

### `/etc/hosts` 설정 (모든 노드 동일)

```bash
# /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
```

## 1. 마스터 노드 설치

마스터 노드는 단일 노드 설치 절차와 동일합니다.

### 1.1 마스터 설치

```bash
# 마스터 노드에서
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 `env.sh` 조정 (클러스터 옵션)

```bash
vi /opt/kopens/plantpulse-platform/plantpulse-startup/env.sh
```

```bash
# 마스터 노드
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 마스터 시작

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-startup
./configure.sh
./prepare-ssl.sh
./start-daemon.sh
./status.sh
```

## 2. 워커 노드 추가

### 2.1 워커 설치

각 워커 노드에서 동일한 절차로 설치합니다.

```bash
# 워커 노드 (예: 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 워커 `env.sh` 조정

```bash
vi /opt/kopens/plantpulse-platform/plantpulse-startup/env.sh
```

```bash
# 워커 노드
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

# 마스터와 동일한 비밀번호 / TLS 설정 사용
export PP_REDIS_PASSWORD=<마스터와 동일>
export PP_CASSANDRA_PASSWORD=<마스터와 동일>
export PP_PG_PASSWORD=<마스터와 동일>
export PP_KAFKA_BROKER_USER=<마스터와 동일>
export PP_KAFKA_BROKER_PASSWORD=<마스터와 동일>
# ... 기타 비밀번호 동기화

# TLS keystore 비밀번호도 동일
export PP_TLS_KEYSTORE_PASSWORD=<마스터와 동일>
```

> **핵심**: 모든 비밀번호 / TLS keystore 비밀번호가 노드 간 동일해야 합니다. 마스터의 `env.sh` 를 worker 로 복사한 뒤 `PP_HOST_IP` 등 노드별 변수만 수정하는 것이 안전합니다.

### 2.3 인증서 동기화

마스터에서 생성된 인증서를 워커에 복사합니다.

```bash
# 마스터에서 워커로 전송
scp -r /var/security/plantpulse/* root@192.168.0.101:/var/security/plantpulse/

# 워커에서 권한 확인
ssh root@192.168.0.101 chmod 0600 /var/security/plantpulse/*.jks
```

### 2.4 워커 시작

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-startup
./configure.sh
./start-daemon.sh
./status.sh
```

워커 노드의 `status.sh` 출력에서 다음이 RUNNING 이면 정상입니다.

* Cassandra (:9042)
* Kafka (:9092)
* Spark Worker (:8081)

> **참고**: 워커 노드는 server / cep / batch 등 애플리케이션 모듈은 실행하지 않습니다. 인프라 / 분산 처리 컴포넌트만 클러스터링됩니다.

## 3. 클러스터 검증

### 3.1 Cassandra 클러스터

```bash
# 마스터에서
cd /opt/kopens/plantpulse-platform/plantpulse-startup
./node-status.sh
```

기대 출력 (예시):

```
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
```

`UN` (Up Normal) 이 모든 노드에 표시되면 정상입니다.

### 3.2 Kafka 클러스터

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-messaging/kafka/bin
./kafka-broker-api-versions.sh --bootstrap-server 192.168.0.41:9092 | head
```

브로커가 3개로 표시되면 정상입니다.

### 3.3 Spark 클러스터

브라우저에서 마스터의 Spark UI 접속:

```
http://192.168.0.41:4440/
```

`Workers` 탭에서 모든 워커가 ALIVE 상태인지 확인합니다.

## 4. 클러스터 운영

### 워커 추가 (동적 확장)

이미 운영 중인 클러스터에 워커 노드를 추가하는 절차:

```mermaid
flowchart LR
  A[1. 신규 워커 설치<br/>setup.sh] --> B[2. env.sh 동기화<br/>마스터 환경 복사]
  B --> C[3. 인증서 복사<br/>scp /var/security]
  C --> D[4. configure.sh<br/>start-daemon.sh]
  D --> E[5. node-status.sh<br/>UN 확인]
  E --> F[6. 토큰 재균형<br/>node-cleanup.sh]
```

### 워커 제거

```bash
# 1. 워커를 안전하게 비우기 (Cassandra)
ssh root@192.168.0.103 \
  /opt/kopens/plantpulse-platform/plantpulse-startup/node-drain.sh

# 2. 마스터에서 노드 제거
cd /opt/kopens/plantpulse-platform/plantpulse-startup
./node-remove.sh
# 호스트 ID 입력

# 3. 워커 정지 후 제거
ssh root@192.168.0.103 \
  /opt/kopens/plantpulse-platform/plantpulse-startup/stop.sh
```

### 노드 교체

장애 노드를 새 노드로 교체할 때는 [관리자: 노드 교체](/plantpulse-platform/admin/troubleshooting.md) 절차를 참고해 주세요. 핵심은 같은 IP / 호스트명을 유지하면서 새 노드를 부팅 후 `bootstrap` 모드로 데이터를 끌어오는 것입니다.

## 5. 클러스터 백업

마스터 노드의 `plantpulse-backup` 이 전체 클러스터를 책임집니다.

```bash
cd /opt/kopens/plantpulse-platform/plantpulse-backup/bin

# Cassandra: 모든 노드에서 snapshot 수집
./backup.sh --cassandra

# PostgreSQL: 마스터에서만
./backup.sh --postgres
```

[백업 및 복구](/plantpulse-platform/admin/backup-recovery.md) 참고.

## 자주 발생하는 문제

| 증상                     | 원인              | 조치                                        |
| ---------------------- | --------------- | ----------------------------------------- |
| 워커 join 안 됨            | seed 노드 미설정     | `cassandra.yaml` 의 `seeds` 에 마스터 IP 포함 확인 |
| Cassandra 토큰 불균형       | 부적절한 join       | `node-cleanup.sh` + 토큰 재할당                |
| Kafka under-replicated | 브로커 다운          | `kafka-topics.sh --describe` + 복제 인자 점검   |
| Spark Worker 등록 안 됨    | 방화벽 7077 차단     | 사설망 7077, 8081 양방향 허용                     |
| 인증서 Mismatch           | keystore 동기화 누락 | 마스터에서 `prepare-ssl.sh` 재실행 + 워커 재배포       |
| 시간 불일치                 | NTP 미설정         | `chronyc tracking` 확인, 100ms 이하 유지        |

## 클러스터 제거

```bash
# 각 워커에서
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-startup
./stop.sh
rm -rf /opt/kopens/plantpulse-platform

# 데이터 디스크는 별도 정책으로 관리 (필요 시 백업 후 삭제)
```

## 관련 문서

* [시작 가이드](/plantpulse-platform/installation/startup-guide.md)
* [운영 관리](/plantpulse-platform/installation/database.md)
* [모듈: storage](/plantpulse-platform/admin/modules/storage.md)
* [모듈: messaging](/plantpulse-platform/admin/modules/messaging.md)
* [모듈: analytics](/plantpulse-platform/admin/modules/analytics.md)
* [백업 및 복구](/plantpulse-platform/admin/backup-recovery.md)
