🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Kubernetes Prometheus 모니터링 완벽 가이드 - 슬라이드 1/13
A

AI Generated

2025. 10. 29. · 39 Views

Kubernetes Prometheus 모니터링 완벽 가이드

Kubernetes 클러스터에서 Prometheus를 활용한 효과적인 모니터링 시스템 구축 방법을 다룹니다. 실시간 메트릭 수집부터 알림 설정까지, 실무에서 바로 활용할 수 있는 가이드입니다.


목차

  1. Prometheus_기본_구조
  2. ServiceMonitor_설정
  3. Custom_Metrics_생성
  4. PromQL_기본_쿼리
  5. Recording_Rules
  6. Alerting_Rules
  7. Grafana_연동
  8. Node_Exporter_활용

1. Prometheus 기본 구조

시작하며

여러분이 Kubernetes 클러스터를 운영하다가 갑자기 서비스가 느려지거나 멈춘 경험이 있나요? 로그를 확인해보니 메모리가 부족했거나 CPU 사용률이 100%였던 상황, 하지만 그 순간의 메트릭 데이터가 없어서 원인 분석이 어려웠던 경험 말이죠.

이런 문제는 모니터링 시스템이 없거나 불완전할 때 발생합니다. 장애가 발생한 후에야 문제를 알게 되고, 정확한 원인을 파악하기 어렵습니다.

더 큰 문제는 반복적인 장애 패턴을 사전에 감지하지 못한다는 것입니다. 바로 이럴 때 필요한 것이 Prometheus입니다.

Kubernetes 환경에서 가장 널리 사용되는 오픈소스 모니터링 시스템으로, 실시간으로 메트릭을 수집하고 저장하며 알림을 보낼 수 있습니다.

개요

간단히 말해서, Prometheus는 시계열 데이터베이스 기반의 모니터링 시스템입니다. Pull 방식으로 타겟 서비스에서 메트릭을 주기적으로 수집하여 저장합니다.

왜 Prometheus가 필요한지 실무 관점에서 설명하자면, Kubernetes는 동적으로 Pod가 생성되고 삭제되는 환경입니다. 이런 환경에서 각 서비스의 상태를 수동으로 확인하는 것은 불가능에 가깝습니다.

Prometheus는 서비스 디스커버리 기능을 통해 자동으로 모니터링 대상을 찾아내고 메트릭을 수집합니다. 전통적인 방법에서는 각 서버에 에이전트를 설치하고 로그를 중앙 서버로 전송했다면, Prometheus는 HTTP 엔드포인트를 통해 메트릭을 수집합니다.

이는 더 간단하고 표준화된 방식입니다. Prometheus의 핵심 특징은 다차원 데이터 모델(레이블 기반), 강력한 쿼리 언어(PromQL), 그리고 분산 스토리지 없이도 동작하는 단순한 아키텍처입니다.

이러한 특징들이 Kubernetes와 완벽하게 통합되어 클라우드 네이티브 환경의 표준 모니터링 솔루션이 되었습니다.

코드 예제

# Prometheus 배포를 위한 기본 values.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s  # 메트릭 수집 주기
      evaluation_interval: 15s  # 규칙 평가 주기

    scrape_configs:
      - job_name: 'kubernetes-pods'
        kubernetes_sd_configs:
          - role: pod  # Pod 자동 디스커버리
        relabel_configs:
          - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
            action: keep
            regex: true  # prometheus.io/scrape=true 어노테이션이 있는 Pod만 수집

설명

이것이 하는 일: 위 설정은 Prometheus의 기본 구성을 정의합니다. 15초마다 Kubernetes Pod에서 메트릭을 자동으로 수집하도록 설정하는 것입니다.

첫 번째로, global 섹션에서 scrape_interval과 evaluation_interval을 15초로 설정합니다. 이는 Prometheus가 15초마다 모든 타겟에서 메트릭을 수집하고, 알림 규칙을 평가한다는 의미입니다.

너무 짧으면 부하가 증가하고, 너무 길면 실시간성이 떨어지므로 15초가 적절한 균형점입니다. 그 다음으로, scrape_configs에서 kubernetes-pods라는 job을 정의합니다.

kubernetes_sd_configs를 통해 Kubernetes API에서 Pod 정보를 자동으로 가져옵니다. 이것이 서비스 디스커버리의 핵심입니다.

relabel_configs 부분이 실행되면서 필터링이 이루어집니다. __meta_kubernetes_pod_annotation_prometheus_io_scrape 레이블을 확인하여 true인 Pod만 선택합니다.

이를 통해 모든 Pod가 아닌, 모니터링이 필요한 Pod만 선택적으로 수집할 수 있습니다. 여러분이 이 설정을 사용하면 새로운 Pod가 배포될 때마다 자동으로 모니터링 대상에 추가되는 효과를 얻을 수 있습니다.

수동 설정 없이 동적인 환경을 모니터링할 수 있고, 리소스를 효율적으로 사용하며, 표준화된 방식으로 메트릭을 관리할 수 있습니다.

실전 팁

💡 scrape_interval은 서비스 특성에 맞게 조정하세요. 실시간 트랜잭션 서비스는 10초, 배치 작업은 30초가 적합합니다. 너무 짧으면 Prometheus 자체의 CPU/메모리 사용량이 증가합니다.

💡 모든 Pod를 모니터링하지 마세요. prometheus.io/scrape: "true" 어노테이션을 사용해 필요한 Pod만 선택하면 불필요한 메트릭 수집을 방지하고 스토리지를 절약할 수 있습니다.

💡 Prometheus는 로컬 스토리지를 사용하므로 데이터 보관 기간을 설정하세요. --storage.tsdb.retention.time=15d 플래그로 15일치 데이터만 보관하면 디스크 공간을 효율적으로 관리할 수 있습니다.

💡 고가용성이 필요하다면 Thanos나 Cortex 같은 솔루션을 검토하세요. Prometheus 단독으로는 단일 장애점이 될 수 있습니다.

💡 메트릭 카디널리티를 주의하세요. 레이블 값이 무한정 증가하면(예: user_id를 레이블로 사용) 메모리가 폭발적으로 증가합니다.


2. ServiceMonitor 설정

시작하며

여러분이 마이크로서비스 아키텍처를 운영하면서 서비스가 10개, 20개로 늘어날 때마다 Prometheus 설정 파일을 수정하는 번거로움을 겪어본 적 있나요? 새 서비스를 배포할 때마다 scrape_configs에 엔드포인트를 추가하고, 서비스가 삭제되면 다시 제거하는 작업 말이죠.

이런 수동 작업은 실수를 유발하고 운영 부담을 가중시킵니다. 설정을 잘못하면 메트릭이 수집되지 않아 장애 감지가 늦어지고, 불필요한 엔드포인트가 남아있으면 리소스가 낭비됩니다.

바로 이럴 때 필요한 것이 ServiceMonitor입니다. Prometheus Operator가 제공하는 CRD(Custom Resource Definition)로, Kubernetes Service를 자동으로 감지하여 모니터링 대상으로 등록합니다.

개요

간단히 말해서, ServiceMonitor는 Kubernetes의 선언적 방식으로 모니터링 대상을 정의하는 리소스입니다. Label Selector를 사용해 모니터링할 Service를 자동으로 찾아냅니다.

왜 ServiceMonitor가 필요한지 실무 관점에서 설명하자면, GitOps 환경에서 애플리케이션 배포와 모니터링 설정을 하나의 매니페스트로 관리할 수 있습니다. 예를 들어, 새로운 API 서비스를 배포할 때 Deployment, Service, ServiceMonitor를 함께 배포하면 별도의 Prometheus 설정 없이 자동으로 모니터링이 시작됩니다.

기존에는 Prometheus 설정 파일을 직접 수정하고 재시작해야 했다면, 이제는 kubectl apply로 ServiceMonitor만 생성하면 Prometheus Operator가 자동으로 설정을 업데이트합니다. ServiceMonitor의 핵심 특징은 선언적 구성, 네임스페이스 기반 격리, 그리고 자동 설정 재로드입니다.

이러한 특징들이 Kubernetes 네이티브한 방식으로 모니터링을 관리할 수 있게 하여, 대규모 클러스터에서도 일관성 있는 모니터링을 가능하게 합니다.

코드 예제

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: api-service-monitor
  namespace: production
  labels:
    team: backend
spec:
  selector:
    matchLabels:
      app: api-server  # 이 레이블을 가진 Service를 모니터링
  endpoints:
    - port: metrics  # Service의 metrics 포트에서 수집
      path: /metrics  # 메트릭 엔드포인트 경로
      interval: 30s  # 수집 주기
      scrapeTimeout: 10s  # 타임아웃 설정
  namespaceSelector:
    matchNames:
      - production  # production 네임스페이스만 대상

설명

이것이 하는 일: ServiceMonitor는 Prometheus Operator에게 "어떤 Service를 어떻게 모니터링할지" 알려주는 설정입니다. Operator가 이를 읽어서 Prometheus 설정을 자동으로 생성합니다.

첫 번째로, selector 섹션에서 matchLabels를 정의합니다. app: api-server 레이블을 가진 모든 Service를 찾아냅니다.

이것이 자동 디스커버리의 핵심입니다. 새로운 Service가 이 레이블로 생성되면 즉시 모니터링이 시작됩니다.

그 다음으로, endpoints 섹션에서 실제 메트릭 수집 방법을 정의합니다. port: metrics는 Service 정의에서 이름이 "metrics"인 포트를 가리킵니다.

path: /metrics는 HTTP GET 요청을 보낼 경로이고, interval: 30s는 30초마다 수집한다는 의미입니다. namespaceSelector가 실행되면서 범위가 제한됩니다.

matchNames에 production만 지정했으므로, 다른 네임스페이스의 Service는 같은 레이블을 가져도 무시됩니다. 이를 통해 환경별로 모니터링을 분리할 수 있습니다.

여러분이 이 설정을 사용하면 마이크로서비스가 증가해도 각 서비스에 동일한 레이블만 부여하면 자동으로 모니터링되는 효과를 얻을 수 있습니다. 설정 파일 수정 없이 선언적으로 관리할 수 있고, 팀별/환경별로 모니터링을 격리할 수 있으며, Git으로 모니터링 설정을 버전 관리할 수 있습니다.

실전 팁

💡 Service에 prometheus.io/scrape: "true" 어노테이션을 추가하지 마세요. ServiceMonitor를 사용할 때는 Label Selector만 사용하는 것이 더 명확하고 관리하기 쉽습니다.

💡 interval을 너무 짧게 설정하면 타겟이 많을 때 Prometheus가 수집을 완료하지 못할 수 있습니다. scrapeTimeout은 항상 interval보다 작아야 하며, 일반적으로 interval의 1/3 정도가 적당합니다.

💡 네임스페이스를 명시하지 않으면 모든 네임스페이스를 스캔합니다. 프로덕션 환경에서는 반드시 namespaceSelector를 사용해 범위를 제한하여 불필요한 리소스 사용을 방지하세요.

💡 ServiceMonitor 자체에도 레이블을 붙이세요(예: team: backend). Prometheus는 prometheus: kube-prometheus 같은 레이블로 어떤 ServiceMonitor를 사용할지 선택할 수 있습니다.

💡 메트릭 엔드포인트가 인증을 요구한다면 basicAuth나 bearerTokenSecret을 설정할 수 있습니다. 보안이 중요한 환경에서는 TLS 설정도 함께 구성하세요.


3. Custom Metrics 생성

시작하며

여러분이 애플리케이션을 개발하면서 CPU, 메모리 같은 시스템 메트릭만으로는 비즈니스 상황을 파악하기 어려운 경험이 있나요? 예를 들어, "현재 처리 중인 주문 수", "평균 결제 처리 시간", "실패한 API 요청 비율" 같은 비즈니스 메트릭 말이죠.

이런 문제는 표준 메트릭만으로는 애플리케이션의 실제 건강 상태를 알 수 없을 때 발생합니다. CPU는 낮은데 주문 처리가 밀리고 있거나, 메모리는 충분한데 에러율이 높을 수 있습니다.

시스템 메트릭과 비즈니스 메트릭 사이의 간극이 장애 대응을 어렵게 만듭니다. 바로 이럴 때 필요한 것이 Custom Metrics입니다.

애플리케이션 코드에서 직접 비즈니스 로직에 맞는 메트릭을 생성하고 Prometheus 형식으로 노출하는 것입니다.

개요

간단히 말해서, Custom Metrics는 개발자가 애플리케이션에서 직접 정의하고 측정하는 메트릭입니다. Prometheus 클라이언트 라이브러리를 사용해 Counter, Gauge, Histogram, Summary 타입으로 메트릭을 생성합니다.

왜 Custom Metrics가 필요한지 실무 관점에서 설명하자면, 비즈니스 KPI를 실시간으로 추적할 수 있습니다. 예를 들어, 결제 서비스에서 "결제 성공률", "평균 처리 시간", "일별 거래액" 같은 메트릭을 수집하면 장애를 조기에 발견하고 비즈니스 영향도를 즉시 파악할 수 있습니다.

기존에는 애플리케이션 로그를 분석하거나 데이터베이스 쿼리로 통계를 계산했다면, 이제는 메트릭으로 실시간 집계가 가능합니다. 로그보다 가볍고, 쿼리보다 빠르며, 시계열 데이터베이스에 최적화되어 있습니다.

Custom Metrics의 핵심 특징은 애플리케이션 레벨의 가시성, 비즈니스 컨텍스트 포함, 그리고 실시간 집계입니다. 이러한 특징들이 개발자가 애플리케이션의 내부 동작을 정확히 이해하고, 비즈니스 임팩트를 측정하며, 데이터 기반으로 의사결정을 내릴 수 있게 합니다.

코드 예제

from prometheus_client import Counter, Histogram, Gauge, start_http_server
import time
import random

# Counter: 증가만 가능한 누적 메트릭 (요청 수, 에러 수 등)
request_count = Counter('api_requests_total', 'Total API requests', ['method', 'endpoint', 'status'])

# Histogram: 분포를 측정 (응답 시간, 요청 크기 등)
request_duration = Histogram('api_request_duration_seconds', 'Request duration', ['endpoint'])

# Gauge: 증가/감소 가능한 현재 값 (동시 접속자, 큐 크기 등)
active_users = Gauge('active_users', 'Current active users')

def process_request(endpoint, method):
    # 요청 수 카운터 증가
    request_count.labels(method=method, endpoint=endpoint, status='200').inc()

    # 응답 시간 측정 (자동으로 버킷에 분류됨)
    with request_duration.labels(endpoint=endpoint).time():
        time.sleep(random.uniform(0.1, 0.5))  # 실제 처리 시뮬레이션

    # 현재 활성 사용자 수 업데이트
    active_users.set(random.randint(50, 200))

# 메트릭 서버 시작 (포트 8000에서 /metrics 엔드포인트 제공)
start_http_server(8000)

설명

이것이 하는 일: 이 Python 코드는 API 서버에서 요청 수, 응답 시간, 활성 사용자 수를 측정하는 Custom Metrics를 생성합니다. Prometheus가 수집할 수 있는 형식으로 HTTP 엔드포인트를 통해 노출합니다.

첫 번째로, 세 가지 메트릭 타입을 정의합니다. Counter는 api_requests_total로 누적 요청 수를 카운트하며, method, endpoint, status 레이블로 세분화합니다.

예를 들어, "GET /api/users 200" 요청과 "POST /api/orders 500" 요청을 별도로 집계할 수 있습니다. Counter는 절대 감소하지 않으므로 rate() 함수로 초당 요청 수를 계산할 수 있습니다.

그 다음으로, Histogram은 request_duration을 측정합니다. time() 컨텍스트 매니저를 사용하면 자동으로 시작과 끝 시간을 측정하여 duration을 기록합니다.

Histogram은 내부적으로 여러 버킷(0.005s, 0.01s, 0.025s 등)에 데이터를 분류하여, P50, P95, P99 같은 백분위수를 계산할 수 있게 합니다. Gauge는 active_users로 현재 시점의 값을 표현합니다.

set() 메서드로 값을 직접 설정하거나, inc()/dec()로 증감할 수 있습니다. 동시 접속자, 큐에 쌓인 메시지 수, 캐시 히트율 같은 "지금 이 순간"의 상태를 측정하는 데 적합합니다.

start_http_server(8000)이 실행되면 8000번 포트에서 /metrics 엔드포인트가 활성화됩니다. Prometheus는 이 엔드포인트를 주기적으로 스크래핑하여 메트릭을 수집합니다.

메트릭은 Prometheus 텍스트 형식으로 자동 변환됩니다. 여러분이 이 코드를 사용하면 애플리케이션 내부의 비즈니스 로직을 실시간으로 모니터링할 수 있습니다.

어느 엔드포인트가 느린지, 어떤 상태 코드가 많이 발생하는지, 사용자 수가 증가하는 추세인지를 즉시 파악할 수 있고, 이를 기반으로 자동 스케일링이나 알림 규칙을 설정할 수 있습니다.

실전 팁

💡 레이블 카디널리티를 주의하세요. user_id, session_id 같이 값이 무한정 증가하는 레이블은 절대 사용하지 마세요. 메모리 부족으로 Prometheus가 다운될 수 있습니다. 대신 endpoint, method, status 같이 값이 제한적인 레이블만 사용하세요.

💡 Histogram의 버킷은 예상 범위를 커버하도록 설정하세요. 기본 버킷이 맞지 않으면 buckets=[0.1, 0.5, 1.0, 2.0, 5.0]처럼 커스터마이즈하세요. 너무 많은 버킷은 스토리지를 낭비합니다.

💡 메트릭 이름은 Prometheus 네이밍 컨벤션을 따르세요. 애플리케이션 접두사를 붙이고(예: myapp_), 단위를 명시하며(_seconds, _bytes), 동사형보다는 명사형을 사용하세요(requests_total이 request_count보다 좋음).

💡 Gauge를 사용할 때 스레드 안전성을 고려하세요. 멀티스레드 환경에서는 inc()/dec()가 원자적 연산이지만, get() 후 set()은 race condition이 발생할 수 있습니다.

💡 메트릭 서버는 별도 포트로 분리하세요. 비즈니스 트래픽과 모니터링 트래픽을 격리하면 부하 상황에서도 메트릭 수집이 안정적으로 동작합니다.


4. PromQL 기본 쿼리

시작하며

여러분이 Prometheus에 수천 개의 메트릭이 쌓여있는데, 정작 "지난 5분간 에러율이 몇 %인지", "API 응답 시간의 P95가 얼마인지" 같은 간단한 질문에 답하지 못한 경험이 있나요? 데이터는 많은데 어떻게 조회해야 할지 막막한 상황 말이죠.

이런 문제는 메트릭을 수집만 하고 쿼리 방법을 모를 때 발생합니다. Raw 데이터는 있지만 의미 있는 인사이트로 변환하지 못하면 모니터링 시스템의 가치가 절반도 발휘되지 않습니다.

바로 이럴 때 필요한 것이 PromQL(Prometheus Query Language)입니다. 시계열 데이터를 필터링하고, 집계하고, 연산하여 원하는 인사이트를 추출하는 강력한 쿼리 언어입니다.

개요

간단히 말해서, PromQL은 Prometheus의 쿼리 언어로 메트릭을 선택하고 변환하는 함수형 언어입니다. SQL처럼 데이터를 조회하지만, 시계열 데이터에 특화된 연산자와 함수를 제공합니다.

왜 PromQL이 필요한지 실무 관점에서 설명하자면, 실시간 대시보드와 알림 규칙을 만들 때 필수적입니다. 예를 들어, "최근 5분간 500 에러가 10회 이상 발생하면 알림"이라는 규칙을 만들려면 PromQL로 에러 수를 집계하고 임계값과 비교해야 합니다.

Grafana 대시보드의 모든 그래프도 PromQL 쿼리로 동작합니다. 기존에는 데이터베이스에 쿼리하거나 로그를 grep으로 검색했다면, PromQL은 시계열 데이터에 최적화되어 있어 훨씬 빠르고 효율적입니다.

레이블 기반 필터링과 시간 범위 연산이 내장되어 있습니다. PromQL의 핵심 특징은 벡터 기반 연산, 시간 범위 선택자, 그리고 다양한 집계 함수입니다.

이러한 특징들이 복잡한 메트릭 분석을 간결한 쿼리로 표현할 수 있게 하며, 실시간으로 대규모 시계열 데이터를 처리할 수 있게 합니다.

코드 예제

# 1. 기본 메트릭 선택: 특정 메트릭의 모든 시계열
api_requests_total

# 2. 레이블 필터링: status가 500인 요청만 선택
api_requests_total{status="500"}

# 3. Rate 함수: 5분간 초당 증가율 계산 (Counter에 필수)
rate(api_requests_total[5m])

# 4. 집계 함수: 엔드포인트별 총 요청 속도
sum by (endpoint) (rate(api_requests_total[5m]))

# 5. 에러율 계산: 500 에러 비율을 백분율로
sum(rate(api_requests_total{status="500"}[5m])) / sum(rate(api_requests_total[5m])) * 100

# 6. Histogram 백분위수: P95 응답 시간
histogram_quantile(0.95, sum by (le) (rate(api_request_duration_seconds_bucket[5m])))

# 7. 임계값 비교: 에러율이 5% 이상인 경우
(sum(rate(api_requests_total{status="500"}[5m])) / sum(rate(api_requests_total[5m])) * 100) > 5

설명

이것이 하는 일: PromQL 쿼리는 Prometheus에 저장된 시계열 데이터에서 원하는 정보를 추출하고 계산합니다. 각 쿼리는 특정 시점의 값이나 시간 범위의 집계를 반환합니다.

첫 번째로, 메트릭 이름만 사용하면 해당 메트릭의 모든 시계열을 선택합니다. api_requests_total은 모든 method, endpoint, status 조합의 데이터를 반환합니다.

중괄호 {}로 레이블 필터를 추가하면 특정 조건을 만족하는 시계열만 선택됩니다. 그 다음으로, rate() 함수가 Counter 메트릭에 적용됩니다.

Counter는 누적값이므로 raw 값은 의미가 없고, 시간당 증가율이 중요합니다. rate(api_requests_total[5m])은 "최근 5분간의 초당 평균 요청 수"를 계산합니다.

[5m]은 범위 벡터 선택자로, 5분간의 데이터 포인트를 선택합니다. sum by (endpoint)가 실행되면서 엔드포인트별로 그룹화됩니다.

여러 Pod에서 같은 endpoint를 서비스한다면, 이들의 rate를 모두 합쳐서 전체 엔드포인트의 요청 속도를 계산합니다. without을 사용하면 특정 레이블을 제외하고 그룹화할 수도 있습니다.

에러율 계산 쿼리는 두 개의 sum을 나눕니다. 분자는 500 에러의 요청 속도, 분모는 전체 요청 속도입니다.

이를 100으로 곱하면 백분율이 됩니다. 이런 비율 계산은 SLA 모니터링에 필수적입니다.

histogram_quantile() 함수는 Histogram 메트릭에서 백분위수를 계산합니다. 0.95는 P95를 의미하고, le 레이블(less or equal)로 그룹화하여 버킷별 누적 분포에서 95번째 백분위수를 추정합니다.

이를 통해 "95%의 요청이 몇 초 안에 완료되는지" 알 수 있습니다. 여러분이 이 쿼리들을 사용하면 메트릭에서 실질적인 인사이트를 추출할 수 있습니다.

단순 수치가 아닌 증가율, 비율, 백분위수를 계산하여 시스템 상태를 정확히 파악할 수 있고, 이를 알림 규칙이나 대시보드에 활용하여 선제적으로 문제에 대응할 수 있습니다.

실전 팁

💡 Counter에는 항상 rate()나 increase()를 사용하세요. raw Counter 값은 Pod 재시작 시 0으로 리셋되어 의미가 없습니다. rate()는 초당 증가율을, increase()는 기간 내 총 증가량을 계산합니다.

💡 범위 벡터의 시간 범위는 scrape_interval의 최소 4배 이상으로 설정하세요. scrape_interval이 15초라면 [1m]은 너무 짧아서 데이터 포인트가 4개밖에 없어 부정확합니다. [5m] 정도가 적당합니다.

💡 sum이나 avg 같은 집계 함수는 by나 without으로 그룹화 레이블을 명시하세요. 명시하지 않으면 모든 레이블이 제거되어 단일 값만 반환되는데, 이후 레이블별 비교가 불가능합니다.

💡 histogram_quantile은 버킷 기반 추정이므로 정확하지 않습니다. 더 정확한 백분위수가 필요하면 Summary 메트릭을 사용하거나, 버킷을 더 촘촘하게 설정하세요.

💡 쿼리 성능을 위해 레이블 필터를 먼저 적용하세요. sum(rate(api_requests_total{status="500"}[5m]))이 rate(sum(api_requests_total{status="500"}[5m]))보다 효율적입니다.


5. Recording Rules

시작하며

여러분이 Grafana 대시보드에서 복잡한 PromQL 쿼리를 실행할 때마다 몇 초씩 걸리거나, 심지어 타임아웃이 발생하는 경험이 있나요? 특히 여러 메트릭을 집계하고 비율을 계산하는 복잡한 쿼리를 여러 대시보드에서 반복 사용할 때 말이죠.

이런 문제는 쿼리가 실행될 때마다 대량의 시계열 데이터를 처음부터 다시 계산하기 때문에 발생합니다. 같은 계산을 반복하면 Prometheus CPU 사용률이 높아지고, 대시보드 로딩이 느려지며, 사용자 경험이 나빠집니다.

바로 이럴 때 필요한 것이 Recording Rules입니다. 자주 사용하는 복잡한 쿼리를 사전에 계산하여 새로운 시계열로 저장함으로써, 쿼리 성능을 극적으로 개선하고 일관성을 보장합니다.

개요

간단히 말해서, Recording Rules는 PromQL 쿼리를 주기적으로 실행하여 결과를 새로운 메트릭으로 저장하는 규칙입니다. evaluation_interval마다 자동으로 계산되어 미리 집계된 메트릭을 생성합니다.

왜 Recording Rules가 필요한지 실무 관점에서 설명하자면, 대규모 환경에서 필수적입니다. 예를 들어, 100개의 마이크로서비스에서 수집한 메트릭으로 전체 에러율을 계산하는 쿼리는 매우 무겁습니다.

이를 Recording Rule로 만들면 미리 계산된 결과를 조회하므로 즉시 응답받을 수 있습니다. 기존에는 쿼리를 실행할 때마다 수백만 개의 데이터 포인트를 스캔하고 집계했다면, Recording Rules는 이미 집계된 결과를 저장하므로 단일 시계열만 조회하면 됩니다.

이는 10배에서 100배까지 성능을 향상시킬 수 있습니다. Recording Rules의 핵심 특징은 사전 계산, 쿼리 재사용, 그리고 계층적 집계입니다.

이러한 특징들이 복잡한 쿼리를 단순화하고, 대시보드 응답 속도를 개선하며, 알림 규칙의 평가 시간을 줄여 시스템 전체의 효율성을 높입니다.

코드 예제

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: recording-rules
  namespace: monitoring
spec:
  groups:
    - name: api_metrics_aggregation
      interval: 30s  # 30초마다 규칙 평가
      rules:
        # 1단계: 서비스별 요청 속도 계산
        - record: job:api_requests:rate5m
          expr: sum by (job, endpoint) (rate(api_requests_total[5m]))

        # 2단계: 서비스별 에러율 계산 (이미 집계된 메트릭 사용)
        - record: job:api_error_rate:ratio
          expr: |
            sum by (job) (rate(api_requests_total{status=~"5.."}[5m]))
            /
            sum by (job) (rate(api_requests_total[5m]))

        # 3단계: 전체 클러스터 P95 응답 시간
        - record: cluster:api_latency:p95
          expr: histogram_quantile(0.95, sum by (le) (rate(api_request_duration_seconds_bucket[5m])))

설명

이것이 하는 일: Recording Rules는 Prometheus가 주기적으로 특정 쿼리를 실행하고 그 결과를 새로운 시계열 메트릭으로 저장하도록 지시합니다. 이후 대시보드나 알림에서는 사전 계산된 메트릭을 빠르게 조회할 수 있습니다.

첫 번째로, interval: 30s 설정으로 30초마다 모든 규칙이 평가됩니다. 이는 scrape_interval과 별개로, 규칙 계산 주기를 의미합니다.

너무 짧으면 Prometheus 부하가 증가하고, 너무 길면 데이터 신선도가 떨어집니다. 그 다음으로, 첫 번째 규칙인 job:api_requests:rate5m이 실행됩니다.

이는 모든 API 요청 메트릭을 job과 endpoint별로 집계하여 5분 평균 요청 속도를 계산합니다. 결과는 job:api_requests:rate5m이라는 새로운 메트릭으로 저장되며, 원본 메트릭보다 시계열 수가 훨씬 적습니다.

두 번째 규칙은 첫 번째 규칙의 결과를 재사용하지 않고 원본 메트릭에서 직접 계산합니다. status=~"5.." 정규식은 500번대 상태 코드를 모두 선택합니다.

500 에러 속도를 전체 요청 속도로 나누어 에러율을 계산하고, 이를 job:api_error_rate:ratio로 저장합니다. 이제 알림 규칙에서 job:api_error_rate:ratio > 0.05만 쿼리하면 됩니다.

세 번째 규칙은 histogram_quantile로 P95 레이턴시를 계산합니다. 이는 매우 무거운 연산이므로 매번 실행하기보다 미리 계산해두는 것이 효율적입니다.

cluster: 접두사는 클러스터 전체 집계를 의미하는 네이밍 컨벤션입니다. 여러분이 Recording Rules를 사용하면 복잡한 대시보드가 즉시 로드되고, 알림 평가가 빨라지며, 일관된 계산 로직을 여러 곳에서 재사용할 수 있습니다.

특히 대규모 환경에서 Prometheus 성능 문제를 해결하는 핵심 기법입니다.

실전 팁

💡 Recording Rules의 네이밍 컨벤션을 따르세요. level:metric:operations 형식으로, 예를 들어 job:api_requests:rate5m은 "job 레벨에서 api_requests 메트릭의 5분 rate"를 의미합니다. 이렇게 하면 규칙의 목적이 명확해집니다.

💡 계층적으로 규칙을 구성하세요. 먼저 세밀한 집계(instance 레벨)를 계산하고, 그 결과를 사용해 더 높은 레벨(job, cluster)을 계산하면 중복 계산을 줄일 수 있습니다. 단, 규칙 간 의존성은 같은 evaluation_interval 내에서만 동작합니다.

💡 Recording Rules도 스토리지를 소비합니다. 불필요하게 많은 레이블을 유지하면 시계열 수가 증가합니다. 집계 시 필요 없는 레이블은 제거하세요.

💡 원본 메트릭의 보관 기간보다 Recording Rules의 결과를 더 오래 보관할 수 있습니다. 예를 들어, 원본은 15일, 집계 결과는 90일 보관하여 장기 트렌드 분석에 활용하세요.

💡 Recording Rules가 실패하면 메트릭이 생성되지 않으므로 Prometheus 로그를 모니터링하세요. 쿼리 문법 오류나 데이터 부재로 인한 실패를 조기에 발견해야 합니다.


6. Alerting Rules

시작하며

여러분이 새벽 3시에 갑자기 서비스 장애로 인한 전화를 받은 경험이 있나요? 사실 그 문제는 한 시간 전부터 조짐이 있었지만, 모니터링 대시보드를 계속 보고 있을 수는 없었기 때문에 늦게 발견한 상황 말이죠.

이런 문제는 수동 모니터링의 한계입니다. 사람이 24시간 대시보드를 주시할 수 없고, 설령 본다 해도 수많은 메트릭 중에서 이상 징후를 즉시 파악하기 어렵습니다.

장애가 발생한 후에야 알게 되면 고객 영향이 커지고 복구 시간이 길어집니다. 바로 이럴 때 필요한 것이 Alerting Rules입니다.

메트릭이 특정 조건을 만족할 때 자동으로 알림을 발생시켜, 문제를 조기에 감지하고 신속하게 대응할 수 있게 합니다.

개요

간단히 말해서, Alerting Rules는 PromQL 쿼리로 조건을 정의하고, 그 조건이 일정 시간 동안 유지되면 알림을 발생시키는 규칙입니다. Prometheus가 주기적으로 규칙을 평가하여 Alertmanager로 알림을 전송합니다.

왜 Alerting Rules가 필요한지 실무 관점에서 설명하자면, 선제적 장애 대응이 가능합니다. 예를 들어, "에러율이 5% 이상 5분간 지속"이라는 규칙을 설정하면 완전한 장애로 확산되기 전에 알림을 받아 조치할 수 있습니다.

또한 비즈니스 임계값(예: 거래액 급감)도 모니터링하여 기술적 장애뿐 아니라 비즈니스 이슈도 감지합니다. 기존에는 특정 시간대에 배치 작업으로 로그를 분석하거나, 외부 모니터링 서비스의 단순한 핑 체크에 의존했다면, Alerting Rules는 실시간으로 복잡한 조건을 평가할 수 있습니다.

메트릭 기반이므로 로그보다 빠르고 정확합니다. Alerting Rules의 핵심 특징은 실시간 평가, for 절을 통한 false positive 방지, 그리고 레이블 기반 라우팅입니다.

이러한 특징들이 의미 있는 알림만 발생시켜 알림 피로도를 줄이고, 적절한 담당자에게 알림을 전달하며, 장애 대응 시간을 단축시킵니다.

코드 예제

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: alerting-rules
  namespace: monitoring
spec:
  groups:
    - name: api_alerts
      interval: 30s
      rules:
        # 높은 에러율 알림
        - alert: HighErrorRate
          expr: |
            (sum by (job) (rate(api_requests_total{status=~"5.."}[5m]))
            /
            sum by (job) (rate(api_requests_total[5m]))) * 100 > 5
          for: 5m  # 5분간 지속되어야 알림 발생
          labels:
            severity: critical  # 알림 심각도
            team: backend
          annotations:
            summary: "High error rate on {{ $labels.job }}"
            description: "{{ $labels.job }} has {{ $value | humanizePercentage }} error rate for 5 minutes"

        # 느린 응답 시간 알림
        - alert: HighLatency
          expr: histogram_quantile(0.95, sum by (job, le) (rate(api_request_duration_seconds_bucket[5m]))) > 2
          for: 10m
          labels:
            severity: warning
            team: backend
          annotations:
            summary: "High latency on {{ $labels.job }}"
            description: "P95 latency is {{ $value }}s (threshold: 2s)"

설명

이것이 하는 일: Alerting Rules는 Prometheus가 주기적으로 PromQL 쿼리를 실행하여 조건을 검사하고, 조건이 충족되면 Alertmanager로 알림을 보냅니다. Alertmanager는 이를 받아서 Slack, 이메일, PagerDuty 등으로 전달합니다.

첫 번째로, HighErrorRate 알림은 에러율이 5%를 초과하는지 확인합니다. expr의 쿼리는 500번대 에러 속도를 전체 요청 속도로 나눈 후 100을 곱해 백분율로 변환하고, 이를 5와 비교합니다.

조건이 true이면 "pending" 상태로 전환됩니다. 그 다음으로, for: 5m 절이 중요합니다.

조건이 true여도 즉시 알림이 발생하지 않고, 5분간 지속적으로 true여야 "firing" 상태로 전환되어 실제 알림이 발송됩니다. 이는 일시적인 스파이크로 인한 오탐(false positive)을 방지합니다.

네트워크 지연으로 순간적으로 에러가 증가했다가 바로 정상화되는 경우를 필터링합니다. labels 섹션에서 severity: critical과 team: backend를 추가합니다.

Alertmanager는 이 레이블을 기반으로 알림을 라우팅합니다. 예를 들어, critical은 PagerDuty로, warning은 Slack으로 보내는 식입니다.

team 레이블로 백엔드 팀에게만 알림을 전달할 수도 있습니다. annotations는 알림 메시지에 표시될 내용입니다.

{{ $labels.job }}은 Go 템플릿 문법으로, 알림을 발생시킨 시계열의 레이블 값을 삽입합니다. {{ $value | humanizePercentage }}는 쿼리 결과 값을 퍼센트 형식으로 표시합니다.

이렇게 하면 "api-server has 7.5% error rate"처럼 구체적인 정보가 포함됩니다. 두 번째 알림인 HighLatency는 P95 레이턴시가 2초를 초과하는지 확인합니다.

for: 10m으로 더 긴 시간을 설정한 이유는, 레이턴시는 일시적으로 증가할 수 있고 즉시 장애로 이어지지 않기 때문입니다. severity: warning으로 설정하여 critical보다 낮은 우선순위로 처리됩니다.

여러분이 Alerting Rules를 사용하면 잠자는 동안에도 시스템이 자동으로 모니터링되고, 문제가 발생하면 즉시 알림을 받을 수 있습니다. 장애를 조기에 감지하여 고객 영향을 최소화하고, 명확한 알림 메시지로 빠르게 원인을 파악하며, 팀별/심각도별로 알림을 분류하여 효율적으로 대응할 수 있습니다.

실전 팁

💡 for 절을 항상 사용하세요. 최소 5분 이상으로 설정하여 일시적인 노이즈를 필터링하세요. critical 알림은 5-10분, warning은 10-30분이 일반적입니다. for를 생략하면 알림 폭풍이 발생할 수 있습니다.

💡 알림은 실제 액션이 필요한 경우에만 발생시키세요. "알아두면 좋은" 정보는 알림이 아닌 대시보드로 표시하세요. 알림 피로도(alert fatigue)는 진짜 장애 알림을 무시하게 만듭니다.

💡 runbook_url 어노테이션을 추가하여 대응 가이드 문서로 링크하세요. 새벽에 알림을 받은 온콜 엔지니어가 즉시 조치 방법을 찾을 수 있게 합니다.

💡 severity 레이블을 일관성 있게 사용하세요. critical(즉시 대응 필요, 고객 영향 있음), warning(조만간 문제될 수 있음), info(참고용) 정도로 구분하세요.

💡 알림 조건은 Recording Rules의 결과를 활용하세요. 복잡한 쿼리를 알림 규칙에 직접 넣으면 평가 시간이 길어져 알림이 지연될 수 있습니다. 미리 계산된 메트릭을 사용하면 평가가 즉시 완료됩니다.


7. Grafana 연동

시작하며

여러분이 Prometheus에 수많은 메트릭을 수집하고 있지만, PromQL 쿼리를 직접 실행해서 숫자로만 확인하는 것이 불편한 경험이 있나요? 시간에 따른 추세를 파악하거나, 여러 메트릭을 비교하거나, 팀원들과 현황을 공유하기 어려운 상황 말이죠.

이런 문제는 시각화 도구가 없을 때 발생합니다. 메트릭은 시계열 데이터이므로 그래프로 표현해야 패턴을 직관적으로 이해할 수 있습니다.

텍스트 기반 쿼리 결과만으로는 장애 발생 시점, 증가 추세, 이상 패턴을 빠르게 파악하기 어렵습니다. 바로 이럴 때 필요한 것이 Grafana입니다.

Prometheus와 완벽하게 통합되는 오픈소스 시각화 플랫폼으로, 메트릭을 다양한 그래프와 대시보드로 표현하여 직관적인 모니터링 환경을 제공합니다.

개요

간단히 말해서, Grafana는 시계열 데이터를 시각화하는 대시보드 플랫폼입니다. Prometheus를 데이터 소스로 연결하고, PromQL 쿼리를 기반으로 다양한 차트와 패널을 구성하여 실시간 대시보드를 만듭니다.

왜 Grafana가 필요한지 실무 관점에서 설명하자면, 운영팀의 시각적 모니터링 허브가 됩니다. 예를 들어, "전체 시스템 상태" 대시보드를 만들어 TV 모니터에 띄워두면 팀원 누구나 한눈에 현황을 파악할 수 있습니다.

또한 고객 미팅에서 서비스 성능 지표를 그래프로 보여줄 수 있고, 장애 발생 시 그래프를 캡처하여 사후 분석(post-mortem)에 활용할 수 있습니다. 기존에는 CLI에서 curl로 Prometheus API를 호출하거나, 웹 UI에서 단순한 그래프만 봤다면, Grafana는 여러 메트릭을 한 화면에 배치하고, 색상과 임계값을 설정하며, 시간 범위를 자유롭게 조정할 수 있습니다.

대시보드를 JSON으로 저장하여 버전 관리하고 팀 간에 공유할 수도 있습니다. Grafana의 핵심 특징은 풍부한 시각화 옵션(라인 차트, 게이지, 히트맵 등), 템플릿 변수를 통한 동적 대시보드, 그리고 알림 기능입니다.

이러한 특징들이 데이터를 아름답고 이해하기 쉬운 형태로 변환하여, 기술팀뿐 아니라 비기술팀도 메트릭을 통해 의사결정을 내릴 수 있게 합니다.

코드 예제

# Grafana 대시보드 JSON 설정 (핵심 부분)
{
  "dashboard": {
    "title": "API Performance Dashboard",
    "panels": [
      {
        "title": "Request Rate",
        "targets": [
          {
            "expr": "sum(rate(api_requests_total[5m])) by (endpoint)",
            "legendFormat": "{{ endpoint }}"
          }
        ],
        "type": "graph",
        "yaxes": [{"format": "reqps"}]
      },
      {
        "title": "Error Rate %",
        "targets": [
          {
            "expr": "sum(rate(api_requests_total{status=~\"5..\"}[5m])) / sum(rate(api_requests_total[5m])) * 100"
          }
        ],
        "type": "gauge",
        "thresholds": "5,10",  # 5% 경고, 10% 위험
        "colors": ["green", "yellow", "red"]
      },
      {
        "title": "P95 Latency",
        "targets": [
          {
            "expr": "histogram_quantile(0.95, sum(rate(api_request_duration_seconds_bucket[5m])) by (le))"
          }
        ],
        "type": "graph",
        "yaxes": [{"format": "s"}]
      }
    ],
    "templating": {
      "list": [
        {
          "name": "namespace",
          "query": "label_values(api_requests_total, namespace)",
          "type": "query"
        }
      ]
    }
  }
}

설명

이것이 하는 일: Grafana 대시보드는 여러 개의 패널(panel)로 구성되며, 각 패널은 PromQL 쿼리를 실행하여 결과를 시각화합니다. 이 예제는 API 성능 모니터링 대시보드의 구조를 보여줍니다.

첫 번째로, "Request Rate" 패널은 엔드포인트별 초당 요청 수를 라인 그래프로 표시합니다. targets 배열에 PromQL 쿼리를 정의하고, legendFormat으로 범례 이름을 설정합니다.

{{ endpoint }}는 각 시계열의 endpoint 레이블 값으로 치환되어, 그래프에 "/api/users", "/api/orders" 같은 범례가 표시됩니다. yaxes의 format: "reqps"는 Y축 단위를 "requests per second"로 표시합니다.

그 다음으로, "Error Rate %" 패널은 게이지(gauge) 타입으로 현재 에러율을 보여줍니다. 게이지는 단일 값을 표시하는 데 적합하며, 시계열 추세보다는 "지금 이 순간"의 상태를 강조합니다.

thresholds: "5,10"은 5%와 10%를 경계로 색상이 변경됨을 의미합니다. 5% 미만은 green, 5-10%는 yellow, 10% 이상은 red로 표시되어 한눈에 위험 수준을 파악할 수 있습니다.

"P95 Latency" 패널은 histogram_quantile로 95번째 백분위수 레이턴시를 그래프로 표시합니다. format: "s"는 초 단위로 표시하며, Grafana가 자동으로 밀리초나 마이크로초로 변환하여 읽기 쉽게 만듭니다.

templating 섹션이 실행되면 대시보드 상단에 드롭다운 변수가 생성됩니다. namespace 변수는 Prometheus에서 api_requests_total 메트릭의 모든 namespace 레이블 값을 쿼리하여 목록을 만듭니다.

사용자가 "production"을 선택하면 모든 패널의 쿼리에 자동으로 {namespace="production"} 필터가 추가됩니다. 이를 통해 하나의 대시보드로 여러 환경(dev, staging, production)을 전환하며 볼 수 있습니다.

여러분이 이 대시보드를 사용하면 API 서비스의 핵심 지표를 한 화면에서 모니터링할 수 있습니다. 요청 속도 증가, 에러율 상승, 레이턴시 증가를 시각적으로 즉시 파악하고, 과거 데이터와 비교하여 트렌드를 분석하며, 팀원들과 동일한 화면을 공유하여 협업할 수 있습니다.

실전 팁

💡 템플릿 변수를 적극 활용하세요. $namespace, $pod 같은 변수를 만들어 하나의 대시보드로 모든 서비스를 볼 수 있게 하면 대시보드 관리 부담이 줄어듭니다. 각 서비스별로 별도 대시보드를 만들지 마세요.

💡 대시보드를 폴더로 구조화하고 태그를 붙이세요. "Infrastructure", "Application", "Business" 폴더로 분류하면 팀원들이 필요한 대시보드를 쉽게 찾을 수 있습니다.

💡 임계값(threshold)을 설정하여 정상/경고/위험 상태를 색상으로 표시하세요. 숫자만 보는 것보다 시각적 신호가 훨씬 효과적입니다. 특히 TV 모니터에 띄울 때 멀리서도 알아볼 수 있습니다.

💡 대시보드를 JSON으로 Export하여 Git에 저장하세요. 인프라스트럭처 as 코드(IaC) 접근법으로 대시보드도 버전 관리하고, 환경 간 복제하며, 리뷰 프로세스를 적용할 수 있습니다.

💡 너무 많은 패널을 한 대시보드에 넣지 마세요. 스크롤이 길어지면 오히려 가독성이 떨어집니다. 핵심 지표만 담은 "Overview" 대시보드와 세부 지표를 담은 "Details" 대시보드를 분리하세요.


8. Node Exporter 활용

시작하며

여러분이 애플리케이션 메트릭은 잘 수집하고 있지만, 정작 서버 자체의 CPU, 메모리, 디스크 상태를 모르는 경험이 있나요? 애플리케이션은 정상인데 서버 디스크가 꽉 차서 로그를 쓰지 못하거나, CPU throttling으로 성능이 저하되는 상황을 늦게 발견한 경우 말이죠.

이런 문제는 호스트 레벨의 시스템 메트릭을 수집하지 않을 때 발생합니다. Kubernetes의 Pod 메트릭만 보면 노드 자체의 리소스 부족이나 하드웨어 문제를 놓칠 수 있습니다.

특히 여러 Pod가 같은 노드에서 실행되면 노드 전체의 리소스 경합을 파악해야 합니다. 바로 이럴 때 필요한 것이 Node Exporter입니다.

Prometheus 생태계의 표준 시스템 메트릭 수집기로, Linux 서버의 CPU, 메모리, 디스크, 네트워크, 파일시스템 등 하드웨어 및 OS 레벨 메트릭을 노출합니다.

개요

간단히 말해서, Node Exporter는 각 노드에서 실행되는 경량 에이전트로, /proc와 /sys 파일시스템에서 시스템 정보를 읽어 Prometheus 형식으로 제공합니다. DaemonSet으로 배포하여 모든 노드에서 자동으로 실행됩니다.

왜 Node Exporter가 필요한지 실무 관점에서 설명하자면, 인프라 레벨의 가시성을 제공합니다. 예를 들어, 특정 노드의 CPU steal time이 높으면 하이퍼바이저 레벨의 문제를 의심할 수 있고, 디스크 I/O wait이 높으면 스토리지 성능 문제를 파악할 수 있습니다.

이런 정보 없이는 애플리케이션이 느린 이유를 찾기 어렵습니다. 기존에는 Nagios 같은 전통적인 모니터링 도구로 각 서버를 개별 관리했다면, Node Exporter는 Kubernetes 네이티브 방식으로 자동 배포되고 Prometheus가 자동으로 수집합니다.

수동 설정 없이 노드가 추가되면 즉시 모니터링이 시작됩니다. Node Exporter의 핵심 특징은 에이전트리스 아키텍처(Pull 방식), 다양한 시스템 메트릭 제공, 그리고 collector 모듈 시스템입니다.

이러한 특징들이 표준화된 방식으로 모든 노드의 상태를 수집하고, 애플리케이션 메트릭과 통합하여 전체적인 시스템 뷰를 제공하며, 하드웨어 문제를 조기에 발견할 수 있게 합니다.

코드 예제

# Node Exporter DaemonSet 배포
apiVersion: apps/v1
kind: DaemonSet  # 모든 노드에 하나씩 Pod 배포
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true  # 호스트 네트워크 사용
      hostPID: true  # 호스트 PID 네임스페이스 접근
      containers:
        - name: node-exporter
          image: prom/node-exporter:latest
          args:
            - --path.procfs=/host/proc  # 호스트의 /proc 마운트
            - --path.sysfs=/host/sys  # 호스트의 /sys 마운트
            - --collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)
          ports:
            - containerPort: 9100  # 메트릭 노출 포트
          volumeMounts:
            - name: proc
              mountPath: /host/proc
              readOnly: true
            - name: sys
              mountPath: /host/sys
              readOnly: true
      volumes:
        - name: proc
          hostPath:
            path: /proc  # 호스트의 /proc를 컨테이너로 마운트
        - name: sys
          hostPath:
            path: /sys

설명

이것이 하는 일: Node Exporter는 Kubernetes의 각 노드에서 하나씩 실행되어, 해당 노드의 하드웨어 및 OS 메트릭을 9100번 포트를 통해 노출합니다. Prometheus는 이를 스크래핑하여 노드 상태를 모니터링합니다.

첫 번째로, DaemonSet을 사용하는 이유는 모든 노드에 자동으로 Pod를 하나씩 배포하기 위함입니다. 노드가 클러스터에 추가되면 자동으로 Node Exporter가 배포되고, 노드가 제거되면 함께 삭제됩니다.

Deployment나 StatefulSet과 달리 DaemonSet은 노드별로 정확히 1개씩만 실행됩니다. 그 다음으로, hostNetwork: true와 hostPID: true 설정이 중요합니다.

Node Exporter는 컨테이너에서 실행되지만, 실제로는 호스트 노드의 정보를 수집해야 합니다. hostNetwork를 사용하면 노드의 네트워크 인터페이스 정보를 볼 수 있고, hostPID를 사용하면 노드에서 실행 중인 모든 프로세스 정보를 볼 수 있습니다.

volumeMounts 섹션에서 /proc와 /sys를 마운트합니다. Linux에서 /proc는 커널과 프로세스 정보를 제공하는 가상 파일시스템이고, /sys는 하드웨어 장치 정보를 제공합니다.

Node Exporter는 이 파일들을 읽어서 CPU 사용률, 메모리 상태, 디스크 I/O, 네트워크 트래픽 등을 계산합니다. readOnly: true로 설정하여 실수로 시스템 파일을 변경하지 않도록 합니다.

args에서 --collector.filesystem.mount-points-exclude를 설정하는 이유는 불필요한 파일시스템을 제외하기 위함입니다. /proc, /sys 같은 가상 파일시스템이나 컨테이너별 마운트는 메트릭으로 수집할 필요가 없으므로 정규식으로 제외합니다.

이렇게 하면 실제 스토리지 볼륨만 모니터링됩니다. Prometheus는 ServiceMonitor나 PodMonitor를 통해 node-exporter Pod의 9100번 포트를 자동 디스커버리합니다.

각 노드에서 node_cpu_seconds_total, node_memory_MemAvailable_bytes, node_disk_io_time_seconds_total 같은 수백 개의 메트릭이 수집되어, PromQL로 "노드별 CPU 사용률", "메모리 부족 위험 노드", "디스크 I/O 병목" 같은 쿼리를 실행할 수 있습니다. 여러분이 Node Exporter를 사용하면 애플리케이션 메트릭과 시스템 메트릭을 통합하여 전체적인 그림을 볼 수 있습니다.

애플리케이션이 느린 이유가 코드 문제인지 인프라 문제인지 즉시 파악할 수 있고, 노드 리소스 부족을 사전에 감지하여 스케일 아웃을 결정하며, 하드웨어 장애 징후를 조기에 발견하여 교체할 수 있습니다.

실전 팁

💡 Node Exporter의 기본 collector는 대부분 활성화되어 있지만, 특정 collector를 비활성화하려면 --no-collector.{name} 플래그를 사용하세요. 예를 들어, NFS를 사용하지 않으면 --no-collector.nfs로 불필요한 메트릭 수집을 줄일 수 있습니다.

💡 hostNetwork를 사용하므로 포트 충돌에 주의하세요. 9100번 포트가 다른 서비스와 겹치면 Node Exporter가 시작하지 못합니다. 필요하면 --web.listen-address로 포트를 변경하세요.

💡 Node Exporter는 텍스트 형식으로 수백 개의 메트릭을 노출합니다. curl로 직접 확인해보세요: curl http://node-ip:9100/metrics. 어떤 메트릭이 있는지 이해하면 더 효과적인 쿼리를 작성할 수 있습니다.

💡 보안을 위해 Node Exporter 포트는 클러스터 내부로만 노출하세요. 외부에서 접근하면 시스템 정보가 유출될 수 있습니다. NetworkPolicy로 Prometheus에서만 접근 가능하도록 제한하세요.

💡 Grafana에서 "Node Exporter Full" 같은 커뮤니티 대시보드를 import하세요. 이미 잘 만들어진 대시보드로 CPU, 메모리, 디스크, 네트워크를 한눈에 볼 수 있고, 대시보드 ID만 입력하면 즉시 사용할 수 있습니다.


#Kubernetes#Prometheus#Monitoring#ServiceMonitor#PromQL#TypeScript

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.