plantpulse-workflow (Workflow)
Role
Orchestration of long-running jobs and data pipelines. Runs two engines together.
| Engine | Purpose |
|---|---|
| Temporal | Distributed workflow, long-running jobs (retry · compensation transaction). The admin console's own durable workflows also run here |
| Kestra | Declarative data pipelines · scheduling. The warehouse archiver submits jobs to it |
| Item | Value |
|---|---|
| Module name | plantpulse-workflow |
| Installation path | /opt/kopens/plantpulse-platform/plantpulse-workflow/ |
| Temporal | 7233 (gRPC) · 8233 (web UI, HTTP) |
| Kestra | 8380 (web UI + API, TLS-only) · 8391 (admin endpoint, internal) |
pd service | workflow — MASTER only. temporal → kestra |
Archive worker is not here (2026-09-06)
The Aster TSDB → Iceberg archiver was briefly a third component of this service but has been moved to the plantpulse-warehouse-web container of the platform image. This is because the data lake is infrastructure, and "which table is archived when and how" is business logic → warehouse module
Configuration
Directory Structure
plantpulse-workflow/
├── temporal/
│ ├── bin/
│ ├── config/workflow.yaml # 생성물 ← /etc/kopens/conf/workflow.yaml.template
│ └── logs/
└── kestra/
├── bin/
├── config/application.yaml # 생성물 ← /etc/kopens/conf/application.yaml.template
└── logs/
Temporal
| Item | Value |
|---|---|
| Port | 7233 (frontend gRPC) · 8233 (web UI) · 7243 (HTTP API) · 7234/7235/7239 (internal services) |
| Backend | PostgreSQL DB temporal · temporal_visibility, account temporal (PP_TEMPORAL_USER / PP_TEMPORAL_PASSWORD) |
| Advertise address | broadcastAddress = PP_TEMPORAL_HOST — if it's loopback, the renderer rejects it |
| Metrics | 8244 (127.0.0.1 only, read by the admin console) |
PP_TEMPORAL_PASSWORD is not a Temporal account in itself but a backend PostgreSQL account. passwd.sh changes it to ALTER ROLE.
The web UI http://<server-ip>:8233/ has no login. Keep it open only on the private network.
docker exec plantpulse-datalake bash -c 'cd /opt/kopens/plantpulse-platform/plantpulse-workflow/temporal && ./bin/temporal --address 127.0.0.1:7233 workflow list'
Kestra
| Item | Value |
|---|---|
| Port | 8380 — TLS-only, http:// does not respond. / redirects to /ui/ |
| Login | PP_KESTRA_ADMIN_EMAIL / PP_KESTRA_ADMIN_PASSWORD (basic-auth) |
| Backend | PostgreSQL DB kestra, account kestra (PP_KESTRA_DB_USER / PP_KESTRA_DB_PASSWORD) — different from the login account |
| Storage | /data1/pp-data/kestra/storage |
Neither password is a target for passwd.sh → Web console login account — Kestra, Non-rotated values
Example Flow
id: daily-report
namespace: plantpulse
description: 매일 새벽 2시에 보고서 스크립트 실행
triggers:
- id: every-2am
type: io.kestra.plugin.core.trigger.Schedule
cron: "0 2 * * *"
tasks:
- id: run
type: io.kestra.plugin.scripts.shell.Commands
commands:
- echo "report"
Operational Commands
docker exec plantpulse-datalake pd status workflow
docker exec plantpulse-datalake pd restart workflow # Temporal + Kestra
docker exec plantpulse-datalake pd logs --lines 100 workflow
Common Issues
| Symptom | Cause | Resolution |
|---|---|---|
| Temporal fails to start | PostgreSQL not ready · temporal role password mismatch | pd status storage, passwd.sh PP_TEMPORAL_PASSWORD |
| Kestra fails to start | kestra role password mismatch | PP_KESTRA_DB_PASSWORD of the sidecar — at boot, pd aligns with the role |
http://…:8380 won't open | TLS-only | https:// |
| Archive not working | Warehouse side | pd retention's cold_tier · archive_job, warehouse container logs |
Temporal broadcastAddress error · render exits with code 8 | Loopback address | Node file → How to change settings |