- "미해결 문제" → "최종 해결 (2025-07-15)" - Prometheus + Grafana 대체 사실 명시 - frontend-base/backend/metrics_database.py 참조 추가 - "후속 작업" 섹션 삭제 (완료됨) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
183 lines
8.5 KiB
Markdown
183 lines
8.5 KiB
Markdown
# 시스템 메트릭 구현 트러블슈팅
|
|
|
|
## 개요
|
|
- **날짜**: 2025-07-14
|
|
- **작업**: 관리자 대시보드에 시스템 메트릭 그래프 추가
|
|
- **목표**: PostgreSQL + TimescaleDB 기반 시계열 데이터 수집 및 Chart.js 그래프 표시
|
|
|
|
## 주요 문제들과 해결 과정
|
|
|
|
### 1. Docker 네트워크 통신 문제
|
|
**문제**: 관리자 대시보드에서 모든 서비스가 timeout/unreachable 상태
|
|
**원인**: Docker 컨테이너간 네트워크 격리 (DOCKER-ISOLATION iptables 체인)
|
|
**해결**:
|
|
- 서비스 URL을 IP 주소에서 컨테이너 이름으로 변경
|
|
- `http://172.17.0.2:5173` → `http://frontend:5173`
|
|
- `http://172.17.0.1:10508` → `http://rb10508_test:10508`
|
|
|
|
### 2. TimescaleDB 설치 및 설정
|
|
**문제**: PostgreSQL에 TimescaleDB 확장 설치 필요
|
|
**해결**:
|
|
```bash
|
|
# TimescaleDB 확장 설치
|
|
sudo apt-get update
|
|
sudo apt-get install timescaledb-2-postgresql-15
|
|
|
|
# 데이터베이스 생성 및 확장 활성화
|
|
sudo -u postgres createdb robeing_metrics
|
|
sudo -u postgres psql robeing_metrics -c "CREATE EXTENSION IF NOT EXISTS timescaledb;"
|
|
```
|
|
|
|
### 3. HDD 저장소 설정
|
|
**문제**: 메트릭 데이터를 HDD에 저장하기 위한 테이블스페이스 생성
|
|
**해결**:
|
|
```sql
|
|
-- HDD 테이블스페이스 생성
|
|
CREATE TABLESPACE hdd_tablespace LOCATION '/hdd/postgresql_data';
|
|
|
|
-- 테이블 생성시 HDD 테이블스페이스 사용
|
|
CREATE TABLE system_metrics (
|
|
time TIMESTAMPTZ NOT NULL,
|
|
metric_type VARCHAR(50) NOT NULL,
|
|
value DOUBLE PRECISION NOT NULL,
|
|
hostname VARCHAR(100) DEFAULT 'localhost'
|
|
) TABLESPACE hdd_tablespace;
|
|
```
|
|
|
|
### 4. PostgreSQL 연결 인증 문제
|
|
**문제**: Docker 컨테이너에서 PostgreSQL 접속 시 password authentication failed
|
|
**원인**: PostgreSQL 사용자 비밀번호 미설정
|
|
**해결**:
|
|
```bash
|
|
# PostgreSQL 비밀번호 설정
|
|
sudo -u postgres psql -c "ALTER USER postgres PASSWORD '19800508';"
|
|
|
|
# docker-compose.yml에 환경변수 추가
|
|
environment:
|
|
- METRICS_DB_PASSWORD=19800508
|
|
```
|
|
|
|
### 5. 테이블 구조 불일치 문제
|
|
**문제**:
|
|
- 로그: `column "timestamp" of relation "system_metrics" does not exist`
|
|
- 실제 테이블: `time` 컬럼 존재, `timestamp` 컬럼 없음
|
|
|
|
**원인**: 코드와 데이터베이스 스키마 불일치
|
|
**해결 과정**:
|
|
1. 기존 테이블 구조 확인:
|
|
```sql
|
|
\d system_metrics
|
|
-- time (timestamptz), metric_type (varchar), value (double precision)
|
|
```
|
|
2. 코드 수정하여 기존 테이블 구조에 맞춤:
|
|
```python
|
|
# 정규화된 구조로 데이터 삽입
|
|
INSERT INTO system_metrics (time, metric_type, value)
|
|
VALUES ($1, $2, $3)
|
|
```
|
|
|
|
### 6. 잘못된 대시보드 구현
|
|
**문제**: 고객용 React 앱에 시스템 메트릭을 구현함
|
|
**원인**: 두 개의 프론트엔드 구조 혼동
|
|
- 고객용: React SPA (`/client/`)
|
|
- 관리자용: 정적 HTML (`/backend/admin_static/`)
|
|
|
|
**해결**: 관리자 대시보드(정적 HTML)에 Chart.js 기반 그래프 구현
|
|
|
|
## 최종 구현 결과
|
|
|
|
### 파일 구조
|
|
```
|
|
backend/
|
|
├── admin_routes.py # 관리자 API 엔드포인트
|
|
├── admin_static/
|
|
│ └── index.html # 관리자 대시보드 (Chart.js 그래프)
|
|
├── metrics_collector.py # 시스템 메트릭 수집기
|
|
├── metrics_database.py # PostgreSQL 데이터베이스 연결
|
|
└── main.py # 메트릭 시스템 초기화
|
|
```
|
|
|
|
### 주요 기능
|
|
1. **메트릭 수집**: 1분 간격으로 CPU, 메모리, 디스크, 업타임 수집
|
|
2. **데이터 저장**: PostgreSQL TimescaleDB 하이퍼테이블에 시계열 데이터 저장
|
|
3. **그래프 표시**: Chart.js로 1h/1d/7d/30d/90d/1y 기간별 그래프
|
|
4. **실시간 표시**: 현재 메트릭 값과 진행률 바 표시
|
|
|
|
### API 엔드포인트
|
|
- `GET /admin/metrics/current` - 현재 메트릭 조회
|
|
- `GET /admin/metrics/history/{period}` - 기간별 메트릭 히스토리
|
|
- `POST /admin/metrics/collect` - 수동 메트릭 수집
|
|
|
|
## 최종 해결 (2025-07-15)
|
|
|
|
**상태**: 메트릭 수집 비활성화 (Prometheus + Grafana로 대체)
|
|
**관련 파일**: frontend-base/backend/metrics_database.py:58-60, 78-80, 148-150
|
|
**해결 방법**: system_metrics 테이블 사용 중단, TODO 주석 처리
|
|
**참고**: 아래 Prometheus + Grafana 방식으로 완전 전환
|
|
|
|
## 학습 포인트
|
|
1. **Docker 네트워크**: 컨테이너간 통신 시 서비스 이름 사용
|
|
2. **TimescaleDB**: PostgreSQL 확장으로 시계열 데이터 최적화
|
|
3. **두 프론트엔드 구조**: 고객용 React vs 관리자용 정적 HTML 구분
|
|
4. **데이터베이스 스키마**: 코드와 실제 테이블 구조 일치 중요성
|
|
5. **PostgreSQL 인증**: Docker 환경에서 비밀번호 설정 필요
|
|
|
|
## `node-exporter` + `Prometheus` + `Grafana` 를 이용한 compute 자원 모니터링
|
|
|
|
해당 문서는 직접 개발하는 방식이 아닌 기존에 널리 쓰이는</br>
|
|
`node-exporter` + `Prometheus` + `Grafana`를 이용하여</br>
|
|
cpu, memory disk 등을 수집하는 방식이다.</br>
|
|
</br>
|
|
먼저 docker 및 물리적 서버로 동작시에는 아래와 같은 구조로 이용된다.
|
|
|
|
```text
|
|
┌───────────────────────────────┐
|
|
│ PC #1 │
|
|
│ ┌────────────────────────┐ │
|
|
│ │ Container: node-exporter│ │
|
|
│ │ - CPU, MEM, Disk, Net │ │
|
|
│ │ - Prometheus metrics │ │
|
|
│ └───────────┬────────────┘ │
|
|
└──────────────┼───────────────┘
|
|
│ (HTTP /metrics)
|
|
│
|
|
┌───────────────────────────────┐
|
|
│ PC #2 │
|
|
│ ┌────────────────────────┐ │
|
|
│ │ Container: node-exporter│ │
|
|
│ │ - CPU, MEM, Disk, Net │ │
|
|
│ │ - Prometheus metrics │ │
|
|
│ └───────────┬────────────┘ │
|
|
└──────────────┼───────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────┐
|
|
│ 중앙 서버 (또는 PC #1) │
|
|
│ ┌─────────────┐ │
|
|
│ │ Prometheus │<── scrape ──────────────┘
|
|
│ │ (metrics DB)│ /metrics from each node
|
|
│ └───────┬─────┘
|
|
│ │
|
|
│ ┌─────▼─────┐
|
|
│ │ Grafana │ (Dashboards)
|
|
│ │ - Prometheus 연결
|
|
│ │ - CPU/MEM/DISK/NET 시각화
|
|
│ └───────────┘
|
|
└─────────────────────────────────────────┘
|
|
```
|
|
|
|
해당 구조는 PC가 2대일 때를 가정했으며 중앙서버를 별도의 PC로 정의할 경우에는 PC가 3대인 모습이다.</br>
|
|
해당 PC 는 K8s의 구조로 변경될 시에는 별도의 worker node로 대체해서 생각하면 된다.
|
|
|
|
여기에서 각각의 역할은 아래와 같다.
|
|
|
|
- node-exporter : 각 PC의 cpu, memory 등을 수집한다. docker인 경우 각각의 컨테이너의 로그도 수집한다.
|
|
- Prometheus: 각 node-exporter 에서 수집된 로그를 저장하며 PQL이라는 쿼리를 통해 로그를 조건에 맞게 추출할 수 있다.
|
|
- Grafana: Prometheus에서 저장된 로그를 단지 시각화 하는 방식이다.
|
|
|
|
설치방법은 아래의 `ref`에 남겨놓았다.
|
|
|
|
ref
|
|
- https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus: 기본적인 문서
|
|
- https://medium.com/%40shyamsandeep28/installation-of-prometheus-grafana-with-node-exporter-8ce3c97d968c: 좀더 세부적인 설정이 가미된 문서
|
|
- 그 이외에는 편의에 맞게 블로그에서 참고하여 형식에 맞게 수정하면 된다. |