4c1dc4082e
Build and Push Images / build-and-push (push) Has been cancelled
이전 세션들에서 작업된 아래 범위를 모두 포함: Fleet 서브시스템 (src/fleet/) - fleetDeviceService / fleetCommandService / fleetDeploymentService / fleetReleaseService - fleetMetricsService, fleetScriptService, fleetEdgeConfigService - Edge 디바이스 관리, 커맨드 발행, 배포/릴리스, 스크립트 동기화 Collector 확장 - centralMqttForwarder / centralForwarderConfigService - equipmentStateService, pythonHookRunner, scriptCache - Modbus/OPC-UA/S7/XGT 프로토콜 클라이언트 - targetDbIntrospection (저장 DB 조회) Routes / API - automationDashboardRoutes, centralForwarderRoutes, equipmentStateRoutes DB - importEdgeConfig (Python cached config → Pipeline DB) - seedDataSources (external_db_connections 초기 시드) 엣지 배포 리소스 - docker/edge/Dockerfile.backend.prod, Dockerfile.frontend.prod - docker/edge/docker-compose.edge.yml 프론트엔드 - admin/automaticMng (centralForwarder, dashboard, equipmentState) - admin/fleet (commands, devices, deployments, releases, scripts, alerts) - admin/pipeline-device 개선 (저장 DB 드롭다운, 태그 매핑 등) - ExternalDbConnectionModal, ScriptsManagerDialog 등 신규 컴포넌트 - lib/api: automationDashboard, centralForwarder, equipmentState, fleet docs/ - EDGE_SERVER_STRUCTURE, FLEET_COMPLETE, FLEET_EDGE_INTEGRATION, FLEET_HOOK_INTEGRATION Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
182 lines
6.1 KiB
Markdown
182 lines
6.1 KiB
Markdown
# Pipeline Edge Deployment
|
|
|
|
스피폭스 등 고객사 엣지 서버에 Pipeline을 올려 기존 Python data-collector + Kafka + forwarder를 **완전 대체**합니다.
|
|
|
|
## 기존 vs 신규 구조
|
|
|
|
```
|
|
[기존]
|
|
PLC → Python data-collector → 로컬 Kafka → kafka-to-central-mqtt → IDC EMQX → TimescaleDB
|
|
|
|
[신규 — Pipeline 단일 서비스]
|
|
PLC → Pipeline (XGT/Modbus/OPC UA/S7 직접 수집 + Python 훅 실행) → IDC EMQX → TimescaleDB
|
|
```
|
|
|
|
Pipeline이 다음 역할을 모두 수행:
|
|
- 장비 폴링 (XGT/Modbus/OPC UA/S7)
|
|
- Python 훅 실행 (transform/filter/derived_tags, `python3` 서브프로세스)
|
|
- 로컬 현재값 스냅샷 (`equipment_current_state`)
|
|
- IDC MQTT 포워딩 (`dt/v1/data/{company_id}/{edge_id}`)
|
|
- 재시도 큐 (`central_mqtt_forwarder_retry_queue`)
|
|
- 모든 것을 UI에서 관리
|
|
|
|
## 1. 이미지 빌드 & 푸시 (최초 1회, 로컬에서)
|
|
|
|
```bash
|
|
cd /Users/chpark/workspace/vexplor_Pipeline
|
|
|
|
# 백엔드 프로덕션 이미지
|
|
docker build \
|
|
-f docker/edge/Dockerfile.backend.prod \
|
|
-t harbor.wace.me/vexplor_fleet/pipeline-backend:latest \
|
|
./backend-node
|
|
|
|
docker push harbor.wace.me/vexplor_fleet/pipeline-backend:latest
|
|
|
|
# (선택) 프론트엔드 이미지 — 엣지에서 UI 직접 띄우려면
|
|
docker build \
|
|
-f docker/dev/frontend.Dockerfile \
|
|
-t harbor.wace.me/vexplor_fleet/pipeline-front:latest \
|
|
./frontend
|
|
|
|
docker push harbor.wace.me/vexplor_fleet/pipeline-front:latest
|
|
```
|
|
|
|
## 2. 엣지 서버 준비 (스피폭스 `112.168.212.142`)
|
|
|
|
> ⚠️ **병행 운영 모드**
|
|
> 기존 Python data-collector / fleet-agent / kafka-to-central-mqtt는 **절대 중지하지 않고** 그대로 둡니다.
|
|
> Pipeline은 옆에서 별도로 기동해 "연결/수집/포워딩이 잘 되는지"만 검증합니다.
|
|
> 안정성 확인 후 사용자가 판단해서 기존 컨테이너 중지 여부 결정.
|
|
|
|
```bash
|
|
ssh wace@112.168.212.142
|
|
|
|
# Harbor 로그인
|
|
docker login harbor.wace.me
|
|
|
|
# Pipeline 전용 디렉토리 (기존 data-collector와 분리)
|
|
mkdir -p /home/wace/pipeline-edge
|
|
cd /home/wace/pipeline-edge
|
|
```
|
|
|
|
### 포트 충돌 확인 (기존 컨테이너와 겹치지 않는지)
|
|
|
|
```bash
|
|
# 기존 스피폭스 엣지의 포트 사용 현황 확인
|
|
docker ps --format 'table {{.Names}}\t{{.Ports}}' | grep -E '8080|1883|8083|9771'
|
|
```
|
|
|
|
만약 겹치면 Pipeline 쪽 포트를 바꿔 기동 (compose에서 `ports:` 좌측 값만 수정).
|
|
|
|
## 3. compose + env 배치
|
|
|
|
`docker-compose.edge.yml`와 `.env.example`를 엣지에 업로드 후 `.env.example`를 `.env`로 복사하고 값 설정:
|
|
|
|
```bash
|
|
# 로컬 → 엣지로 scp
|
|
scp docker/edge/docker-compose.edge.yml wace@112.168.212.142:/home/wace/pipeline-edge/
|
|
scp docker/edge/.env.example wace@112.168.212.142:/home/wace/pipeline-edge/.env
|
|
|
|
# 엣지에서 .env 편집
|
|
ssh wace@112.168.212.142
|
|
cd /home/wace/pipeline-edge
|
|
vi .env # DATABASE_URL, JWT_SECRET, PASSWORD_ENCRYPTION_KEY, EDGE_ID 등 입력
|
|
```
|
|
|
|
## 4. 기동
|
|
|
|
```bash
|
|
docker compose -f docker-compose.edge.yml up -d
|
|
|
|
# 프론트 UI도 같이 띄우려면:
|
|
docker compose -f docker-compose.edge.yml --profile with-ui up -d
|
|
|
|
# Watchtower 자동 업데이트까지:
|
|
docker compose -f docker-compose.edge.yml --profile watchtower up -d
|
|
```
|
|
|
|
## 5. 검증
|
|
|
|
```bash
|
|
# 헬스체크
|
|
curl http://localhost:8080/health
|
|
|
|
# 부팅 로그 확인
|
|
docker logs pipeline-backend --tail 100 | grep -iE 'collector|forwarder|script'
|
|
|
|
# 기대 출력:
|
|
# ✅ 중앙 MQTT 포워더 + 장비 현재값 테이블 생성 완료
|
|
# ✅ 프로토콜 CHECK 제약 확장 완료
|
|
# 🔌 장비 수집기 자동 시작: N개 연결
|
|
# [CentralForwarder] 연결됨: mqtt://211.115.91.170:31883
|
|
```
|
|
|
|
- 이후 웹에서 `http://<엣지IP>:9771`로 UI 접근 (또는 중앙 Pipeline UI에서 같은 DB 공유 시 공통 사용).
|
|
- **장비 통신** 페이지에서 PLC 연결 활성화 / 비활성화 가능
|
|
- **Python 훅** `/admin/fleet/scripts`에서 편집 → 연결에 체크박스로 붙임 → 다음 폴링부터 자동 반영
|
|
|
|
## 6. 롤백 / 정리
|
|
|
|
기존 Python data-collector는 그대로 돌고 있으므로 **Pipeline만 내리면** 원상 복구됩니다.
|
|
|
|
```bash
|
|
# Pipeline만 중지 (기존 data-collector는 영향 없음)
|
|
cd /home/wace/pipeline-edge
|
|
docker compose -f docker-compose.edge.yml down
|
|
```
|
|
|
|
## 병행 운영 중 주의사항 — **중복 IDC 전송 방지**
|
|
|
|
기존 `kafka-to-central-mqtt` forwarder가 돌고 있는 상태에서 Pipeline 포워더까지 켜면 **같은 데이터가 IDC에 두 번 들어갑니다** (동일 `edge_id`/`company_id` + 동일 토픽).
|
|
|
|
### 해결책 (택 1)
|
|
|
|
**A. Pipeline 포워더는 켜지 말기 (추천 — 연결 검증만 먼저)**
|
|
- `/admin/automaticMng/centralForwarder` 에서 포워더 설정 **비활성**(`is_enabled='N'`) 유지
|
|
- Pipeline은 수집/UI 테스트만, IDC 전송은 기존 forwarder가 계속 담당
|
|
|
|
**B. 테스트용 edge_id 사용**
|
|
- `.env`에 `EDGE_ID=spifox-pipeline-test` 같은 식별자
|
|
- IDC TimescaleDB에서 이 edge_id만 별도로 보면서 수집값 검증
|
|
- 검증 끝나면 실 edge_id로 변경 + 기존 forwarder 중지
|
|
|
|
**C. 기존 포워더 중지 (완전 대체 시점)**
|
|
```bash
|
|
docker stop kafka-to-central-mqtt
|
|
# 이제 Pipeline 포워더 활성화
|
|
```
|
|
|
|
## 주요 환경변수
|
|
|
|
| 변수 | 설명 | 필수 |
|
|
|---|---|---|
|
|
| `DATABASE_URL` | PostgreSQL 접속 URL | ✅ |
|
|
| `JWT_SECRET` | JWT 서명 키 (32+ 글자) | ✅ |
|
|
| `PASSWORD_ENCRYPTION_KEY` | AES-256 키 (32바이트 hex) | ✅ |
|
|
| `ENABLE_AUTO_COLLECTOR` | 부팅 시 모든 활성 연결 자동 폴링 (엣지=true) | 엣지용 |
|
|
| `COMPANY_CODE` | 고객사 식별 (예: spifox) | ✅ |
|
|
| `EDGE_ID` | 엣지 UUID | ✅ |
|
|
|
|
## 트러블슈팅
|
|
|
|
### Python 훅 실행 에러
|
|
```bash
|
|
docker exec pipeline-backend python3 --version # 3.11+이어야 함
|
|
```
|
|
|
|
### IDC MQTT 미연결
|
|
```bash
|
|
docker exec pipeline-backend node -e '
|
|
const mqtt=require("mqtt");
|
|
const c=mqtt.connect("mqtt://211.115.91.170:31883",{username:"ingestion",password:"ingestion_secret_prod"});
|
|
c.on("connect",()=>{console.log("OK"); c.end();});
|
|
c.on("error",e=>console.log("ERR",e.message));
|
|
'
|
|
```
|
|
|
|
### PLC 미연결
|
|
```bash
|
|
docker exec pipeline-backend sh -c 'timeout 3 bash -c "cat < /dev/tcp/192.168.101.50/2004" && echo OK || echo FAIL'
|
|
```
|