본문으로 건너뛰기

문제 해결

이 문서는 원라인 / Docker 설치로 운영되는 PlantPulse 플랫폼에서 자주 발생하는 문제와 해결 방법을 안내합니다. 대부분의 문제는 아래 절차를 순서대로 따라가면 해결할 수 있습니다.

컨테이너는 아홉 개입니다

플랫폼은 Docker Compose 스택으로 동작합니다 — 인증서 하나(plantpulse-certs), 데이터레이크 하나, 앱 여섯, 프록시 하나. 아홉 개 모두 상시 동작하며 (healthy) 가 정상입니다. 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 상태에서 회복되지 않음​

원인해결
Aster TSDB 스키마 마이그레이션 실패./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 는 인증서를 한 번 굽고 계속 떠 있으면서 만료를 감시합니다. (healthy) 가 정상입니다. 헬스체크는 프로세스가 살아 있는지가 아니라 볼륨의 자재가 쓸 만한지를 봅니다 — 만료까지 남은 시간, 키스토어가 열리는지까지 확인합니다.

증상: 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

# 특정 포트 점유 프로세스 확인 (예: 80)
ss -tlnp | grep :80

# 충돌 프로세스를 종료한 후 재시도
./restart.sh

상세 포트 목록은 포트 및 서비스 관리 페이지를 참고해 주세요.

이미지 / 레지스트리 문제​

증상: docker pull → unauthorized: authentication required​

레지스트리 인증이 만료되었거나 자격증명이 없는 상태입니다.

docker login docker.kopens.io
# Username/Password 입력 후, 하던 설치 · 업그레이드 원라이너를 다시 실행

증상: 이미지 다운로드 실패 (네트워크)​

# 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 refusedPostgreSQL 컴포넌트 다운컨테이너 내부에서 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/ 밑에 같은 이름이 남아 있을 수 있지만 읽지 않으며, 설치 스크립트가 정본으로 되돌립니다 → 환경 변수 레퍼런스

Aster TSDB (시계열 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 을 엽니다
ss -tlnp | grep -E ':(80|443)\s'
증상원인해결
페이지가 열리지 않음plantpulse-proxy 가 비정상./status.sh 로 프록시 상태 확인. 프록시가 80/443 을 받는 유일한 입구입니다
페이지가 열리지 않음방화벽 차단회사/클라우드 방화벽에서 80, 443, 4950 허용 요청
로그인 실패비밀번호 불일치기본 admin / admin123! 확인. 변경했다면 관리자에게 초기화 요청
403 Forbidden사용자 권한 부족관리자에게 역할(role) 확인 요청
세션 만료30분 무활동 시 자동 로그아웃다시 로그인

데이터 수집 문제​

데이터 수집 경로: OPC 서버 → 메시지 브로커(Kafka/MQTT) → 엔진 파이프라인 → Aster TSDB. 이 경로 중 한 곳이라도 막히면 데이터가 들어오지 않습니다.

증상: 데이터가 수집되지 않음​

점검 항목확인 방법
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 상향
Aster TSDB 쓰기 지연pd node compactionstats 확인, 디스크 I/O 모니터링
Kafka lagpd 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 으로 분석합니다.

알람 문제​

증상원인해결
알람이 발생하지 않음알람 설정이 해제 상태알람 > 고급 알람에서 체크 → 선택된 알람 설정 배치
값은 넘었는데 알람이 목록에 없음잠시 숨김 · 계획정비 또는 수리 억제 · 서비스 제외숨김 · 억제 · 서비스 제외 확인. 숨긴 발생은 GET /api/v5/alarm/suppressed 로도 봅니다
알람 푸시가 거듭 옴억제 시간이 0알람 설정의 중복 알람 억제 → 억제 시간 (분)
복귀가 거절됨복귀 점검 실패(값이 정상 범위가 아니거나 10분 안의 값이 없음)값을 확인한 뒤 다시 복귀하거나, 사유를 적고 그래도 복귀
스테이트먼트 저장이 거절됨종류별 필수 출력 칸이 없음종류별 필수 칸
알람 설정 생성이 422 (API)직접 지은 IDGET /api/v5/alarm/config/new-id 로 받은 ID 를 씁니다
이메일 알림 미발송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

오브젝트 스토어(RustFS) 문제​

로그에 AccessDenied 가 끝없이 찍힙니다​

[RUSTFS] level=ERROR op=GetObject err=S3Error(code: AccessDenied, message: "Access Denied")

자격증명 문제가 아닙니다. 관리 API 의 지표 수집기가 2초마다 옛 MinIO 메트릭 경로(/minio/v2/metrics/cluster)를 부르는데, RustFS 에는 그 경로가 없어 요청이 S3 라우터로 떨어집니다. 그러면 버킷 이름이 minio 인 조회로 읽히고, 수집기는 서명을 붙이지 않으므로 익명 요청이 되어 거부됩니다.

물음답
데이터가 위험한가아닙니다. 읽기 시도 하나가 거부되는 것이고 저장물과 무관합니다
비밀번호를 고치면 되나아닙니다 — 운영자가 손댈 자리가 아닙니다. 요청을 보내는 쪽이 서명을 붙이지 않는 우리 수집기이고, 설령 서명하게 만들어도 지표는 여전히 비어 있습니다(없는 엔드포인트이기 때문입니다)
얼마나 찍히나2초 주기 — 하루 4만 줄이 넘습니다
지금 할 일이 서명을 «아는 잡음» 으로 두고 넘기십시오. 진짜 오류가 묻히지 않게, 로그를 볼 때 이 한 줄을 걸러 내고 보십시오
언제 사라지나2026.09 다음 판에서 사라집니다 — 수집기가 없는 엔드포인트를 아예 부르지 않도록 고쳤습니다 — 하루 약 4만 3천 줄이 사라집니다(41 실측: 반영 뒤 36분 연속 0줄)
로그가 조용해져도 «지표는» 돌아오지 않습니다

다음 판에서 사라지는 것은 로그 줄이지 값이 아닙니다. 오프라인 드라이브 · 오프라인 노드 · 용량 알람은 그 뒤에도 값을 받지 못합니다 — RustFS 에 메트릭 경로가 생겨야 바뀝니다. 조용해진 것을 「고쳐졌다」로 읽지 마십시오.

MinIO 시절에는 200 이었습니다

그때는 메트릭 경로가 인증 없이 열려 있어(MINIO_PROMETHEUS_AUTH_TYPE=public) 수집이 됐습니다. RustFS 로 바꾸면서 대응하는 설정이 없어 그 일곱 지표(minio_cluster_*)는 더 이상 오지 않습니다. 콘솔에서 그 값들이 비어 보이는 것도 같은 이유입니다.

디스크 / 볼륨 문제​

증상: 디스크 공간 부족​

# 호스트 디스크 사용량
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 으로 정리 (이미지/네트워크/캐시)
Aster TSDB SSTable 누적컨테이너 내부에서 pd node cleanup, pd node compact
로그 디렉토리 비대/opt/kopens/plantpulse-platform-docker/logs 정리

주의: docker volume prune 은 사용 중이 아닌 볼륨을 모두 삭제합니다. pp-* 볼륨이 실수로 지워지지 않도록 컨테이너를 정지 상태로 두지 마세요.

증상: 볼륨 데이터 복구가 필요​

운영 관리 - 백업과 복구 페이지의 복구 절차를 참고해 주세요.

업데이트 / 롤백 문제​

증상: 업그레이드 후 컨테이너가 정상 동작하지 않음​

판 올리기는 설치 원라이너 재실행이 공식 절차입니다. 업그레이드가 실패하면 원라이너가 업그레이드 직전 백업으로 이전 판에 자동으로 되돌립니다(UPGRADE FAILED 블록에 백업 위치가 찍힙니다). 찍힌 검사 항목을 보고 원인을 고친 뒤 같은 원라이너를 다시 실행합니다. 손으로 되돌릴 때는 bin/upgrade-rollback.sh <백업 위치> 를 씁니다. ./update.sh 로 이미지 태그만 바꿔 되돌리지 마세요 — 운영 스크립트 · compose 는 새 판 그대로 남습니다.

증상: 업데이트 중 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 실측으로 Aster TSDB 가 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

관련 문서​