네이티브 설치 — 컨테이너 없이 호스트에 직접 설치
이 페이지는 PlantPulse Edge 를 Docker 없이 호스트 OS 위에 직접(native) 설치해서 운영하는 방식을 정리합니다.
게이트웨이 런타임(Tomcat / Cassandra / Redis / HiveMQ / Time-Series-Engine / Node-RED)을 각각 호스트
프로세스로 띄우고, plantpulse.service (systemd) 하나가 전체 스택을 관리합니다.
- 개발 / 디버그 워크스테이션 — 코드를 직접 올리고 JSP / 클래스 hot-swap 으로 빠르게 검증
- 2026.05 미만 legacy 박스 유지보수 — 이미 native 로 운영 중인 현장
- Docker 사용이 불가한 보안 정책 환경
신규 양산/현장 1대 설치의 표준은 컨테이너 모드입니다 →
빠른 설치 (install.sh) / 도커(컨테이너) 설치 상세.
네이티브는 plantpulse.service, 컨테이너는 plantpulse-edge.service 를 사용합니다.
두 서비스를 동시에 띄우면 80/443/1880/9042/12000 등 포트와 /data1 데이터 경로가 충돌합니다.
systemctl is-active plantpulse-edge.service 가 active 면 그 박스는 컨테이너 박스입니다 —
네이티브를 올리기 전에 반드시 한쪽을 stop/disable 하세요.
1. 런타임 모델 — 무엇이 어떻게 도는가
네이티브 모드는 게이트웨이를 구성하는 7개 컴포넌트를 각각 호스트 프로세스로 실행합니다.
오케스트레이션은 $PE_HOME/bin/ 의 bash 스크립트가 담당하고, 각 컴포넌트는 자기 디렉터리의
bin/start.sh / bin/stop.sh 를 가집니다.
| 컴포넌트 | 역할 | 디렉터리 |
|---|---|---|
Redis (cache) | 포인트 큐 (Redisson) | $PE_HOME/cache/ |
HiveMQ (mqtt) | MQTT broker / Sparkplug B | $PE_HOME/mqtt/ |
Cassandra (db) | 시계열 저장 (pe keyspace) | $PE_HOME/db/ |
Time-Series-Engine (tse) | 시계열 엔진 | $PE_HOME/timeseries/engine/ |
| Dashboard | 대시보드 | $PE_HOME/timeseries/dashboard/ |
Tomcat (server) | webapp plantpulse-edge-web (수집/REST/OPC-UA/UI) | $PE_HOME/server/ |
Node-RED (node) | 플로우 (/ui/flow) | $PE_HOME/node/ |
부팅 순서 (의존성 순) — bin/start.sh 가 이 순서로 기동합니다:
cache → mqtt → db → tse → dashboard → server → node
- HTTP 80 / HTTPS 443 로 웹 UI 와 REST API 제공 (8080 아님)
- JVM 은 JDK 21 (class file version 65) — Spring MVC 6.2 (non-boot)
- graceful shutdown:
ServerStartListener가 collector → Redisson → OPC → Cassandra 정리 후Runtime.halt(0). 데드라인 watchdog(-Dplantpulse.edge.shutdown.deadline.ms, 기본 9000ms)이 STOP_TIMEOUT 레이스를 막습니다.
2. 디렉터리 구조 ($PE_HOME = /opt/kopens/plantpulse-edge)
$PE_HOME/
├── app/plantpulse-edge-web/ # webapp (WEB-INF/classes·jsp·lib + public)
├── bin/ # 오케스트레이션 스크립트 (아래 6장)
│ ├── start.sh / stop.sh # full stack — cache→mqtt→db→tse→dashboard→server→node
│ ├── restart.sh # Tomcat(server) + Node-RED 만
│ ├── lifecycle-lib.sh # pp_log / pp_wait_port / run_module_start 헬퍼
│ ├── upgrade.sh / firmware.sh / backup.sh / clean.sh / reboot.sh
│ └── log-viewer.sh / node-*.sh
├── conf/ # canonical 설정 (운영자 편집)
│ ├── app.properties # webapp 설정 (이 박스가 canonical)
│ └── env.sh # JAVA_HOME / PP_LANG / PP_TZ / PE_DATA_DIR …
├── server/ # Tomcat (bin/ conf/ logs/)
│ ├── bin/setenv.sh # JVM 옵션 / LOCALE / -Dpe.conf.dir
│ ├── conf/server.xml # Connector(80/443) / Context
│ └── logs/ # catalina.out / system.log / api.log / driver.log
├── cache/ → Redis (bin/start.sh / stop.sh)
├── db/ → Cassandra (bin/start.sh / stop.sh)
├── mqtt/ → HiveMQ (bin/start.sh / stop.sh)
├── timeseries/engine/ + dashboard/
└── node/ → Node-RED (userDir/node_modules/node-red-contrib-plantpulse-edge/)
데이터 디렉터리는 $PE_DATA_DIR(기본 /data1)로 분리합니다 (Cassandra SSTable / Redis AOF / HiveMQ / Node-RED userDir).
3. 사전 요구 (native)
| 항목 | 기준 |
|---|---|
| OS | Linux (RHEL/Rocky/Alma/Fedora 계열 권장) |
| 권한 | root (sudo -i) |
| JDK | OpenJDK 21 (dnf install java-21-openjdk java-21-openjdk-devel) — class file 65 호환 |
| Node.js | Node-RED 용 (nodejs / npm) |
| Python 3 | 보조 스크립트 |
| 디스크 | /opt/kopens 3GB+, /data1 100GB+ 권장 |
| 메모리 | 최소 8GB (Cassandra heap + Tomcat heap), 16GB+ 권장 |
| NIC | 산업 어플라이언스 표준 2개 (1=WAN/외부, 2=PLC/내부) |
| 시각 | NTP(chrony) 동기 |
OS 패키지, sysctl/limits, 방화벽, chrony, NIC static, SSL 발급, systemd 등록까지
한 번에 처리하는 자동 native 설치 도구가 별도로 있습니다 →
(legacy) H/W 전체 설치 (tools/setup.sh). 본 페이지는 그 도구가 깔아놓는
런타임 구조와 수동/디버그 기동 절차를 다룹니다.
4. 설치 절차
4.1 자동 (권장) — tools/setup.sh
OS 부팅 직후 빈 박스라면 자동 설치 도구가 패키지 · 네트워크 · 튜닝 · JDK · systemd 까지 한 번에 정렬합니다. 단계별 입력(호스트명, NIC, 방화벽 포트)과 22단계 상세는 (legacy) H/W 전체 설치를 그대로 따릅니다.
sudo -i
cd /opt/kopens/tools
./setup.sh # 대화형 — 호스트명 + NIC 입력 후 진행, 끝나면 10초 후 자동 reboot
재부팅 후 plantpulse.service 가 자동으로 풀스택을 기동합니다.
4.2 수동 / 디버그 — 런타임만 올리기
이미 OS / JDK 21 / 네트워크가 준비된 박스(또는 개발 워크스테이션)에 런타임 배치만 올릴 때:
sudo -i
# 1) 런타임 배치를 $PE_HOME 에 펼침 (운영팀 제공 native bundle 기준)
# /opt/kopens/plantpulse-edge/{app,bin,conf,server,cache,db,mqtt,timeseries,node}
# 2) 환경 파일 확인 — JDK 21 / 언어 / 시간대 / 데이터 경로
cat $PE_HOME/conf/env.sh
# export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
# export PP_LANG="${PP_LANG:-en}" / export PP_TZ="${PP_TZ:-Asia/Seoul}"
# export PE_DATA_DIR=/data1
# (상세: env 환경 설정 페이지)
# 3) 메인 설정 — 사이트/플랫폼/DB/MQTT 값
vi $PE_HOME/conf/app.properties # edge.id / edge.site_id / server.host / cassandra.* …
# 4) 풀스택 기동 (cache→mqtt→db→tse→dashboard→server→node)
$PE_HOME/bin/start.sh
env.sh/app.properties환경 변수 레이어 상세는 env 환경 설정,app.properties키 전체는 app.properties 가이드를 봅니다.
5. systemd 통합 — plantpulse.service
설치가 끝나면 systemd 가 풀스택을 자동 관리합니다.
sudo systemctl enable plantpulse # 부팅 시 자동 시작 등록
sudo systemctl start plantpulse # 시작 (ExecStart → service-start.sh → bin/start.sh)
sudo systemctl stop plantpulse # 정지 (ExecStop → service-stop.sh → bin/stop.sh)
sudo systemctl status plantpulse # 상태
sudo systemctl restart plantpulse # 풀스택 재시작 (60초+ 다운타임)
sudo journalctl -u plantpulse -n 100 # systemd 로그 마지막 100줄
내부 wiring:
plantpulse.service ─ ExecStart=service-start.sh ─→ bin/start.sh (cache→mqtt→db→tse→dashboard→server→node)
└ ExecStop =service-stop.sh ─→ bin/stop.sh
bin/restart.sh 는 Tomcat(server) + Node-RED 만 재시작합니다(~6초, Cassandra/Redis 유지).
app.properties 수정 반영이나 webapp 갱신은 이걸 쓰세요.
systemd restart 는 stop.sh → start.sh 풀스택이라 60초+ 다운타임이 발생합니다.
상세: 재시작 (restart.sh).
6. bin 스크립트 카탈로그
| 스크립트 | 범위 | 비고 |
|---|---|---|
bin/start.sh | 풀스택 기동 | cache→mqtt→db→tse→dashboard→server→node |
bin/stop.sh | 풀스택 정지 | 컴포넌트별 stop.sh 호출, STOP_TIMEOUT_SECONDS(기본 10s) 초과 시 kill -9 |
bin/restart.sh | Tomcat + Node-RED 만 | ~6초, 코드/설정 반영용 |
bin/backup.sh | 설정 백업 | 백업 가이드 |
bin/upgrade.sh | 업그레이드 | 업그레이드 |
bin/clean.sh | 작업 디렉터리 정리 | 정리/청소 |
bin/reboot.sh / firmware.sh | 호스트 reboot / 펌웨어 | — |
bin/log-viewer.sh | 7개 컴포넌트 로그 tail | 무한 tail -f — 자동화/비대화 SSH 에선 직접 호출 금지(세션 hang) |
각 run() 은 catch(Throwable) 가드 + awaitTermination 으로 안전하게 종료됩니다.
7. 설치 후 정상 동작 확인 (1분)
# 1) systemd 서비스 살아있는지
systemctl status plantpulse # active (running)
# 2) 시스템 헬스 — HTTP 200 이면 게이트웨이 정상
curl -s http://127.0.0.1/api/v1/system/health | python3 -m json.tool
# 3) OPC-UA 트리 (등록 0 이어도 빈 배열이면 OK)
curl -s http://127.0.0.1/ui/opcua/tree | python3 -c 'import sys,json;print(len(json.load(sys.stdin)["data"]["tree"]))'
# 4) 웹 UI
# 브라우저 → https://<게이트웨이>/ui/main (로고 + 카드가 보이면 정상)
로그 전수 확인 — catalina.out(부팅 실패) + system.log(ERROR/Exception) 뿐 아니라
7개 컴포넌트(server/cache/db/mqtt/tse/dashboard/node) 로그를 모두 SEVERE/ERROR 없는지 본다.
자동화에선 log-viewer.sh(무한 tail) 대신 각 logs/*.log 를 tail -n / timeout 으로 bounded 하게 읽는다.
restart 후 ServerStartListener 가 조용히 실패해 collector 미완료(OPC 카운트 0)면 restart.sh 한 번 더.
단 /api/v1/system/health 의 data.monitor=null (+ data.api_client=null)은 race 가 아니라 설계입니다
(HealthResponse.livenessWithComponents 가 그 두 필드를 비워둠).
8. 자주 빠지는 함정
| 증상 | 원인 / 해결 |
|---|---|
UnsupportedClassVersionError (class file 65) | JDK 21 미설치/미지정. env.sh 의 JAVA_HOME=/usr/lib/jvm/java-21-openjdk 확인 |
| UI 언어가 의도와 다름(ko/en) | setenv.sh 의 -Duser.language 가 JAVA_TOOL_OPTIONS 보다 우선. env 환경 설정의 LOCALE 동적화 참고 |
connect ECONNREFUSED 127.0.0.1:80 | Tomcat 미기동. bin/restart.sh 또는 bin/stop.sh+start.sh |
| 포트/데이터 충돌 | 같은 박스에 plantpulse-edge.service(컨테이너)도 active. 한쪽 stop/disable |
정지 시 kill -9 발생 | cleanup(~10s)이 STOP_TIMEOUT_SECONDS(10s)와 레이스. deadline watchdog 으로 완화. 완전 clean 원하면 STOP_TIMEOUT 25 + deadline 20000 |
| 재부팅 후 안 뜸 | journalctl -u plantpulse --no-pager 로 unit 실패 원인 → bin/start.sh 직접 실행하며 막히는 지점 확인 |
9. 다음 문서
- env 환경 설정 —
env.sh/PP_LANG/PP_TZ/-Dpe.conf.dir - 도커(컨테이너) 설치 상세 — 양산 표준 배포
- (legacy) H/W 전체 설치 (
tools/setup.sh) — 자동 native 설치 22단계 - app.properties 가이드 — 메인 설정 키 전체
- 재시작 (
restart.sh) / 시작 (start.sh) / 중지 (stop.sh) - 설치 직후 체크리스트 / 프로덕션 인수 기준