본문으로 건너뛰기

pd — 데이터레이크 CLI

pd(PlantPulse DataLake)는 데이터레이크 컨테이너 안에서 서비스 여덟 개를 기동 · 정지 · 진단하고, 설정을 렌더하고, 백업을 찍는 단일 진입점 명령입니다. 관리 콘솔이 보여 주는 거의 모든 것이 이 명령의 --json 출력입니다.

항목
모듈plantpulse-datalake-cli
위치컨테이너 안 /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd (PATH 에 있음)
호스트에는없습니다 — 반드시 docker exec plantpulse-datalake pd …
docker exec plantpulse-datalake pd status # 하나만 칠 때
/opt/kopens/plantpulse-platform-docker/bin/shell.sh # 여러 개 칠 때 — 셸을 열고 pd … 만 친다
운영자의 첫 진입점은 여기가 아닙니다

플랫폼 전체의 시작 / 정지 / 재시작은 호스트의 /opt/kopens/plantpulse-platform-docker/bin/ 에서 합니다 — up.sh · down.sh · restart.sh · restart-datalake.sh · status.sh 입니다. pd 는 그보다 한 겹 아래, 컨테이너 의 서비스를 다루는 도구입니다. 컨테이너 자체도 켜질 때 pd start, 꺼질 때 pd stop 을 돌리므로 운영자가 pd start 를 손으로 칠 일은 드뭅니다. 대부분 «상태 보기» 와 «서비스 하나 재기동» 입니다.

30초 요약

안전 등급: 읽기 = 아무것도 안 바꿈 · 변경 = 상태를 바꿈 · 파괴적 = 데이터나 프로세스를 지움.

동사한 줄등급
pd status [서비스] [--wait]포트 표. 전 행 RUNNING 일 때만 exit 0읽기
pd doctor환경 · 시크릿 · 템플릿 · 런타임 트리 검사 (PASS / FAIL / N/A)읽기
pd env이 노드의 디렉터리 · 이미지 정체 — 선언만, 측정 없음읽기
pd logs [--list] [--lines N] [서비스…]서비스 로그 따라가기읽기
pd storage볼륨 · WAL · 복제 슬롯 · 저장소 크기 · Kafka 보존읽기
pd retention테이블 TTL · 토픽 보존 · 콜드 티어 · 아카이브 잡읽기
pd flowKafka 컨슈머 그룹 lag읽기
pd downtime계획 밖으로 죽어 있던 구간 — 재기만 한다읽기
pd config list · diff · diff --templates템플릿 → 경로 표 · 런타임 vs 렌더 · 호스트 템플릿 vs 이미지 기본값읽기
pd node status · info · cql · psqlCassandra / PostgreSQL 조회와 셸읽기
pd backup list · schedule · status물리 백업 세트 · 타이머 · 지금 도는 것읽기
pd backup restore … --dry-run복원 계획만읽기
pd start [서비스] · stop · restart [--clean]순서대로 기동 · 역순 정지(정지 증명) · 둘 다변경
pd config render설정 생성물을 실제로 쓴다변경
pd secret rotate VAR=값자격증명 회전 — 호스트의 passwd.sh 가 부릅니다. 직접 치지 마세요변경
pd backup · pd backup run --engine E --type full|diff논리 덤프 · 물리 백업 한 번변경
pd backup schedule set|reset백업 타이머 일정변경
pd node add · repair · compact · flush · drainCassandra 정비변경
pd clean멈춘 모듈의 로그 · 임시 파일 삭제파괴적(로그)
pd kill [--dry-run]PP_HOME 아래 프로세스 전부 SIGKILL파괴적
pd recover [파일]pp DB 를 DROP 하고 논리 덤프로 복원파괴적
pd backup restore … --yes데이터 디렉터리를 물리 백업으로 되돌림파괴적
pd node cleanup · remove <host-id>스냅샷 삭제 · 링에서 노드 제거파괴적

옵션 셋은 어느 동사에나 같은 뜻입니다.

옵션
--json사람용 표 대신 JSON 문서 하나. 콘솔이 읽는 형식. 받는 동사가 정해져 있고 다른 동사에 붙이면 exit 2 로 거부
--show-secretsconfig diff 만. 비밀번호를 *** 로 가리지 않음. --json 과 함께 쓸 수 없음
PD_DEBUG=1DEBUG 로그. PD_DEBUG=1 pd start 처럼 앞에 붙임

서비스와 기동 순서

서비스 여덟 개는 정해진 순서로 뜹니다. 정본은 services/order.txt 하나입니다. pd start 는 위에서 아래로, pd stop 은 역순입니다.

순서서비스MASTERWORKER안의 컴포넌트pd status 행(포트)
1storagevalkey → postgres → cassandra → minio(MASTER 만)6379 · 5432 · 9042 · 9000
2analyticsspark-master → hive → gravitino → kyuubi (WORKER 는 spark-worker · kyuubi)7077 · 4440 · 9083 · 19001 · 10000
3messagingkafka · mqtt(HiveMQ)9092 · 1883
4timeseriesengine(TSE) · dashboard(Grafana)7800 · 3000
5cepTomcat7400
6workflowtemporal → kestra7233 · 8233 · 8380
7data-gatewayTomcat5500
8admin-api관리 콘솔 백엔드4949
  • 각 서비스를 띄운 뒤 헬스체크가 UP 을 돌려줄 때까지 기다렸다가 다음으로 갑니다(상한: storage 1800초, analytics 600초, 나머지 300초).
  • storageanalytics문지기입니다. 안 뜨면 뒤를 시도하지 않고 exit 5. 나머지는 경고하고 계속(끝에 exit 6).
  • timeseries 는 2026-09-05 부터 MASTER 전용입니다. plantpulse-sql 은 2026-09-07 에 폐기돼 목록에서 빠졌습니다.

수명주기

pd status # 전체 표 — 마지막 줄 "0 STOPPED" 면 정상
pd status storage # 서비스 하나의 헬스체크
pd status storage --wait # UP 이 될 때까지 대기

pd start cep # 죽은 서비스 하나 다시 띄우기
pd stop cep # 서비스 하나 내리기 — «멈췄다» 를 증명한다 (30초 + SIGTERM 15초 + SIGKILL 10초)
pd restart cep # stop → (정지가 증명되면) 5초 → start
pd restart cep --clean # 사이에 pd clean
pd restart # 전부 — 몇 분 걸린다. storage 가 먼저 돌아온다

pd status 의 상태는 넷입니다.

상태
RUNNING포트가 열려 있다
STOPPED포트가 닫혀 있다. 기동 직후 몇십 초는 창(window)이니 1분 뒤 다시 본다
UNKNOWN못 쟀다 — 포트를 재는 도구가 없을 때. 죽은 것이 아니다
DISABLEDPD_OPTIONS 로 껐다. 종료 코드를 바꾸지 않는다
pd stop 이 exit 7 이면 바로 pd start 하지 마세요

STILL RUNNING 은 정지를 증명하지 못했다는 뜻입니다. 살아남은 프로세스 위에 띄우면 포트 충돌 · 데이터 손상이 납니다. pd kill --dry-run 으로 무엇이 남았는지 본 뒤 pd kill, pd status 로 비었음을 확인하고 pd start. FORCE=1 pd start 는 쓰지 마세요.

컨테이너 자체의 Docker HEALTHCHECK 는 pd status 를 부르지 않습니다(느리고 가끔 흔들려서). 대신 postgres · cassandra 가 실제 쿼리에 답하나와 포트 전부가 열려 있나를 봅니다. 그래서 «docker ps 는 healthy 인데 pd status 는 STOPPED» 는 기동 창이거나 한 번 빗나간 것이고, «unhealthy 인데 pd status 는 전부 RUNNING» 이면 포트는 열렸지만 쿼리에 답을 못 하는 상태입니다(pd logs storage).

진단

pd doctor # 여섯 절 검사. 마지막 줄 FAIL 0 이면 된다
pd env # 디렉터리 · 이미지 정체 (0.25초)
pd logs --list # 따라갈 파일 목록만
pd logs --lines 50 cep # cep 만, 마지막 50줄부터
pd storage # 볼륨 90% 이상이면 FAIL
pd retention # 왜 안 줄어드나 — TTL · 토픽 보존 · 콜드 티어
pd flow # 데이터가 안 들어온다 — 컨슈머 lag
pd downtime # 자꾸 죽는 것 같다 — 계획 밖 정지 기록

pd doctor 의 여섯 절: [1] inputs(시크릿 · 노드 파일 · 이미지) · [2] tools · [3] config templates(전부 렌더되나) · [4] runtime tree · [5] TLS material · [6] core ports. N/A 는 «여기서는 잴 수 없다» 이고 괄호에 이유가 붙습니다. 컨테이너 안에서 사이드카 파일이 없는 것은 정상입니다 — 값은 환경변수로 옵니다.

pd flowNA 는 «뒤처졌다» 가 아니라 «한 번도 읽은 적이 없다» 입니다. MEMB 열이 0 이면 소비자가 안 떠 있는 것, 0 보다 큰데 토픽이 비었으면 정상(읽을 게 없음), 0 보다 큰데 토픽에 데이터가 있으면 진짜 의심 신호입니다.

설정

pd config list # 이 모드의 템플릿 → 경로 표
pd config diff # 런타임 파일 vs 지금 렌더하면 나올 것 (0 같음 / 1 다름 / 3 시크릿 없음 / 4 렌더 실패)
pd config diff --templates # 호스트 템플릿 vs 이미지 기본값 (same / differs / local / missing)
pd config render # 실제로 쓴다 — 그 뒤 pd restart <서비스> 까지가 한 세트

값을 바꾸는 절차와 «어디를 고쳐야 하나» 는 설정 바꾸는 법에 있습니다. 컨테이너 안 생성물을 직접 고치지 마세요 — 다음 pd start 에 사라집니다.

Cassandra · PostgreSQL 노드 조작

pd node status # nodetool status — UN 이 정상, DN 이면 죽은 노드
pd node status --json # + PostgreSQL 복제 · Valkey 복제 · 워커 명부
pd node info # 노드 상세
pd node cql # cqlsh (cassandra 계정)
pd node psql # psql (postgres OS 사용자)
pd node errors # cassandra debug.log 의 최근 WARN/ERROR
pd node topic # kafka 토픽 "event" describe
pd node tpstats | compactionstats | proxyhistograms | table-stats [ks] | table-histograms <ks> <tbl> | sstable-size <ks> <tbl> | disk
변경하는 동사등급한 줄
pd node add변경살아 있는 노드 수에 맞춰 키스페이스 RF 를 올리고(최대 3) repair. 워커를 붙인 뒤 마스터에서 한 번
pd node repair · repair-table <ks> <tbl>변경(무겁다)노드 간 데이터 불일치를 맞춘다
pd node flush · drain변경메모리의 쓰기를 디스크로. drain 은 그 뒤 쓰기를 거부하므로 정지 직전에만
pd node compact [ks] [tbl]변경(무겁다)SSTable 병합
pd node cleanup파괴적스냅샷 전부 삭제 + 이 노드가 더 이상 소유하지 않는 데이터 삭제
pd node remove <host-id>파괴적죽은 노드를 링에서 뺀다. 살아 있는 노드에 쓰면 안 된다
pd node upgrade · init-cms · train-zstd · cache-clear변경설치 절차 · 버전업 · OS 페이지 캐시 비우기

백업 · 복원

pd backup # PostgreSQL 논리 덤프 → /data1/pp-data/postgres/dump/
pd backup list | schedule | status
pd backup run --engine postgres --type diff
pd backup restore --engine postgres --set <세트> --dry-run # 계획 먼저
pd recover [덤프파일] # pp DB 하나를 논리 덤프로 되돌림 (파괴적)

절차는 백업 · 복원에 있습니다.

종료 코드

코드
0성공. status 는 전부 RUNNING, doctor 는 FAIL 0, config diff 는 차이 없음
1일반 실패 · «다르다» · «문제 있다»
2사용법 오류 — 모르는 동사 · 서비스 · 옵션, --json 거부, PP_HOME 미명시
3필수 시크릿 누락 — 메시지에 이름 전부. backup run · restore 에서는 «다른 백업이 돌고 있다»
4렌더 실패 — 치환 안 된 ${PP_*}, 이름 전부 나열
5문지기 서비스(storage · analytics)가 안 떠서 기동 중단
6기동은 끝났는데 서비스 일부가 준비 안 됨
7정지를 증명하지 못함(STILL RUNNING)
8광고 주소가 루프백(127.0.0.1) — 렌더 거부

로그 형식과 저널

pd 가 찍는 모든 줄은 한 모양입니다 — [시각] [DATALAKE-CLI] [레벨] [동사] 메시지. INFO 는 stdout, 나머지는 stderr 로 갑니다.

pd start · stop · restart · backup 은 JSON 한 줄씩을 이벤트 저널 plantpulse-datalake-admin-api/logs/pd-events.jsonl 에 남기고, 콘솔이 그것을 이벤트 타임라인으로 보여 줍니다. 콘솔에서 실행한 명령은 actoroperator:<이름> 으로 남습니다.

옛 이름 대응표

plantpulse-startup 의 스크립트 모음은 2026-09-03 에 pd 로 합쳐졌고 옛 디렉터리는 이미지에 없습니다.

옛 스크립트지금
start-daemon.sh · start.shpd start
stop.shpd stop
restart.sh · restart-<모듈>.shpd restart [서비스]
restart-monitor.shpd restart admin-api
status.shpd status
kill.sh · clean.shpd kill · pd clean
configure.shpd config render
log-viewer.shpd logs
node-<동사>.sh · node-added.sh · node-error.shpd node <동사> · pd node add · pd node errors
secrets/rotate.shpd secret rotate (호스트의 passwd.sh 가 부른다)
env.sh · env-reset.sh · env-validate.sh없어졌습니다 — 값은 호스트의 사이드카 · 노드 파일과 compose 가 정합니다
prepare-ssl.shplantpulse-certs 컨테이너가 합니다 → 보안 설정
PP_OPTIONSPD_OPTIONS (2026-09-07). 옛 이름은 읽히지 않습니다
앱 재시작 스크립트를 컨테이너 안에서 찾지 마세요

서버 · 배치 · 웨어하우스 · OPC-UA · AASX 는 각자의 컨테이너에서 돕니다. 데이터레이크 컨테이너에는 그 모듈이 없습니다. 앱은 호스트에서 재시작하세요.

cd /opt/kopens/plantpulse-platform-docker/bin
./restart-server.sh # 또는 restart-batch.sh · restart-warehouse.sh · restart-one.sh <서비스>

관련 문서