문제 해결
이 문서는 원라인 / Docker 설치로 운영되는 PlantPulse 플랫폼에서 자주 발생하는 문제와 해결 방법을 안내합니다. 대부분의 문제는 아래 절차를 순서대로 따라가면 해결할 수 있습니다.
플랫폼은 Docker Compose 스택으로 동작합니다 — 인증서 원샷 하나(plantpulse-certs, Exited (0) 이 정상), 데이터레이크 하나, 앱 여섯, 프록시 하나. plantpulse-platform 이라는 이름의 컨테이너는 없습니다.
「무엇이 고장났나」를 먼저 좁히세요. ./status.sh 가 서비스별로 답합니다 → 설치되는 모양
첫 단계: 어떤 문제든 우선 아래 3가지를 먼저 확인해 주세요.
cd /opt/kopens/plantpulse-platform-docker/bin./status.sh # 컨테이너 / health / 볼륨 요약./ops-check.sh # 운영 health + critical log./logs.sh -n 200 # 최근 컨테이너 로그 (전체)그래도 해결되지 않으면
./doctor.sh로 진단 tarball 을 생성하여 기술 지원팀에 전달해 주세요.
컨테이너 기동 문제
증상: 컨테이너가 unhealthy 상태에서 회복되지 않음
| 원인 | 해결 |
|---|---|
| Cassandra 스키마 마이그레이션 실패 | ./logs.sh cassandra -n 300 으로 에러 확인 후 ./restart.sh 시도. 반복 실패 시 ./doctor.sh |
| 데이터 디렉토리 권한 문제 | 호스트의 /data1/pp-data 권한 확인. sudo chown -R root:root /data1/pp-data && sudo chmod -R 755 /data1/pp-data |
| 메모리 부족 (OOMKilled) | docker inspect <컨테이너> --format '{{.State.OOMKilled}}' 로 확인. 컨테이너마다 한계값이 다릅니다 — 데이터레이크는 DOCKER_DATALAKE_MEMORY, 앱은 DOCKER_SERVER_MEMORY 등 (환경 변수) |
| JVM warm-up 미완료 | 부팅에는 3~5분 소요됨. 5분 이상 unhealthy 가 지속되면 다음 단계 진단 |
# 어떤 서비스가 비정상인가 (0 = 정상 / 2 = 비정상)
./status.sh
# 스택 전체 준비 판정
./stack-verify-boot.sh
# 컨테이너별 메모리 / CPU
docker stats --no-stream
# 헬스체크 엔드포인트 응답 확인
curl -kfsS https://<서버IP>:4950/api/health | jq
plantpulse-certs 는 인증서를 굽고 스스로 끝나므로 Exited (0) 이 성공 상태입니다. compose 가 이 컨테이너의 헬스체크를 명시적으로 꺼 두었기 때문에(healthcheck: disable) health 칸은 비어 있고, 정상 동작하는 컨테이너가 unhealthy 로 보이는 일도 없습니다. status.sh 와 ops-check.sh 는 이 컨테이너만 종료 코드로 판정하니, 손으로 볼 때도 그렇게 봐 주세요.
증상: no such service · 컨테이너가 없다고 나옴
최초 설치가 완료되지 않았거나 ./remove.sh 로 컨테이너가 제거된 상태입니다.
옛 런북을 따라 plantpulse-platform 을 찾고 있었다면 그 이름의 컨테이너는 없습니다 — 이름은 ./status.sh 또는 ./logs.sh --list 로 확인하세요.
cd /opt/kopens/plantpulse-platform-docker/bin
./install.sh # 최초 설치
# 또는 OS 설정이 이미 끝났다면
./up.sh # 컨테이너 생성 + 기동
증상: address already in use (포트 충돌)
호스트에 이전 버전의 plantpulse 가 native 로 실행 중이거나 다른 서비스가 포트를 점유하고 있는 경우입니다.
# 호스트 native plantpulse 정지
pkill -ef plantpulse
# 특정 포트 점유 프로세스 확인 (예: 7500)
ss -tlnp | grep :7500
# 충돌 프로세스를 종료한 후 재시도
./restart.sh
상세 포트 목록은 포트 및 서비스 관리 페이지를 참고해 주세요.
이미지 / 레지스트리 문제
증상: docker pull → unauthorized: authentication required
레지스트리 인증이 만료되었거나 자격증명이 없는 상태입니다.
docker login docker.kopens.io
# Username/Password 입력 후
./update.sh
증상: 이미지 다운로드 실패 (네트워크)
# 1. 레지스트리 접근 가능 여부 확인
curl -fsSL https://docker.kopens.io/v2/
# 2. DNS 확인
nslookup docker.kopens.io
# 3. 회사 방화벽 / 프록시 차단 가능성 — 네트워크 관리자에게 다음 도메인 허용 요청
# docker.kopens.io, download.kopens.io
폐쇄망 환경이라면 Docker 설치 페이지의 폐쇄망(Airgap) 설치 절차를 따라주세요.
데이터베이스 문제
데이터베이스 컴포넌트는 컨테이너 내부에서 동작합니다. 점검은 ./shell.sh 로 컨테이너에 진입한 뒤 수행합니다.
PostgreSQL (메타 DB)
역할: 사용자 정보, 사이트 설정, 자산 설정 등 플랫폼의 메타데이터를 저장합니다.
./shell.sh # 컨테이너 진입
# 컨테이너 내부에서
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node psql # PostgreSQL 셸 접속
psql=# SELECT 1;
psql=# SHOW max_connections;
psql=# SELECT count(*) FROM pg_stat_activity;
| 증상 | 원인 | 해결 |
|---|---|---|
| Connection refused | PostgreSQL 컴포넌트 다운 | 컨테이너 내부에서 pd restart storage 실행. 호스트에서는 ./restart.sh |
| Too many connections | 연결 풀 초과 | properties 의 connection pool 설정 검토. 일시적이면 storage 재시작 |
| Authentication failed | 비밀번호 불일치 | /etc/kopens/plantpulse-platform.env 의 PP_PG_PASSWORD 와 애플리케이션 properties 일치 여부 확인 |
경로 확인 — 시크릿 사이드카의 정본은
/etc/kopens/plantpulse-platform.env하나입니다(권한0600). 옛 설치에서/opt/kopens/밑에 같은 이름이 남아 있을 수 있지만 읽지 않으며, 설치 스크립트가 정본으로 되돌립니다 → 환경 변수 레퍼런스
Cassandra (시계열 DB)
역할: 센서 시계열 데이터, 알람 이력 등 대량 데이터를 저장합니다.
./shell.sh
# 컨테이너 내부에서
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node status # 클러스터 상태
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node compactionstats # 컴팩션 진행 상태
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node cql # CQL 셸 접속
| 증상 | 원인 | 해결 |
|---|---|---|
| Connection timeout | 노드 다운 | pd node status 로 노드 상태 확인 후 pd restart storage |
| WriteTimeout | 쓰기 지연 (디스크 I/O 포화) | pd node compactionstats 확인, pd node compact 로 수동 컴팩션 |
| ReadTimeout | 읽기 지연 (큰 파티션) | pd node table-histograms 로 파티션 크기 확인 |
| 디스크 공간 부족 | SSTable 누적 | pd node cleanup 실행 후 df -h /data1 으로 확인 |
Valkey (Redis 캐시)
./shell.sh
# 컨테이너 내부에서
redis-cli -a "$PP_REDIS_PASSWORD" ping
redis-cli -a "$PP_REDIS_PASSWORD" INFO memory
로그인 / 콘솔 접속 문제
증상: 브라우저에서 콘솔에 접속이 안 됨
# 1. 컨테이너 health 확인
./status.sh
# 2. 외부 노출 IP 설정 확인
grep DOCKER_PP_EXTERNAL_IP env.sh
# 3. 호스트 방화벽 확인
sudo firewall-cmd --list-ports # RHEL/Rocky/Oracle
sudo ufw status # Ubuntu
# 4. 포트 점유 확인 — 프록시가 80/443 을, 데이터레이크가 7443 을 엽니다
ss -tlnp | grep -E ':(80|443|7443)\s'
| 증상 | 원인 | 해결 |
|---|---|---|
| 페이지가 열리지 않음 | plantpulse-proxy 가 비정상 | ./status.sh 로 프록시 상태 확인. 프록시가 80/443 을 받는 유일한 입구입니다 |
| 페이지가 열리지 않음 | 방화벽 차단 | 회사/클라우드 방화벽에서 80, 443, 7443, 4950 허용 요청 |
| 로그인 실패 | 비밀번호 불일치 | 기본 admin / admin123! 확인. 변경했다면 관리자에게 초기화 요청 |
| 403 Forbidden | 사용자 권한 부족 | 관리자에게 역할(role) 확인 요청 |
| 세션 만료 | 30분 무활동 시 자동 로그아웃 | 다시 로그인 |
데이터 수집 문제
데이터 수집 경로: OPC 서버 → 메시지 브로커(Kafka/MQTT) → 엔진 파이프라인 → Cassandra. 이 경로 중 한 곳이라도 막히면 데이터가 들어오지 않습니다.
증상: 데이터가 수집되지 않음
| 점검 항목 | 확인 방법 |
|---|---|
| OPC 연결 상태 | 웹 콘솔 > 연결 관리 > 상태에서 CONNECTED 확인 |
| 엔진 상태 | 콘솔 > 모니터링 > 시스템 상태에서 RUNNING 확인 |
| 파이프라인 | MPS(초당 메시지 수) 가 0 이면 수신 중단 |
| 메시지 브로커 | ./shell.sh 진입 후 /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node topic 로 Kafka 토픽 확인 |
| 네트워크 | OPC 서버 → 플랫폼 호스트 IP 핑 / telnet |
증상: 데이터 지연
| 원인 | 해결 |
|---|---|
| 파이프라인 큐 적체 | properties 의 engine.pipeline.threads 상향 |
| Cassandra 쓰기 지연 | pd node compactionstats 확인, 디스크 I/O 모니터링 |
| Kafka lag | pd node topic 로 consumer lag 확인 |
| 네트워크 지연 | OPC 서버 ↔ 플랫폼 호스트 RTT 측정 |
성능 문제
증상: 콘솔 / API 응답이 느림
# 호스트에서 컨테이너 자원 사용량
docker stats --no-stream
# 앱 컨테이너의 JVM 메모리 (그 앱이 도는 컨테이너 안에서)
./shell.sh plantpulse-server-web
jmap -heap $(pgrep -f plantpulse-server)
앱 여섯은 각자 컨테이너에서 돌기 때문에, 데이터레이크 안에서 앱 프로세스를 찾으면 나오지 않습니다. ./status.sh 로 대상 컨테이너를 확인한 뒤 ./shell.sh <컨테이너> 로 들어가세요.
| 원인 | 해결 |
|---|---|
| 컨테이너 메모리 부족 | 해당 컨테이너의 한계값 상향 후 ./restart.sh — 데이터레이크는 DOCKER_DATALAKE_MEMORY, 앱은 DOCKER_SERVER_MEMORY 등 (환경 변수) |
| JVM 메모리 부족 | 컨테이너 내부 setenv 의 힙 크기 조정 (자세한 내용은 성능 튜닝) |
| GC 빈번 | GC 로그 분석, G1GC 옵션 튜닝 |
| DB 슬로우 쿼리 | PostgreSQL slow query 로그 확인 |
| 호스트 CPU 포화 | top / htop 확인 후 DOCKER_PP_CPUS 상향 검토 |
증상: OutOfMemoryError
# 컨테이너 내부에서 heap dump 활성화
./shell.sh
# setenv 또는 JAVA_TOOL_OPTIONS 에 -XX:+HeapDumpOnOutOfMemoryError 추가
# 생성된 hprof 를 호스트로 복사
docker cp plantpulse-datalake:/path/to/heap.hprof /tmp/
Eclipse MAT / VisualVM 으로 분석합니다.
알람 문제
| 증상 | 원인 | 해결 |
|---|---|---|
| 알람이 발생하지 않음 | 알람 설정 미배포 | 알람 설정 화면에서 "배포" 클릭 |
| 알람 중복 발생 | 중복 체크 비활성화 | 알람 설정에서 중복 체크 활성화 |
| 이메일 알림 미발송 | SMTP 설정 오류 | mail.properties 확인 (컨테이너 내부 /opt/kopens/plantpulse-platform/plantpulse-server/config/) |
| 알림 소리 안남 | 브라우저 자동재생 정책 | 브라우저 설정에서 사이트 자동재생 허용 |
UI 문제
| 증상 | 해결 |
|---|---|
| 화면이 깨짐 | 브라우저 캐시 삭제 (Ctrl+Shift+Delete) |
| 차트 미표시 | 브라우저 개발자 도구(F12) > Console 에서 JS 에러 확인 |
| 실시간 갱신 끊김 | 프록시/방화벽의 SSE(HTTP 스트리밍) 버퍼링·타임아웃 설정 확인 |
| 대시보드 로드 실패 | 연결된 태그 / 데이터 소스 존재 여부 확인 |
| 한글 깨짐 | env.sh 의 PP_LANG=ko, PP_TZ=Asia/Seoul 확인 후 ./restart.sh |
디스크 / 볼륨 문제
증상: 디스크 공간 부족
# 호스트 디스크 사용량
df -h
df -h /data1 # 데이터 디스크
# Docker 사용량 (이미지 / 볼륨 / 빌드 캐시)
docker system df
# 컨테이너 내부 사용량
./shell.sh
df -h
du -sh /opt/kopens/plantpulse-platform/plantpulse-storage/db/cassandra/data
| 원인 | 해결 |
|---|---|
| 오래된 백업 누적 | /data1/pp-backup/docker-volume 의 오래된 tar.gz 정리 |
| Docker 미사용 이미지 | docker system prune 으로 정리 (이미지/네트워크/캐시) |
| Cassandra SSTable 누적 | 컨테이너 내부에서 pd node cleanup, pd node compact |
| 로그 디렉토리 비대 | /opt/kopens/plantpulse-platform-docker/logs 정리 |
주의:
docker volume prune은 사용 중이 아닌 볼륨을 모두 삭제합니다.pp-*볼륨이 실수로 지워지지 않도록 컨테이너를 정지 상태로 두지 마세요.
증상: 볼륨 데이터 복구가 필요
운영 관리 - 백업과 복구 페이지의 복구 절차를 참고해 주세요.
업데이트 / 롤백 문제
증상: 업데이트 후 컨테이너가 정상 동작하지 않음
./update.sh 는 health 검증에 실패하면 자동으로 이전 이미지로 rollback 합니다. 수동 rollback 이 필요한 경우:
# 1. 이전 버전 태그를 env.sh 에 지정
vi env.sh
# PP_IMAGE_TAG="2026.04" ← 이전 안정 버전
# 2. 업데이트 재실행
./update.sh
증상: 업데이트 중 NOT FOUND CONTAINER
최초 설치(./install.sh)가 안 된 상태입니다. 먼저 설치를 수행해 주세요.
네트워크 / 클러스터 문제
증상: 워커가 마스터에 join 되지 않음
# 1. 워커 컨테이너 진입 (워커는 기본 스택의 서비스가 아니라 shell.sh 로는 잡히지 않습니다)
docker exec -ti plantpulse-worker-1 /bin/bash
# 워커 내부에서 마스터 IP 로 연결 테스트
ping ${PP_MASTER_IP}
# 2. 마스터에서 링 확인 — 이것이 조인의 «유일한» 증거입니다
cd /opt/kopens/plantpulse-platform-docker/bin
./shell.sh
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node status
# 3. JGroups / Cassandra 포트 (7000, 7001, 7800, 7801, 9042) 방화벽 허용 확인
조인에 실패한 워커도 성공한 워커와 똑같이 정상으로 보고합니다 — 컨테이너의 자체 검사는 «마스터에 닿는가»만 보기 때문입니다. 2026-08-31 실측으로 Cassandra 가 OOMKilled 된 워커가 링은 1노드인 채로 health: starting 을 유지했습니다.
반드시 pd node status 의 링 목록으로 판정하세요. 워커 추가는 bin/worker-add.sh 가 이 확인을 대신 해 줍니다 → 클러스터 설치
증상: MQTT / Kafka 외부 클라이언트 연결 실패
호스트 방화벽과 회사/클라우드 방화벽에서 1883/1884 (MQTT), 9092/9093/9094 (Kafka) 가 허용되었는지 확인해 주세요. 자세한 포트 목록은 포트 구성 정보 를 참고해 주세요.
- MQTT 는
plantpulse-proxy가 받습니다. 설비는 이 호스트만 알면 되고, 브로커가 옮겨가거나 이름이 바뀌어도 설비 설정을 건드릴 필요가 없습니다. 1884 는 TLS passthrough 라 브로커가 TLS 를 종단합니다. - Kafka 는 프록시를 거치지 않습니다. 클라이언트가 부트스트랩 후
advertised.listeners주소로 다시 접속하기 때문입니다 — 부트스트랩만 성공하고 그 뒤가 조용히 실패한다면 이 주소를 먼저 의심하세요.
긴급 대응
컨테이너가 응답하지 않을 때
cd /opt/kopens/plantpulse-platform-docker/bin
# 1. 상태 확인
docker ps -a
./status.sh
# 2. 로그에서 마지막 에러 확인
./logs.sh -n 200
# 3. 안전 재시작
./restart.sh
# 4. 위 단계로 회복 안 될 경우 진단 tarball 생성
./doctor.sh
# 생성된 tarball 을 webmaster@kopens.com 으로 전달
데이터 손상 의심 시
# 1. 즉시 정지 (추가 손상 방지)
./down.sh
# 2. 최신 백업 확인
ls -lh /data1/pp-backup/docker-volume/
# 3. 진단 tarball 생성 (절대 데이터를 임의로 수정하지 마세요)
./doctor.sh
# 4. 기술 지원팀 연락
데이터 손상 시 금지 사항: 직접
pd node repair,pd node cleanup, SSTable 삭제 등을 수행하지 마세요. 잘못된 복구 작업은 손상을 확대시킬 수 있습니다. 반드시 기술 지원팀과 협의 후 진행해 주세요.
지원 요청 시 필요한 정보
위 방법으로 해결되지 않으면 아래 정보를 함께 보내주시면 빠른 분석이 가능합니다.
| 항목 | 수집 방법 |
|---|---|
| 진단 tarball | ./doctor.sh 실행 후 생성된 파일 |
| 컨테이너 로그 | ./logs.sh -n 500 > /tmp/container.log 2>&1 (여덟 컨테이너 전부) |
| 모듈별 로그 | ./tools/copy-log-to-local.sh 결과 (/tmp/plantpulse-log/) |
| 이미지 버전 | ./stack-version.sh 출력 |
| 환경 변수 | env.sh (비밀번호는 마스킹) |
| 시스템 정보 | OS, CPU, 메모리, 디스크 (uname -a, free -h, df -h) |
| 에러 메시지 | 정확한 에러 메시지 / 브라우저 콘솔(F12) 캡처 |
| 재현 절차 | 문제 발생 직전에 수행한 작업 순서 |
기술 지원: webmaster@kopens.com