Kubernetes

Prometheus 란? — 한 덩어리로 깔리고, 메모리 때문에 보관 기간을 깎았다

한 줄로

Prometheus 를 단독으로 깔지 않는다. kube-prometheus-stack 이라는 묶음 차트로
Grafana·Alertmanager·수집기까지 6개 컴포넌트가 한 번에 들어온다.

그래서 진짜 문제는 설치가 아니라 자원 배분이다. 서버 한 대에 클러스터가 여러 개 뜨기 때문이다.

왜 묶음으로 깔았나

Prometheus 만 깔면 안 된다. 지표를 수집당하는 쪽이 있어야 한다.

컴포넌트 역할
Prometheus 지표를 모아 저장
Prometheus Operator Prometheus 설정을 CRD 로 관리
kube-state-metrics 쿠버 리소스 상태(파드 수, 재시작 횟수…)를 지표로 변환
node-exporter 노드의 CPU·메모리·디스크를 지표로 변환
Alertmanager 경보 발송
Grafana 시각화

이걸 하나씩 깔면 버전 호환과 연결 설정을 직접 맞춰야 한다. kube-prometheus-stack
이미 맞춰진 조합을 준다.

LOCAL_CHART=".../kube-prometheus-stack-34.10.0.tgz"
helm install monitoring "${LOCAL_CHART}" --namespace monitoring --wait

명령 한 줄이다. 대신 뭘 깔았는지 정확히 알기 어려워진다 — 이게 묶음 차트의 대가다.

폐쇄망이라 차트를 파일로 들고 있다

보통은 helm repo add 로 원격 저장소에서 차트를 받는다. 여기서는 못 한다. 인터넷이 없다.

그래서 .tgz 파일을 서버에 미리 갖다 두고 그 경로를 직접 가리킨다.

if [ ! -f "${LOCAL_CHART}" ]; then
  echo "❌ Local chart not found: ${LOCAL_CHART}"
  exit 1
fi

파일이 없으면 명확히 실패한다. 차트 버전을 올리려면 파일을 새로 갖다 놓아야 한다.
helm repo update 로는 안 된다.

이미지도 마찬가지다. 차트가 기본으로 가리키는 Docker Hub 주소를 전부 로컬 레지스트리로 바꾼다.
--set이미지 지정만 8개 들어간다.

--set kube-state-metrics.image.repository="localhost:5001/kube-state-metrics/kube-state-metrics"
--set prometheus-node-exporter.image.repository="localhost:5001/prometheus/node-exporter"
--set global.imagePullPolicy="IfNotPresent"

IfNotPresent 가 중요하다. 기본값(Always)이면 파드가 뜰 때마다 레지스트리를 확인하는데,
폐쇄망에서 그 확인이 실패하면 파드가 안 뜬다.

진짜 쟁점 — 자원을 얼마나 줄 것인가

스크립트 주석에 이렇게 적혀 있다.

# 리소스 제한 설정 (4vCPU/7.8GB 서버 최적화)

서버 한 대의 사양이다. 그런데 이 서버 위에 회사마다 클러스터가 하나씩 뜬다.
모니터링 스택도 회사 수만큼 뜬다는 뜻이다.

그래서 6개 컴포넌트 전부에 자원 상한을 건다.

컴포넌트 CPU 요청 → 상한 메모리 요청 → 상한
Prometheus 100m → 300m 512Mi → 1Gi
Grafana 50m → 150m 128Mi → 256Mi
Alertmanager 25m → 100m 64Mi → 128Mi
Operator 25m → 100m 64Mi → 128Mi
kube-state-metrics 25m → 100m 64Mi → 128Mi
node-exporter 25m → 100m 64Mi → 128Mi

합치면 요청 250m CPU · 약 900Mi 메모리, 상한까지 쓰면 950m · 약 1.8Gi 다.

7.8GB 서버에서 클러스터 하나가 모니터링에만 최대 1.8GB 를 쓴다. 클러스터 4개면 7.2GB 다.
블록체인 노드가 들어갈 자리가 없어진다.

요청값(250m/900Mi) 기준으로 보면 여유가 있어 보이지만, 요청은 최소 보장치일 뿐이다.
부하가 몰리면 상한까지 올라간다.

보관 기간이 12시간이다

가장 눈에 띄는 값이다.

--set prometheus.prometheusSpec.retention=12h

Prometheus 기본값은 15일이다. 그걸 12시간으로 줄였다.

지표를 오래 들고 있으면 디스크와 메모리를 먹는다. 클러스터가 여러 개 뜨는 상황에서
15일치를 회사마다 쌓으면 감당이 안 된다.

대신 어제 무슨 일이 있었는지 알 수 없다. 장애가 밤에 났고 아침에 확인하면
이미 지표가 사라져 있다. 사후 분석을 포기하고 실시간 확인만 남긴 셈이다.

이 트레이드오프는 기록해둘 만하다. 서버를 증설하거나 원격 저장소(remote write)를 붙이면
가장 먼저 되돌릴 값이기 때문이다.

한 번에 정한 값이 아니다

git 로그를 보면 보관 기간은 여러 번 깎였다. 처음부터 12시간이 아니었다.

메모리 최적화: Besu JVM 힙 제한 및 모니터링 retention 조정   (2026-05-06)

- Besu 설치 스크립트: config.json 의 jvmOpts 를 읽어 전달
- Prometheus retention: 14d → 3d, retentionSize 800MB 제한 추가

이 커밋은 monitoring.yml14일 → 3일로 줄였다. 지금 글에서 본 12h
설치 스크립트 쪽의 다른 값이니, 두 군데가 각각 줄어든 셈이다.

주목할 건 커밋 제목이다. “메모리 최적화” 이고, 같은 커밋에서 Besu 의 JVM 힙 제한과
응답 로깅 필터까지 함께 손봤다.

즉 이건 Prometheus 하나의 문제가 아니었다. 서버 전체가 메모리에 쫓기고 있었고,
그중 하나로 지표 보관 기간이 깎인 것이다. 클러스터가 회사마다 하나씩 뜨는
구조에서 모니터링 스택도 회사 수만큼 늘어나니 예견된 일이기도 하다.

retentionSize 제한을 함께 넣은 것도 눈에 띈다. 기간만 정하면 트래픽이 많은 날 용량이
튀는데
, 크기 상한을 같이 걸면 그게 막힌다. 기간과 크기 두 축으로 거는 게 안전하다.

교훈 하나가 남는다. 자원 제한 값은 처음에 정하는 게 아니라 밀려서 정해진다.
14일 → 3일 → (스크립트 쪽은) 12시간으로 내려온 궤적이 그 압박을 그대로 보여준다.

노출은 Ingress 로

설치가 끝나면 ClusterIP 서비스를 만들고 Ingress 규칙을 건다. Prometheus 는
{Ingress포트}/prometheus 로 들어간다.

포트를 따로 쓰지 않는 이유와 경로 재작성이 필요한 이유는
Ingress 글에 적었다.

여기서 걸린 것 — 설치 실패는 잡는데, 바깥이 삼킨다

스크립트 자체는 실패를 제대로 처리한다.

helm install monitoring "${LOCAL_CHART}" ... || {
  echo "❌ Failed to install monitoring stack"
  exit 1
}

exit 1 로 명확히 끝낸다. 차트 파일이 없을 때도 마찬가지다.

문제는 호출부다.

bash "$SCRIPT_DIR/04-install-monitoring.sh" ... || {
  echo "⚠️ ... non-critical, continuing..."
}

스크립트가 정직하게 실패를 알렸는데 바깥에서 무시한다. 그리고 클러스터는 ACTIVE
기록된다.

모니터링이 없는 클러스터가 정상으로 보이는 건 특히 곤란하다. 문제를 발견하는 수단 자체가
없는 상태
인데, 그 사실을 알려줄 방법도 없기 때문이다.

정리

  • Prometheus 단독이 아니라 kube-prometheus-stack 묶음으로 6개가 한 번에 깔린다
  • 폐쇄망이라 차트를 .tgz 파일로 들고 있고, 이미지 경로 8개를 --set 으로 갈아끼운다.
    imagePullPolicy: IfNotPresent 가 아니면 파드가 안 뜬다
  • 자원 상한이 핵심이다. 서버 한 대에 클러스터가 여러 개 뜨므로,
    모니터링 하나가 최대 950m CPU · 1.8Gi 를 먹는 걸 통제해야 한다
  • 보관 기간 12시간 — 기본값 15일에서 대폭 줄였다. 사후 분석을 포기한 트레이드오프
  • 이 값은 한 번에 정해진 게 아니다. “메모리 최적화” 커밋에서 14d → 3d 로 깎인 이력이
    있고, Besu JVM 힙 제한과 같은 커밋이었다 — 서버 전체가 메모리에 쫓기고 있었다
  • 기간과 함께 retentionSize 도 걸었다. 기간만 정하면 트래픽 많은 날 용량이 튄다
  • ⚠️ 무한 리다이렉트를 한 번 겪었다. routePrefix 와 Ingress 경로 재작성이 충돌했다
    (Ingress 편에 자세히)
  • ⚠️ 스크립트는 exit 1 로 정직하게 실패하는데 호출부가 삼킨다.
    모니터링 없는 클러스터가 ACTIVE 로 보인다

같이 읽을 글:
Grafana 대시보드를 파일로 심는다 ·
Ingress 로 포트 3개를 1개로 줄였다 ·
회사마다 클러스터 하나씩 띄운다