infra-report/research.md

30 KiB
Raw Blame History

인프라 주간 모니터링 보고서 시스템 - 기술 리서치

1. 프로젝트 개요

목표: Prometheus API와 Kubernetes API에서 인프라 메트릭 데이터를 수집하여 주간 모니터링 보고서를 자동 생성하는 시스템

배포 환경: Kubernetes 클러스터 내 Pod으로 배포 (namespace: soo)

핵심 모니터링 메트릭:

  • CPU 사용률
  • Memory 사용률
  • Disk 사용률
  • NAS (NFS/CIFS) 스토리지
  • Network Traffic (송/수신)

핵심 분석 항목:

  • 평균(avg) / 최대(max) / 최소(min) 값
  • Peak 구간 감지 (이상 탐지)
  • 주의가 필요한 데이터 구간 하이라이트

2. 데이터 소스 분석

2.1 Prometheus HTTP API

Prometheus는 REST API를 통해 메트릭 데이터를 조회할 수 있다.

주요 엔드포인트

엔드포인트 용도 설명
GET /api/v1/query 즉시 쿼리 현재 시점의 메트릭 조회
GET /api/v1/query_range 범위 쿼리 주간 보고서의 핵심 - 시작/종료 시간 + step 간격으로 시계열 데이터 조회
GET /api/v1/labels 레이블 목록 사용 가능한 메트릭 레이블 조회
GET /api/v1/label/<name>/values 레이블 값 특정 레이블의 값 조회
GET /api/v1/metadata 메트릭 메타데이터 메트릭 설명 및 타입 정보

query_range API 호출 예시

GET /api/v1/query_range?query=<PromQL>&start=<rfc3339>&end=<rfc3339>&step=<duration>
  • 최대 조회 범위: 32일 (주간 보고서에 충분)
  • step: 데이터 해상도 (예: 5m, 15m, 1h)
  • 주간 보고서용 권장 step: 5m ~ 15m (세밀한 peak 감지를 위해)

핵심 PromQL 쿼리

CPU 사용률 (%):

# 노드별 CPU 사용률
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 또는
sum by (instance) (rate(node_cpu_seconds_total{mode!="idle"}[5m])) * 100

Memory 사용률 (%):

# 노드별 메모리 사용률
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

Disk 사용률 (%):

# 파일시스템별 디스크 사용률
(1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) * 100

NAS/NFS 모니터링:

# NFS 마운트 디스크 사용률
(1 - node_filesystem_avail_bytes{fstype="nfs"} / node_filesystem_size_bytes{fstype="nfs"}) * 100

# NFS 마운트 디스크 사용률 (nfs4 포함)
(1 - node_filesystem_avail_bytes{fstype=~"nfs|nfs4|cifs"} / node_filesystem_size_bytes{fstype=~"nfs|nfs4|cifs"}) * 100

참고: NAS 모니터링은 node_exporter의 filesystem collector가 NFS/CIFS 마운트도 수집함. Synology 등 전용 NAS는 SNMP exporter(snmp_exporter)를 통해 더 상세한 메트릭 수집 가능.

Network Traffic (bytes/sec):

# 수신 트래픽 (bytes/sec)
sum by (instance) (rate(node_network_receive_bytes_total{device!~"lo|veth.*|docker.*|br-.*"}[5m]))

# 송신 트래픽 (bytes/sec)
sum by (instance) (rate(node_network_transmit_bytes_total{device!~"lo|veth.*|docker.*|br-.*"}[5m]))

# bps 단위로 변환
sum by (instance) (rate(node_network_receive_bytes_total{device!~"lo|veth.*|docker.*|br-.*"}[5m])) * 8

통계 분석용 PromQL (avg / max / peak 감지)

평균 (avg_over_time):

# 주간 평균 CPU 사용률
avg_over_time(
  (100 - avg by (instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)[7d:5m]
)

최대 (max_over_time):

# 주간 최대 CPU 사용률
max_over_time(
  (100 - avg by (instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)[7d:5m]
)

Peak/이상 탐지 (Z-Score 기반):

# Z-Score = (현재값 - 평균) / 표준편차
# |Z| > 2 이면 이상 구간으로 판단
(
  rate(node_cpu_seconds_total{mode!="idle"}[5m])
  - avg_over_time(rate(node_cpu_seconds_total{mode!="idle"}[5m])[1d])
) / stddev_over_time(rate(node_cpu_seconds_total{mode!="idle"}[5m])[1d])

표준편차 기반 이상 탐지:

# 평균 + 2*표준편차를 초과하는 구간 감지
<metric> > (avg_over_time(<metric>[7d:5m]) + 2 * stddev_over_time(<metric>[7d:5m]))

2.2 Kubernetes API

노드 정보 조회

엔드포인트 용도
GET /api/v1/nodes 전체 노드 목록 + 스펙(CPU, Memory, OS 등)
GET /api/v1/nodes/<name> 특정 노드 상세 정보
GET /apis/metrics.k8s.io/v1beta1/nodes 노드별 실시간 리소스 사용량 (metrics-server 필요)
GET /apis/metrics.k8s.io/v1beta1/nodes/<name> 특정 노드 실시간 사용량

노드 정보에서 얻을 수 있는 데이터

{
  "metadata": { "name": "node-1", "labels": { "role": "worker" } },
  "status": {
    "capacity": { "cpu": "16", "memory": "65536Mi" },
    "allocatable": { "cpu": "15800m", "memory": "63000Mi" },
    "nodeInfo": {
      "osImage": "Ubuntu 22.04",
      "kubeletVersion": "v1.28.0",
      "containerRuntimeVersion": "containerd://1.7.0"
    },
    "conditions": [
      { "type": "Ready", "status": "True" },
      { "type": "MemoryPressure", "status": "False" },
      { "type": "DiskPressure", "status": "False" }
    ]
  }
}

인증 방식 (Pod 내부 배포 기준)

Pod으로 배포되므로 In-Cluster Config를 사용한다. K8s가 자동으로 ServiceAccount 토큰을 Pod에 마운트해준다.

/var/run/secrets/kubernetes.io/serviceaccount/token    ← Bearer Token
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt   ← CA 인증서
KUBERNETES_SERVICE_HOST / KUBERNETES_SERVICE_PORT       ← API 서버 주소 (자동 주입)

@kubernetes/client-node 라이브러리 사용 시:

import * as k8s from '@kubernetes/client-node';

const kc = new k8s.KubeConfig();
kc.loadFromCluster();  // ← in-cluster config 자동 로드

const coreApi = kc.makeApiClient(k8s.CoreV1Api);
const nodes = await coreApi.listNode();

참고: 외부 개발 시에는 kc.loadFromDefault()로 로컬 kubeconfig 사용 가능


3. 아키텍처 (K8s Pod 배포)

3.1 배포 아키텍처

K8s Pod으로 배포되므로 클러스터 내부 통신을 활용한 Next.js 풀스택 (BFF 패턴) 단일 구성이 최적이다.

┌─── K8s Cluster ──────────────────────────────────────────────┐
│                                                              │
│  ┌─── Pod: infra-report (ns: soo) ────────────────────────┐  │
│  │                                                        │  │
│  │  ┌─────────────────────────────────┐                   │  │
│  │  │  Next.js (App Router)           │                   │  │
│  │  │  ┌───────────┐  ┌────────────┐  │                   │  │
│  │  │  │ Frontend  │  │ API Routes │──┼──→ Prometheus     │  │
│  │  │  │ (React)   │  │ (BFF)      │──┼──→ K8s API Server │  │
│  │  │  └───────────┘  └────────────┘  │                   │  │
│  │  └─────────────────────────────────┘                   │  │
│  │  ServiceAccount: infra-report-sa                       │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌── Service ──┐                                             │
│  │ ClusterIP   │ ← Ingress / NodePort로 외부 접근            │
│  │ :3000       │                                             │
│  └─────────────┘                                             │
│                                                              │
│  Prometheus: http://prometheus-server.monitoring    │
│  K8s API:    https://kubernetes.default.svc (in-cluster)     │
└──────────────────────────────────────────────────────────────┘

3.2 K8s Pod 배포의 이점

이점 설명
CORS 문제 없음 API Routes가 서버 사이드에서 Prometheus 호출 (Pod 간 통신)
인증 자동 처리 ServiceAccount 토큰이 Pod에 자동 마운트 → K8s API 인증
Prometheus 내부 접근 prometheus-server.monitoring으로 클러스터 내부 DNS 호출
설정 관리 ConfigMap/Secret으로 환경변수 주입
헬스체크 K8s liveness/readiness probe 활용
자동 복구 Pod 장애 시 자동 재시작
수평 확장 필요시 replica 증가 가능 (보고서 용도라 보통 1개면 충분)

3.3 프론트엔드 Only 가능 여부

K8s Pod으로 배포하는 이상 BFF 패턴이 자연스러운 선택이다. Next.js 자체가 서버 런타임을 포함하므로 "프론트만 구현"해도 API Routes로 백엔드 로직을 가진 풀스택 앱이 된다. 즉, 프론트엔드 코드만 작성해도 사실상 백엔드가 포함된 구조이므로 프론트 개발자 혼자서 충분히 구현 가능하다.


4. 기술 스택 상세

4.1 프론트엔드

카테고리 추천 기술 대안 선택 이유
프레임워크 Next.js (App Router) Vite + React API Routes로 BFF 패턴, standalone 빌드로 K8s 최적화
언어 TypeScript JavaScript 타입 안정성, API 응답 타입 정의
차트 라이브러리 Apache ECharts (echarts-for-react) Recharts, Chart.js 대량 데이터 처리 성능 우수, 다양한 차트 타입, 인터랙티브 기능
UI 프레임워크 Tailwind CSS + shadcn/ui Ant Design, MUI 경량, 커스터마이징 용이, 보고서 레이아웃에 적합
테이블 TanStack Table AG Grid 정렬/필터링, 경량
상태관리 TanStack Query (React Query) SWR, Zustand API 데이터 캐싱/재조회 최적화
날짜 처리 date-fns 또는 dayjs moment.js (deprecated) 경량, 트리쉐이킹 지원
PDF 생성 html2canvas + jsPDF (클라이언트) 또는 Puppeteer (서버) react-pdf 보고서 레이아웃 그대로 PDF 변환

차트 라이브러리 비교 (보고서 용도 관점)

기준 ECharts Recharts Chart.js
대량 데이터 (1만+ 포인트) WebGL 렌더링으로 최고 SVG 기반, 느려짐 Canvas 기반, 양호
시계열 차트 내장 dataZoom, 브러시 선택 기본적 줌 플러그인 필요
보고서 스타일 풍부한 옵션 심플 심플
툴팁/인터랙션 매우 풍부 기본적 기본적
번들 사이즈 ~1MB (트리쉐이킹 가능) ~200KB ~60KB
React 통합 echarts-for-react 래퍼 네이티브 React react-chartjs-2 래퍼

권장: 인프라 모니터링 보고서는 데이터 포인트가 많고 시계열 분석이 핵심이므로 Apache ECharts 추천. 데이터가 적고 단순한 보고서라면 Recharts도 충분.

4.2 백엔드 (경량)

카테고리 추천 기술 대안 선택 이유
런타임 Node.js Python (FastAPI) 프론트와 언어 통일, Next.js API Routes 활용 가능
HTTP 클라이언트 axios 또는 fetch (Node 18+) got, node-fetch Prometheus/K8s API 호출
K8s 클라이언트 @kubernetes/client-node kubectl exec 공식 JS 클라이언트, in-cluster config 지원
스케줄링 node-cron 또는 K8s CronJob Bull Queue Pod 내부 cron 또는 K8s 네이티브 CronJob
PDF (서버) Puppeteer Playwright 헤드리스 브라우저로 pixel-perfect PDF

4.3 Python 백엔드 대안 (데이터 분석 강점)

카테고리 기술 장점
프레임워크 FastAPI 비동기, 자동 API 문서, 타입 힌트
Prometheus 클라이언트 prometheus-api-client PromQL 결과를 Pandas DataFrame으로 변환
K8s 클라이언트 kubernetes (공식) 완성도 높은 공식 클라이언트
데이터 분석 Pandas, NumPy 통계 분석(평균/최대/표준편차/이상탐지) 강력
PDF 생성 WeasyPrint, ReportLab HTML → PDF 변환

참고: 데이터 분석/통계에 중점을 둔다면 Python 백엔드가 더 강력하지만, 프론트엔드와의 통합성과 단일 프로젝트 관리를 고려하면 Next.js + API Routes가 더 실용적.


5. 보고서 데이터 가공 로직

5.1 데이터 수집 흐름

1. 보고 기간 설정 (예: 지난 7일)
   ├─ start: 2026-03-05T00:00:00Z
   └─ end:   2026-03-12T00:00:00Z

2. Prometheus query_range API 호출
   ├─ CPU 사용률 쿼리 (step=5m → 2,016 데이터포인트/노드)
   ├─ Memory 사용률 쿼리
   ├─ Disk 사용률 쿼리
   ├─ NAS 사용률 쿼리
   └─ Network 트래픽 쿼리

3. K8s API 호출
   ├─ 노드 목록 + 스펙 (CPU cores, RAM 총량)
   └─ 노드 상태 (conditions)

4. 데이터 가공
   ├─ 노드별 통계 계산 (avg, max, min, p95, p99)
   ├─ Peak 구간 감지 (Z-Score 기반)
   ├─ 임계값 초과 구간 마킹
   └─ 트렌드 분석 (전주 대비 증감)

5. 보고서 렌더링
   ├─ 요약 대시보드 (핵심 지표 카드)
   ├─ 시계열 차트 (peak 구간 하이라이트)
   ├─ 노드별 상세 테이블
   └─ PDF 내보내기

5.2 Peak 감지 알고리즘

방법 1: PromQL 서버 사이드 (Prometheus에서 계산)

# avg_over_time + stddev_over_time 조합
# 평균 + 2σ 초과 시 peak으로 판정

# CPU peak 감지
(100 - avg by (instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
>
(
  avg_over_time((100 - avg by (instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)[7d:5m])
  + 2 * stddev_over_time((100 - avg by (instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)[7d:5m])
)

방법 2: 클라이언트/백엔드 사이드 (JavaScript/Python)

// Z-Score 기반 peak 감지
function detectPeaks(dataPoints, threshold = 2) {
  const values = dataPoints.map(d => d.value);
  const mean = values.reduce((a, b) => a + b) / values.length;
  const stddev = Math.sqrt(
    values.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / values.length
  );

  return dataPoints.map(d => ({
    ...d,
    zScore: (d.value - mean) / stddev,
    isPeak: Math.abs((d.value - mean) / stddev) > threshold,
  }));
}

5.3 보고서 구성 요소

┌─────────────────────────────────────────────────┐
│           인프라 주간 모니터링 보고서              │
│           2026.03.05 ~ 2026.03.12               │
├─────────────────────────────────────────────────┤
│  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐        │
│  │ CPU  │  │ MEM  │  │ DISK │  │ NET  │  ← 요약 │
│  │ 평균 │  │ 평균 │  │ 평균 │  │ 평균 │  카드   │
│  │ 최대 │  │ 최대 │  │ 최대 │  │ 최대 │        │
│  │ 최소 │  │ 최소 │  │ 최소 │  │      │        │
│  └──────┘  └──────┘  └──────┘  └──────┘        │
├─────────────────────────────────────────────────┤
│  [CPU 사용률 시계열 차트]                         │
│  ████████░░░░████████████████░░░░████████       │
│           ↑ peak 구간 하이라이트                  │
├─────────────────────────────────────────────────┤
│  [Memory 사용률 시계열 차트]                      │
├─────────────────────────────────────────────────┤
│  [Disk/NAS 사용률 차트]                          │
├─────────────────────────────────────────────────┤
│  [Network Traffic 차트 (In/Out)]                 │
├─────────────────────────────────────────────────┤
│  노드별 상세                                     │
│  ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┐   │
│  │ 노드 │ CPU  │ CPU  │ CPU  │ MEM  │ MEM  │ MEM  │ DISK │      │
│  │      │ avg  │ max  │ min  │ avg  │ max  │ min  │ max  │      │
│  ├──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┤   │
│  │node-1│ 45%  │ 92%  │ 12%  │ 67%  │ 85%  │ 41%  │ 72%  │      │
│  │node-2│ 38%  │ 78%  │  8%  │ 55%  │ 70%  │ 35%  │ 45%  │      │
│  └──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┘   │
├─────────────────────────────────────────────────┤
│  ⚠ 주의 구간                                    │
│  - node-1: 03/07 14:00~16:30 CPU 92% 도달       │
│  - node-2: 03/09 02:00~03:00 Memory 85% 초과    │
│  - NAS-01: 디스크 사용률 85% 초과 (증설 검토 필요) │
└─────────────────────────────────────────────────┘

6. 기술 스택 최종 추천

6.1 추천 구성: Next.js 풀스택 + K8s 배포

infra-report/
├── src/
│   ├── app/                    # Next.js App Router
│   │   ├── page.tsx            # 메인 보고서 페이지
│   │   ├── api/                # API Routes (BFF)
│   │   │   ├── metrics/        # Prometheus 데이터 프록시 + 가공
│   │   │   │   ├── cpu/route.ts
│   │   │   │   ├── memory/route.ts
│   │   │   │   ├── disk/route.ts
│   │   │   │   ├── nas/route.ts
│   │   │   │   └── network/route.ts
│   │   │   ├── nodes/route.ts  # K8s 노드 정보
│   │   │   └── report/route.ts # 보고서 데이터 통합
│   │   └── report/
│   │       └── [id]/page.tsx   # 개별 보고서 상세
│   ├── components/
│   │   ├── charts/             # 차트 컴포넌트
│   │   │   ├── CpuChart.tsx
│   │   │   ├── MemoryChart.tsx
│   │   │   ├── DiskChart.tsx
│   │   │   ├── NetworkChart.tsx
│   │   │   └── PeakHighlight.tsx
│   │   ├── report/             # 보고서 레이아웃 컴포넌트
│   │   │   ├── SummaryCards.tsx
│   │   │   ├── NodeTable.tsx
│   │   │   └── AlertSection.tsx
│   │   └── ui/                 # 공통 UI 컴포넌트
│   ├── lib/
│   │   ├── prometheus.ts       # Prometheus API 클라이언트
│   │   ├── kubernetes.ts       # K8s API 클라이언트 (in-cluster config)
│   │   ├── analytics.ts        # 통계 계산 (avg, max, peak 감지)
│   │   └── formatters.ts       # 데이터 포맷팅 (bytes→GB 등)
│   └── types/
│       ├── metrics.ts          # 메트릭 데이터 타입
│       └── report.ts           # 보고서 데이터 타입
├── k8s/                        # K8s 매니페스트
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── serviceaccount.yaml
│   ├── rbac.yaml               # ClusterRole + ClusterRoleBinding
│   └── configmap.yaml
├── Dockerfile
├── .dockerignore
├── package.json
├── tailwind.config.ts
├── tsconfig.json
└── .env.local                  # 로컬 개발용 (Pod에서는 ConfigMap/Secret 사용)

6.2 핵심 패키지 목록

{
  "dependencies": {
    "next": "^14.x",
    "react": "^18.x",
    "typescript": "^5.x",

    "echarts": "^5.x",
    "echarts-for-react": "^3.x",

    "@tanstack/react-query": "^5.x",
    "@tanstack/react-table": "^8.x",

    "tailwindcss": "^3.x",
    "@radix-ui/react-*": "latest",

    "axios": "^1.x",
    "@kubernetes/client-node": "^0.20.x",

    "date-fns": "^3.x",
    "jspdf": "^2.x",
    "html2canvas": "^1.x",

    "zod": "^3.x"
  }
}

7. K8s 배포 상세

7.1 Dockerfile

# ── Build Stage ──
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# ── Production Stage ──
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"

CMD ["node", "server.js"]

next.config.jsoutput: 'standalone' 설정 필요

7.2 K8s 매니페스트

ServiceAccount + RBAC (노드 조회 권한)

# k8s/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: infra-report-sa
  namespace: soo
---
# k8s/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: infra-report-reader
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list"]
  - apiGroups: ["metrics.k8s.io"]
    resources: ["nodes"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: infra-report-reader-binding
subjects:
  - kind: ServiceAccount
    name: infra-report-sa
    namespace: soo
roleRef:
  kind: ClusterRole
  name: infra-report-reader
  apiGroup: rbac.authorization.k8s.io

ConfigMap (환경변수)

# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: infra-report-config
  namespace: soo
data:
  PROMETHEUS_URL: "http://prometheus-server.monitoring"
  REPORT_STEP: "5m"
  REPORT_RANGE_DAYS: "7"
  TZ: "Asia/Seoul"

Deployment

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: infra-report
  namespace: soo
  labels:
    app: infra-report
spec:
  replicas: 1
  selector:
    matchLabels:
      app: infra-report
  template:
    metadata:
      labels:
        app: infra-report
    spec:
      serviceAccountName: infra-report-sa
      containers:
        - name: infra-report
          image: harbor.inje-private.com/soo/infra-report:latest
          ports:
            - containerPort: 3000
          envFrom:
            - configMapRef:
                name: infra-report-config
          resources:
            requests:
              cpu: "100m"
              memory: "256Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"
          livenessProbe:
            httpGet:
              path: /api/health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 30
          readinessProbe:
            httpGet:
              path: /api/health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10

Service + Ingress

# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: infra-report
  namespace: soo
spec:
  type: ClusterIP
  selector:
    app: infra-report
  ports:
    - port: 80
      targetPort: 3000
      protocol: TCP
---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: infra-report
  namespace: soo
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: infra-report.gpulive.cloud    # 실제 도메인으로 변경
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: infra-report
                port:
                  number: 80

7.3 환경변수 관리

구분 로컬 개발 K8s Pod
Prometheus URL .env.local ConfigMap
K8s 인증 kubeconfig (자동) ServiceAccount (자동)
민감 정보 .env.local Secret
타임존 OS 설정 ConfigMap (TZ=Asia/Seoul)

7.4 빌드/배포 파이프라인

1. 코드 Push → Gitea (gitea.inje-private.com)
2. CI (Gitea Runner)
   ├─ npm ci && npm run build
   ├─ docker build → harbor.inje-private.com/soo/infra-report:${TAG}
   └─ docker push
3. CD (ArgoCD: argocd.gpulive.cloud)
   ├─ k8s/ 매니페스트 변경 감지
   └─ 자동 배포 (sync)

7.5 Next.js 설정 (standalone 빌드)

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',  // Docker 최적화 필수
  experimental: {
    // 서버 컴포넌트에서 K8s 클라이언트 사용 시
    serverComponentsExternalPackages: ['@kubernetes/client-node'],
  },
};

module.exports = nextConfig;

8. 구현 우선순위 로드맵

Phase 1: 프로젝트 세팅 + K8s 배포 기반

  • Next.js 프로젝트 초기 구성 (TypeScript, Tailwind, standalone 빌드)
  • Dockerfile 작성 + 로컬 빌드 테스트
  • K8s 매니페스트 작성 (ServiceAccount, RBAC, Deployment, Service)
  • Harbor 이미지 Push + K8s 클러스터 배포 확인
  • Health check API (/api/health) 구현

Phase 2: 데이터 수집 MVP

  • Prometheus API 클라이언트 구현 (lib/prometheus.ts)
  • K8s 노드 정보 조회 (lib/kubernetes.ts, in-cluster config)
  • CPU/Memory 메트릭 API Routes 구현
  • 기본 시계열 차트 (ECharts)
  • 요약 카드 컴포넌트

Phase 3: 데이터 확장

  • Disk/NAS/Network 메트릭 추가
  • 노드별 상세 테이블
  • 통계 계산 로직 (avg, max, p95)

Phase 4: 분석 기능

  • Peak 구간 감지 (Z-Score)
  • 차트에 peak 구간 하이라이트
  • 주의 구간 알림 섹션
  • 전주 대비 트렌드

Phase 5: 보고서 기능

  • PDF 내보내기
  • 보고서 기간 선택 UI
  • Ingress 설정 + 외부 접근

Phase 6: 자동화 (추후)

  • 주간 자동 보고서 생성 (CronJob 또는 node-cron)
  • Slack/Email 발송
  • Gitea Runner CI/CD 파이프라인 연동
  • ArgoCD 자동 배포

9. 참고 자료

Prometheus

Kubernetes

프론트엔드

PDF 생성

NAS/Storage