# Fleet Management 시스템 구축 계획서 ## 개요 **목표:** 10,000개 이상의 온프레미스 공장 서버를 중앙에서 효율적으로 관리 **현재 상태:** 1개 업체 (스피폭스), Watchtower 기반 자동 업데이트 **목표 상태:** 10,000개 업체, 실시간 모니터링 & 원격 제어 가능 --- ## 목차 1. [아키텍처 설계](#1-아키텍처-설계) 2. [Phase별 구현 계획](#2-phase별-구현-계획) 3. [핵심 컴포넌트 상세](#3-핵심-컴포넌트-상세) 4. [데이터베이스 스키마](#4-데이터베이스-스키마) 5. [API 설계](#5-api-설계) 6. [기술 스택](#6-기술-스택) 7. [일정 및 마일스톤](#7-일정-및-마일스톤) 8. [리스크 및 대응](#8-리스크-및-대응) --- ## 1. 아키텍처 설계 ### 1.1 전체 아키텍처 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ Vexplor 글로벌 플랫폼 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Web UI │ │ Fleet API │ │ Config │ │ Monitoring │ │ │ │ (Dashboard) │ │ Gateway │ │ Server │ │ & Alerts │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ │ │ └────────────────┼────────────────┼────────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Message │ │ Device │ │ │ │ Broker │ │ Registry │ │ │ │ (MQTT) │ │ (Redis) │ │ │ └──────┬──────┘ └─────────────┘ │ │ │ │ └──────────────────────────┼────────────────────────────────────────────┘ │ │ MQTT (TLS) │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Agent │ │ Agent │ │ Agent │ │ 스피폭스 │ │ 엔키드 │ │ 고객 N │ └─────────┘ └─────────┘ └─────────┘ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Vexplor │ │ Vexplor │ │ Vexplor │ │ Backend │ │ Backend │ │ Backend │ │Frontend │ │Frontend │ │Frontend │ │ DB │ │ DB │ │ DB │ └─────────┘ └─────────┘ └─────────┘ ``` ### 1.2 통신 흐름 ``` [공장 서버 → 글로벌] 1. Agent 시작 시 MQTT 연결 (Outbound Only) 2. 주기적 Heartbeat 전송 (30초) 3. 상태/메트릭 보고 (5분) 4. 로그 전송 (선택적) [글로벌 → 공장 서버] 1. 업데이트 명령 2. 설정 변경 3. 재시작 명령 4. 데이터 요청 ``` --- ## 2. Phase별 구현 계획 ### Phase 1: 기반 구축 (1~10개 업체) **기간:** 2주 | 구현 항목 | 설명 | 우선순위 | | :--- | :--- | :--- | | Device Registry API | 디바이스 등록/조회 | P0 | | Heartbeat API | 상태 보고 수신 | P0 | | 기본 대시보드 | 디바이스 목록/상태 표시 | P1 | | Agent 기본 버전 | Heartbeat 전송 기능 | P0 | **산출물:** - `POST /api/fleet/devices/register` - `POST /api/fleet/devices/heartbeat` - `GET /api/fleet/devices` - Agent Docker 이미지 --- ### Phase 2: 실시간 통신 (10~100개 업체) **기간:** 4주 | 구현 항목 | 설명 | 우선순위 | | :--- | :--- | :--- | | MQTT 브로커 설치 | Eclipse Mosquitto | P0 | | Agent MQTT 연결 | 상시 연결 유지 | P0 | | 원격 명령 기능 | 업데이트/재시작 명령 | P1 | | 실시간 상태 업데이트 | WebSocket → 대시보드 | P1 | **산출물:** - MQTT 브로커 (Docker) - Agent v2 (MQTT 지원) - 원격 명령 UI --- ### Phase 3: 배포 관리 (100~500개 업체) **기간:** 6주 | 구현 항목 | 설명 | 우선순위 | | :--- | :--- | :--- | | 버전 관리 시스템 | 릴리즈 버전 관리 | P0 | | 단계적 롤아웃 | Canary 배포 | P0 | | 롤백 기능 | 이전 버전 복구 | P0 | | 그룹 관리 | 지역/업종별 그룹핑 | P1 | | 배포 스케줄링 | 시간대별 배포 | P2 | **산출물:** - Release Management UI - Deployment Pipeline - Rollback 자동화 --- ### Phase 4: 모니터링 강화 (500~2,000개 업체) **기간:** 6주 | 구현 항목 | 설명 | 우선순위 | | :--- | :--- | :--- | | 메트릭 수집 | CPU/Memory/Disk | P0 | | 알림 시스템 | Slack/Email/SMS | P0 | | 로그 중앙화 | 원격 로그 수집 | P1 | | 이상 탐지 | 자동 장애 감지 | P1 | | SLA 대시보드 | 가용성 리포트 | P2 | **산출물:** - Prometheus + Grafana - Alert Manager - Log Aggregator (Loki) --- ### Phase 5: 대규모 확장 (2,000~10,000개 업체) **기간:** 8주 | 구현 항목 | 설명 | 우선순위 | | :--- | :--- | :--- | | MQTT 클러스터링 | 고가용성 브로커 | P0 | | 샤딩 | 지역별 분산 | P0 | | 자동 프로비저닝 | 신규 업체 자동 설정 | P1 | | API Rate Limiting | 과부하 방지 | P1 | | 멀티 리전 | 글로벌 분산 | P2 | **산출물:** - MQTT Cluster (EMQX) - Regional Gateway - Auto-provisioning System --- ## 3. 핵심 컴포넌트 상세 ### 3.1 Fleet Agent (공장 서버에 설치) ``` ┌─────────────────────────────────────────┐ │ Fleet Agent │ ├─────────────────────────────────────────┤ │ ┌─────────────┐ ┌─────────────┐ │ │ │ MQTT │ │ Command │ │ │ │ Client │ │ Executor │ │ │ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────────────────────┐ │ │ │ Core Controller │ │ │ └─────────────────────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Metrics │ │ Docker │ │ │ │ Collector │ │ Manager │ │ │ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────┘ ``` **주요 기능:** - MQTT 연결 유지 (자동 재연결) - Heartbeat 전송 (30초) - 시스템 메트릭 수집 - Docker 컨테이너 관리 - 원격 명령 실행 ### 3.2 Fleet Manager (글로벌 서버) **주요 기능:** - 디바이스 등록/인증 - 상태 모니터링 - 배포 오케스트레이션 - 설정 관리 - 알림 발송 ### 3.3 Message Broker (MQTT) **선택지:** | 옵션 | 장점 | 단점 | 추천 규모 | | :--- | :--- | :--- | :--- | | Mosquitto | 가볍고 간단 | 클러스터링 어려움 | ~1,000 | | EMQX | 클러스터링, 고성능 | 복잡함 | 1,000~100,000 | | HiveMQ | 엔터프라이즈급 | 비용 | 100,000+ | **권장:** Phase 1~3은 Mosquitto, Phase 4~5는 EMQX --- ## 4. 데이터베이스 스키마 ### 4.1 디바이스 테이블 ```sql -- 디바이스 (공장 서버) 정보 CREATE TABLE fleet_devices ( id SERIAL PRIMARY KEY, device_id VARCHAR(50) UNIQUE NOT NULL, -- 고유 식별자 company_code VARCHAR(20) NOT NULL, -- 회사 코드 device_name VARCHAR(100), -- 표시 이름 -- 연결 정보 ip_address VARCHAR(45), last_seen_at TIMESTAMPTZ, is_online BOOLEAN DEFAULT false, -- 버전 정보 agent_version VARCHAR(20), app_version VARCHAR(20), -- 시스템 정보 os_info JSONB, hardware_info JSONB, -- 그룹/태그 device_group VARCHAR(50), tags JSONB DEFAULT '[]', -- 메타 created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), FOREIGN KEY (company_code) REFERENCES company_info(company_code) ); CREATE INDEX idx_fleet_devices_company ON fleet_devices(company_code); CREATE INDEX idx_fleet_devices_online ON fleet_devices(is_online); CREATE INDEX idx_fleet_devices_group ON fleet_devices(device_group); ``` ### 4.2 Heartbeat 로그 테이블 ```sql -- Heartbeat 기록 (TimescaleDB 권장) CREATE TABLE fleet_heartbeats ( id BIGSERIAL, device_id VARCHAR(50) NOT NULL, received_at TIMESTAMPTZ DEFAULT NOW(), -- 상태 status VARCHAR(20), -- OK, WARNING, ERROR uptime_seconds BIGINT, -- 메트릭 cpu_percent DECIMAL(5,2), memory_percent DECIMAL(5,2), disk_percent DECIMAL(5,2), -- 컨테이너 상태 containers JSONB, PRIMARY KEY (device_id, received_at) ); -- TimescaleDB 하이퍼테이블 변환 (선택) -- SELECT create_hypertable('fleet_heartbeats', 'received_at'); ``` ### 4.3 배포 테이블 ```sql -- 릴리즈 버전 관리 CREATE TABLE fleet_releases ( id SERIAL PRIMARY KEY, version VARCHAR(20) NOT NULL, release_type VARCHAR(20), -- stable, beta, hotfix -- 이미지 정보 backend_image VARCHAR(200), frontend_image VARCHAR(200), agent_image VARCHAR(200), -- 변경사항 changelog TEXT, -- 상태 status VARCHAR(20) DEFAULT 'draft', -- draft, testing, released, deprecated released_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW() ); -- 배포 작업 CREATE TABLE fleet_deployments ( id SERIAL PRIMARY KEY, release_id INTEGER REFERENCES fleet_releases(id), -- 배포 대상 target_type VARCHAR(20), -- all, group, specific target_value VARCHAR(100), -- 그룹명 또는 device_id -- 롤아웃 설정 rollout_strategy VARCHAR(20), -- immediate, canary, scheduled rollout_percentage INTEGER, scheduled_at TIMESTAMPTZ, -- 상태 status VARCHAR(20) DEFAULT 'pending', started_at TIMESTAMPTZ, completed_at TIMESTAMPTZ, -- 결과 total_devices INTEGER, success_count INTEGER DEFAULT 0, failed_count INTEGER DEFAULT 0, created_at TIMESTAMPTZ DEFAULT NOW() ); -- 개별 디바이스 배포 상태 CREATE TABLE fleet_deployment_status ( id SERIAL PRIMARY KEY, deployment_id INTEGER REFERENCES fleet_deployments(id), device_id VARCHAR(50), status VARCHAR(20) DEFAULT 'pending', -- pending, downloading, installing, completed, failed started_at TIMESTAMPTZ, completed_at TIMESTAMPTZ, error_message TEXT, UNIQUE(deployment_id, device_id) ); ``` ### 4.4 알림 규칙 테이블 ```sql -- 알림 규칙 CREATE TABLE fleet_alert_rules ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, -- 조건 condition_type VARCHAR(50), -- offline, version_mismatch, high_cpu, etc. condition_value JSONB, threshold_minutes INTEGER, -- 조건 지속 시간 -- 알림 채널 notify_channels JSONB, -- ["slack", "email"] notify_targets JSONB, -- 수신자 목록 -- 상태 is_enabled BOOLEAN DEFAULT true, created_at TIMESTAMPTZ DEFAULT NOW() ); -- 알림 기록 CREATE TABLE fleet_alerts ( id SERIAL PRIMARY KEY, rule_id INTEGER REFERENCES fleet_alert_rules(id), device_id VARCHAR(50), alert_type VARCHAR(50), message TEXT, severity VARCHAR(20), -- info, warning, critical -- 해결 상태 status VARCHAR(20) DEFAULT 'open', -- open, acknowledged, resolved resolved_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW() ); ``` --- ## 5. API 설계 ### 5.1 Device Management API ```yaml # 디바이스 등록 POST /api/fleet/devices/register Request: device_id: string (required) company_code: string (required) device_name: string agent_version: string os_info: object Response: success: boolean data: device_id: string mqtt_credentials: broker_url: string username: string password: string # 디바이스 목록 조회 GET /api/fleet/devices Query: company_code: string is_online: boolean device_group: string page: number limit: number Response: success: boolean data: Device[] pagination: { total, page, limit } # 디바이스 상세 조회 GET /api/fleet/devices/:deviceId Response: success: boolean data: device: Device recent_heartbeats: Heartbeat[] recent_alerts: Alert[] ``` ### 5.2 Heartbeat API ```yaml # Heartbeat 전송 POST /api/fleet/devices/:deviceId/heartbeat Request: status: string uptime_seconds: number metrics: cpu_percent: number memory_percent: number disk_percent: number containers: - name: string status: string version: string Response: success: boolean data: commands: Command[] # 대기 중인 명령 반환 ``` ### 5.3 Deployment API ```yaml # 배포 생성 POST /api/fleet/deployments Request: release_id: number target_type: "all" | "group" | "specific" target_value: string rollout_strategy: "immediate" | "canary" | "scheduled" rollout_percentage: number scheduled_at: datetime Response: success: boolean data: deployment_id: number estimated_devices: number # 배포 상태 조회 GET /api/fleet/deployments/:deploymentId Response: success: boolean data: deployment: Deployment status_summary: pending: number in_progress: number completed: number failed: number device_statuses: DeploymentStatus[] # 배포 롤백 POST /api/fleet/deployments/:deploymentId/rollback Response: success: boolean data: rollback_deployment_id: number ``` ### 5.4 Command API ```yaml # 원격 명령 전송 POST /api/fleet/devices/:deviceId/commands Request: command_type: "update" | "restart" | "config" | "logs" payload: object Response: success: boolean data: command_id: string status: "queued" # 명령 결과 조회 GET /api/fleet/commands/:commandId Response: success: boolean data: command_id: string status: "queued" | "sent" | "executing" | "completed" | "failed" result: object ``` --- ## 6. 기술 스택 ### 6.1 글로벌 플랫폼 | 컴포넌트 | 기술 | 비고 | | :--- | :--- | :--- | | Fleet API | Node.js (기존 backend-node 확장) | 기존 코드 재사용 | | Message Broker | Mosquitto → EMQX | 단계적 전환 | | Device Registry | Redis | 빠른 조회 | | Database | PostgreSQL | 기존 DB 확장 | | Time-series DB | TimescaleDB | Heartbeat 저장 | | Monitoring | Prometheus + Grafana | 메트릭 시각화 | | Log | Loki | 로그 중앙화 | | Alert | AlertManager | 알림 관리 | ### 6.2 Fleet Agent | 컴포넌트 | 기술 | 비고 | | :--- | :--- | :--- | | Runtime | Go 또는 Node.js | 가볍고 안정적 | | MQTT Client | Paho MQTT | 표준 라이브러리 | | Docker SDK | Docker API | 컨테이너 관리 | | Metrics | gopsutil | 시스템 메트릭 | ### 6.3 대시보드 | 컴포넌트 | 기술 | 비고 | | :--- | :--- | :--- | | UI Framework | Next.js (기존) | 기존 코드 확장 | | Real-time | Socket.io | 실시간 상태 | | Charts | Recharts | 메트릭 시각화 | | Map | Leaflet | 지역별 표시 | --- ## 7. 일정 및 마일스톤 ### 7.1 전체 일정 ``` 2025 Q1 2025 Q2 2025 Q3 │ │ │ ├── Phase 1 (2주) ─────────┤ │ │ Device Registry │ │ │ Heartbeat API │ │ │ 기본 대시보드 │ │ │ │ │ │ ├── Phase 2 (4주) ──────────┤ │ │ │ MQTT 브로커 │ │ │ │ Agent v2 │ │ │ │ 원격 명령 │ │ │ │ │ │ │ │ ├── Phase 3 (6주) ──────┤ │ │ │ 버전 관리 │ │ │ │ Canary 배포 │ │ │ │ 롤백 │ │ │ │ │ ``` ### 7.2 상세 마일스톤 | 마일스톤 | 목표 | 완료 기준 | 예상 일정 | | :--- | :--- | :--- | :--- | | M1 | Device Registry | 디바이스 등록/조회 API 완료 | 1주차 | | M2 | Heartbeat | 상태 보고 & 저장 완료 | 2주차 | | M3 | Basic Dashboard | 디바이스 목록 UI 완료 | 2주차 | | M4 | MQTT Setup | 브로커 설치 & 연결 테스트 | 4주차 | | M5 | Agent v2 | MQTT 기반 Agent 완료 | 6주차 | | M6 | Remote Command | 업데이트/재시작 명령 완료 | 8주차 | | M7 | Release Mgmt | 버전 관리 UI 완료 | 10주차 | | M8 | Canary Deploy | 단계적 배포 완료 | 14주차 | --- ## 8. 리스크 및 대응 ### 8.1 기술적 리스크 | 리스크 | 영향 | 확률 | 대응 | | :--- | :--- | :--- | :--- | | MQTT 연결 불안정 | 높음 | 중간 | 자동 재연결, 오프라인 큐 | | 대량 동시 접속 | 높음 | 높음 | 클러스터링, 로드밸런싱 | | 보안 취약점 | 높음 | 낮음 | TLS 필수, 인증 강화 | | 네트워크 단절 | 중간 | 높음 | 로컬 캐시, 재전송 로직 | ### 8.2 운영 리스크 | 리스크 | 영향 | 확률 | 대응 | | :--- | :--- | :--- | :--- | | 잘못된 배포 | 높음 | 중간 | Canary 배포, 자동 롤백 | | 모니터링 누락 | 중간 | 중간 | 다중 알림 채널 | | 버전 파편화 | 중간 | 높음 | 강제 업데이트 정책 | --- ## 9. 다음 단계 ### 즉시 시작할 작업 (Phase 1) 1. **Device Registry 테이블 생성** - `fleet_devices` 테이블 마이그레이션 2. **Fleet API 엔드포인트 개발** - `POST /api/fleet/devices/register` - `POST /api/fleet/devices/:deviceId/heartbeat` - `GET /api/fleet/devices` 3. **Agent 기본 버전 개발** - Docker 이미지로 배포 - 주기적 Heartbeat 전송 4. **대시보드 기본 화면** - 디바이스 목록 - 온라인/오프라인 상태 표시 --- ## 부록 ### A. MQTT 토픽 설계 ``` vexplor/ ├── devices/ │ ├── {device_id}/ │ │ ├── status # 상태 보고 (Agent → Server) │ │ ├── metrics # 메트릭 보고 (Agent → Server) │ │ ├── commands # 명령 수신 (Server → Agent) │ │ └── responses # 명령 응답 (Agent → Server) │ │ ├── broadcasts/ │ ├── all # 전체 공지 │ └── groups/{group} # 그룹별 공지 │ └── system/ ├── announcements # 시스템 공지 └── maintenance # 점검 알림 ``` ### B. Agent 설정 파일 ```yaml # /opt/vexplor/agent/config.yaml device: id: "SPIFOX-001" company_code: "SPIFOX" name: "스피폭스 메인 서버" mqtt: broker: "mqtts://mqtt.vexplor.com:8883" username: "${MQTT_USERNAME}" password: "${MQTT_PASSWORD}" keepalive: 60 reconnect_interval: 5 heartbeat: interval: 30 # seconds metrics: enabled: true interval: 300 # 5 minutes collect: - cpu - memory - disk - network docker: socket: "/var/run/docker.sock" managed_containers: - vexplor-backend - vexplor-frontend - vexplor-db ``` ### C. 참고 자료 - [EMQX Documentation](https://docs.emqx.com/) - [Eclipse Mosquitto](https://mosquitto.org/) - [AWS IoT Device Management](https://aws.amazon.com/iot-device-management/) - [Google Cloud IoT Core](https://cloud.google.com/iot-core) - [HashiCorp Nomad](https://www.nomadproject.io/)