Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .gitea/workflows | ||
| charts/infra-report | ||
| src | ||
| .dockerignore | ||
| .gitignore | ||
| Dockerfile | ||
| README.md | ||
| next-env.d.ts | ||
| next.config.js | ||
| package-lock.json | ||
| package.json | ||
| plan.md | ||
| postcss.config.mjs | ||
| record.md | ||
| research.md | ||
| tailwind.config.ts | ||
| tsconfig.json | ||
README.md
Infra Report
Kubernetes 클러스터 인프라 모니터링 주간 리포트 시스템. Prometheus와 Kubernetes API에서 메트릭을 수집하여 웹 대시보드로 시각화합니다.
기능
- CPU / Memory / Disk / NAS 사용률 시계열 차트 및 통계 (avg, max, min)
- Ingress / Istio Network Traffic RX/TX 분리 차트 및 통계
- 노드별 상세 테이블 (CPU, Memory, Disk avg/max/min, 노드 스펙)
- NAS / Ingress / Istio 상세 테이블 (mountpoint별, RX/TX별 avg/max/min)
- 주의 구간 자동 감지 (임계값 기반 + Z-score peak 감지)
- 기간 선택 (시작일/종료일 직접 설정 + 프리셋 버튼)
- 차트 인터랙션 (hover 시 전체 데이터 tooltip, 클릭 시 solo 모드)
- Alert 클릭 → 차트 확대 (주의 구간 항목 클릭 시 해당 시간대로 zoom)
- Alert 유형 구분 (PEAK 보라색 / WARNING 주황색 / CRITICAL 빨간색 태그)
- PDF 내보내기
기술 스택
| 구분 | 기술 |
|---|---|
| Frontend | Next.js 14 (App Router), React 18, TypeScript |
| 스타일링 | Tailwind CSS 3 |
| 차트 | Apache ECharts 6 (echarts-for-react) |
| 상태관리 | TanStack React Query 5 |
| 데이터 소스 | Prometheus HTTP API, Kubernetes API |
| PDF 생성 | html2canvas + jsPDF |
| 컨테이너 | Docker (multi-stage build, standalone output) |
| 패키지 관리 | Helm Chart (OCI) |
| CI/CD | Gitea Actions → Harbor (Docker + Helm OCI) |
| 배포 | ArgoCD (자동 sync, semver range >0.0.0) |
| 레지스트리 | Harbor |
프로젝트 구조
src/
├── app/
│ ├── page.tsx # 메인 대시보드 페이지
│ └── api/
│ ├── report/route.ts # 전체 리포트 API
│ ├── metrics/[type]/route.ts # 개별 메트릭 API
│ └── health/route.ts # 헬스체크
├── components/
│ ├── charts/
│ │ ├── TimeSeriesChart.tsx # CPU/Memory/Disk/NAS 차트
│ │ └── NetworkChart.tsx # Ingress/Istio 네트워크 차트
│ ├── report/
│ │ ├── SummaryCards.tsx # 상단 요약 카드 (5개)
│ │ ├── NodeTable.tsx # 노드별 상세 테이블
│ │ ├── NasTable.tsx # NAS mountpoint별 상세
│ │ ├── NetworkTable.tsx # Network RX/TX 상세
│ │ ├── AlertPanel.tsx # 주의 구간 패널 (CPU/Memory/Disk/NAS)
│ │ ├── NetworkAlertPanel.tsx # Network 주의 구간 패널
│ │ └── ReportHeader.tsx # 리포트 헤더 + PDF 버튼
│ └── ErrorBoundary.tsx # 에러 격리 컴포넌트
├── hooks/
│ └── useReport.ts # React Query 기반 데이터 fetch
├── lib/
│ ├── prometheus.ts # Prometheus API 클라이언트 + PromQL 쿼리
│ ├── kubernetes.ts # Kubernetes API 클라이언트
│ ├── analytics.ts # 통계 계산 + Z-score peak 감지
│ └── formatters.ts # 포맷팅 유틸 (bytes, percent, timestamp)
└── types/
└── metrics.ts # TypeScript 인터페이스 정의
charts/infra-report/ # Helm Chart
├── Chart.yaml
├── values.yaml
└── templates/
├── deployment.yaml
├── service.yaml
├── ingress.yaml
├── configmap.yaml
├── serviceaccount.yaml
├── clusterrole.yaml
└── clusterrolebinding.yaml
주의 구간 판단 기준
임계값 기반
| 메트릭 | Warning | Critical |
|---|---|---|
| CPU | - | max > 90% |
| Memory | 80% < max ≤ 90% | max > 90% |
| Disk | 80% < max ≤ 90% | max > 90% |
| NAS | 80% < max ≤ 90% | max > 90% |
Z-score Peak 감지
모든 메트릭에 적용됩니다. 상승 방향(평균 초과)만 감지합니다.
- 알고리즘: 전체 데이터의 평균(mean)과 모표준편차(stddev)를 계산하고, 각 데이터 포인트의 Z-score
(값 - mean) / stddev를 산출 - Threshold: 메트릭별로 다름
| 메트릭 | Z-score Threshold |
|---|---|
| CPU | 5 |
| Memory | 5 |
| Disk | 2 |
| NAS | 2 |
| Ingress | 5 |
| Istio | 5 |
- 최소 표준편차 가드:
stddev < 0.5이면 데이터 변동이 무의미하므로 peak 감지 스킵 (Disk 등 안정적 메트릭에서 미세 변동이 peak으로 잡히는 문제 방지) - 감지 방향: 상승(양수)만 감지 (
zScore > threshold). 평균 이하 급감은 peak으로 잡지 않음 - 구간 병합: 연속된 peak 포인트를 하나의 구간으로 묶어 시작/종료 시간, 최대값, 평균값 기록
- 차트 표시: peak 구간은 차트에 빨간색 반투명 영역(markArea)으로 표시
- 클릭 확대: AlertPanel에서 peak 항목 클릭 시 해당 시간대로 차트 확대 (최소 앞뒤 15분 padding)
환경 변수 (ConfigMap)
charts/infra-report/values.yaml의 config 섹션에서 설정합니다.
| 변수 | 기본값 | 설명 |
|---|---|---|
PROMETHEUS_URL |
http://prometheus-server.monitoring |
Prometheus 서버 주소 |
REPORT_STEP |
5m |
데이터 수집 간격 |
REPORT_RANGE_DAYS |
7 |
기본 조회 기간 (일) |
TZ |
Asia/Seoul |
타임존 |
QUERY_CPU |
100 - (avg by (node)(...)) |
CPU 사용률 PromQL |
QUERY_MEMORY |
(1 - MemAvailable/MemTotal) * 100 |
Memory 사용률 PromQL |
QUERY_DISK |
(1 - avail/size) * 100 |
Disk 사용률 PromQL |
QUERY_NAS |
NFS 기반 쿼리 | NAS 사용률 PromQL |
QUERY_INGRESS_RX/TX |
ingress-nginx 컨테이너 네트워크 | Ingress 트래픽 PromQL |
QUERY_ISTIO_RX/TX |
istio-system 컨테이너 네트워크 | Istio 트래픽 PromQL |
PromQL 쿼리를 변경하면 values.yaml 수정 후 Helm chart를 재배포하면 됩니다 (소스 코드 수정 불필요).
배포 방법
사전 요구사항
- Kubernetes 클러스터
- Prometheus (node-exporter 포함)
- Harbor 레지스트리
- ArgoCD
- Gitea (소스 저장소 + CI/CD)
1. Gitea 저장소 Secrets 등록
Gitea 저장소 Settings > Secrets에 다음을 등록합니다:
| Secret | 설명 |
|---|---|
REGISTRY_URL |
Harbor 주소 (예: harbor.example.com) |
REGISTRY_USER |
Harbor 사용자 |
REGISTRY_PASSWORD |
Harbor 비밀번호 |
2. Harbor Pull Secret 생성
kubectl create secret docker-registry harbor-pull-secret \
--docker-server=harbor.example.com \
--docker-username=admin \
--docker-password='password' \
-n soo
3. ArgoCD Repository Secret 생성
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: harbor-helm-repo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
type: Opaque
stringData:
type: helm
name: harbor-infra
url: harbor.example.com/infra
enableOCI: "true"
username: admin
password: "password"
EOF
4. ArgoCD Application 생성
kubectl apply -f - <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: infra-report
namespace: argocd
spec:
project: default
source:
chart: infra-report
repoURL: harbor.example.com/infra
targetRevision: ">0.0.0"
helm:
releaseName: infra-report
destination:
server: https://kubernetes.default.svc
namespace: soo
syncPolicy:
automated:
prune: true
selfHeal: true
EOF
5. 코드 Push → 자동 배포
main 브랜치에 push하면:
- Gitea Actions: Docker 이미지 빌드 → Harbor push
- Gitea Actions: Helm chart 패키징 → Harbor OCI push (타임스탬프 기반 버전)
- ArgoCD: 새 chart 버전 감지 → 자동 sync → 파드 재배포
.md파일만 변경된 push에서는 CI가 실행되지 않습니다 (paths-ignore설정).
로컬 개발
npm install
npm run dev # http://localhost:3000
Prometheus 접근이 필요하므로 포트포워딩 또는 환경 변수 설정이 필요합니다:
PROMETHEUS_URL=http://localhost:9090 npm run dev
시간대 처리
- Prometheus는 항상 UTC로 데이터를 저장/반환합니다
- 프론트엔드에서
Asia/Seoul타임존으로 변환하여 표시합니다 TZ환경 변수는 Prometheus 쿼리에 영향을 주지 않습니다
노드 배치
기본적으로 nodegroup: nd 라벨이 있는 노드에만 배포됩니다. values.yaml의 nodeSelector에서 변경 가능합니다.
Kubernetes RBAC
ServiceAccount infra-report-sa에 ClusterRole이 부여되어 노드 정보를 조회합니다:
nodes리소스에 대한get,list권한
이미지 태그 전략
- CI에서
sha-<7자리 commit hash>형태로 태그 생성 (예:sha-25c7d82) v*태그 push 시 태그 이름 그대로 사용 (예:v1.0.0)- Helm chart의
appVersion에 이미지 태그가 자동 설정됨 - Deployment는
appVersionfallback으로 이미지 태그 결정