Prometheus + Grafana 모니터링 & Slack 알람 구축

2026. 5. 4. 16:54·Project

AWS 환경에 Prometheus + Grafana 모니터링 & Slack 알람 구축

CloudWatch 기본 지표만으로는 부족했던 모니터링을 Prometheus·Grafana로 강화
Slack 알람과 메트릭 필터링까지 적용한 과정 정리

Prometheus Node Exporter Grafana Cloud Slack Webhook AWS EC2


1. 왜 Prometheus + Grafana인가?

AWS CloudWatch는 기본적인 인스턴스 지표(CPU Utilization, NetworkIn/Out 등)를 제공하지만 메모리 사용률이나 파일시스템 용량 같은 OS 레벨의 상세 지표는 기본 제공하지 않습니다. CloudWatch Agent를 추가 설치하면 수집 자체는 가능하지만 커스텀 대시보드 구성의 유연성이나 PromQL 같은 강력한 쿼리 언어를 활용한 분석에는 한계가 있습니다.

이 프로젝트에서는 CPU·메모리·파일시스템·네트워크 등 세밀한 지표를 초 단위로 수집하고 유연한 대시보드로 시각화하기 위해 Prometheus + Grafana 조합을 선택했습니다.


2. 모니터링 아키텍처

전체 데이터 흐름은 다음과 같습니다.

구성 요소 역할
Node Exporter 각 EC2에서 OS 레벨 메트릭(CPU, 메모리, 디스크, 네트워크)을 HTTP 엔드포인트로 노출
Prometheus Node Exporter의 /metrics 엔드포인트를 주기적으로 scrape하여 시계열 데이터로 저장
Grafana Prometheus를 데이터소스로 연결해 대시보드 패널로 시각화

3. 구축 과정

3-1. Node Exporter 설치

모니터링이 필요한 모든 EC2 인스턴스에 Node Exporter를 설치합니다. 기본 포트는 9100이며 systemd 서비스로 등록하여 인스턴스 재시작 시에도 자동 실행되도록 구성합니다.

# Node Exporter 다운로드 및 설치
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.linux-amd64.tar.gz
tar xvfz node_exporter-1.8.1.linux-amd64.tar.gz
sudo mv node_exporter-1.8.1.linux-amd64/node_exporter /usr/local/bin/

# systemd 서비스 등록
sudo tee /etc/systemd/system/node_exporter.service > /dev/null <<EOF
[Unit]
Description=Node Exporter
After=network.target

[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter

정상 동작 확인은 curl http://localhost:9100/metrics로 메트릭이 출력되는지 확인하면 됩니다.

3-2. Prometheus 설치 및 설정

Prometheus 서버에서 각 Node Exporter를 scrape 대상으로 등록합니다.

# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets:
          - '<WEB_SERVER_1_IP>:9100'
          - '<WEB_SERVER_2_IP>:9100'
          - '<WAS_SERVER_1_IP>:9100'
          - '<WAS_SERVER_2_IP>:9100'

💡 CloudWatch와의 차이
scrape_interval: 15s로 설정하면 15초마다 각 타겟의 메트릭을 수집합니다. CloudWatch 기본 5분 간격과 비교하면 훨씬 세밀한 모니터링이 가능합니다.

3-3. Grafana 대시보드 구성

Grafana에서 Prometheus를 데이터소스로 추가한 뒤 Node Exporter Full 대시보드(Dashboard ID: 1860)를 import하면 CPU, 메모리, 디스크 I/O, 네트워크 트래픽 등을 한눈에 확인할 수 있는 대시보드가 바로 구성됩니다.


4. Slack 실시간 알람 체계 구축

모니터링 지표가 확보되었으니 다음 단계는 이상 징후 발생 시 즉각 알림을 받는 것입니다. 도입 전에는 장애를 인지하기까지 평균 10분 정도 걸렸는데 이를 개선하기 위해 Grafana Alert Rules와 Slack Webhook을 연동했습니다.

4-1. Alert Rule 설정

CPU 사용률이 50%를 초과하면 알람이 발생하도록 PromQL 기반 Alert Rule을 작성합니다.

100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

이 쿼리는 최근 5분간 idle 상태로 보낸 CPU 시간의 초당 변화율을 구한 뒤 100에서 빼서 실제 CPU 사용률(%)을 계산합니다.

  • node_cpu_seconds_total{mode="idle"} — CPU가 idle 상태로 소비한 누적 시간(초)
  • rate(...[5m]) — 최근 5분간 초당 변화율 (0~1 사이 값)
  • avg by (instance) — 멀티코어 환경에서 인스턴스별 평균
  • 100 - (... * 100) — idle 비율을 사용률로 변환

4-2. Notification Template

알람 메시지가 한눈에 들어오도록 커스텀 Go Template을 작성했습니다.

{{ define "cpu_alert" }}
{{ if gt (len .Alerts.Firing) 0 }}

{{ range .Alerts.Firing }}
*Server :* {{ .Labels.instance | reReplaceAll ":.*" "" }}
*Usage :* {{ index .Values "A" | printf "%.1f" }}%
*Threshold :* 50%
*Time :* {{ .StartsAt.Add 32400000000000 | date "2006-01-02 15:04:05" }} KST
{{ end }}
{{ end }}
{{ end }}

템플릿 주요 포인트:

  1. reReplaceAll ":.*" "" — 인스턴스 주소에서 포트 번호(:9100)를 제거하여 IP만 표시합니다.
  2. index .Values "A" — Alert Rule에서 정의한 쿼리(A)의 현재 값을 가져옵니다.
  3. .StartsAt.Add 32400000000000 — UTC 시간에 9시간(나노초 단위)을 더해 KST로 변환합니다. Grafana Alert 시간은 기본 UTC이므로 이 처리가 필요합니다.

4-3. Slack 알람 결과

Alert Rule의 Threshold 조건이 충족되면 Slack 채널에 아래와 같은 메시지가 즉시 전송됩니다.


5. 성과 정리

항목 도입 전 도입 후
수집 가능 지표 CloudWatch 기본 (CPU Utilization 등) CPU, 메모리, 파일시스템, 네트워크 상세 메트릭
수집 간격 5분 (CloudWatch 기본) 15초 (Prometheus scrape_interval)
대시보드 CloudWatch 콘솔 Grafana 커스텀 대시보드
장애 감지 평균 약 10분 5분 이내
알림 체계 없음 (수동 확인) Slack 실시간 알람 자동 발송

6. Grafana Cloud 메트릭 필터링으로 비용 최적화

Prometheus를 로컬에서 운영하면 스토리지 비용만 고려하면 되지만 Grafana Cloud로 Remote Write하는 경우 무료 티어의 Active Series 제한(10,000 시리즈)을 의식해야 합니다. Node Exporter는 기본적으로 수백 개의 메트릭을 노출하는데, 인스턴스 수가 늘어나면 시리즈 수가 금방 한계에 도달합니다.

6-1. 문제 상황

🚨 Rate Limit 초과
EC2 인스턴스 4대에 Node Exporter를 설치하고 모든 메트릭을 Grafana Cloud로 전송하니 무료 티어의 rate limit에 걸려 데이터가 누락되기 시작했습니다. 실제로 대시보드와 알림에 사용하는 메트릭은 전체의 일부에 불과한데, 불필요한 메트릭까지 전부 전송하고 있었던 것이 원인이었습니다.

6-2. 필터링 전략

Prometheus에서 메트릭을 필터링할 수 있는 단계는 크게 세 가지입니다.

  1. relabel_configs — scrape 전 타겟 자체를 선택/제외하는 단계
  2. metric_relabel_configs — scrape 후 로컬 저장 전 메트릭을 필터링하는 단계
  3. write_relabel_configs ← 이번에 사용 — Remote Write 전 외부 전송 대상 메트릭을 필터링하는 단계. 로컬에는 전체 데이터를 유지하면서 비용이 발생하는 구간에서만 필터링합니다.

6-3. 실제 적용 설정

대시보드(Node Exporter Dashboard EN 20201010-StarsL)와 Alert Rule에서 실제로 참조하는 메트릭만 allowlist 방식으로 유지했습니다.

# prometheus.yml — remote_write
remote_write:
  - url: '<GRAFANA_CLOUD_REMOTE_WRITE_URL>'
    basic_auth:
      username: '<USER_ID>'
      password: '<API_KEY>'

    write_relabel_configs:
      - source_labels: [__name__]
        regex: '(node_load.*|node_cpu_seconds_total
                |node_memory_.*|node_filesystem_.*
                |node_disk_.*|node_network_.*_bytes_total
                |node_network_.*_packets_total
                |node_netstat_.*|node_sockstat_.*
                |node_filefd_.*|node_context_switches_total
                |node_boot_time_seconds|node_time_seconds
                |node_uname_info|up)'
        action: keep

✅ allowlist vs denylist
action: keep은 regex에 매칭되는 메트릭만 남기고 나머지를 모두 버리는 allowlist 방식입니다. 반대로 특정 메트릭만 제거하는 action: drop(denylist)도 있지만, 불필요한 메트릭이 추가될 때마다 규칙을 추가해야 하므로 allowlist가 더 안전합니다.

6-4. 타겟 관리 최적화: 단일 Job 통합

필터링과 함께 타겟 관리 방식도 정리했습니다. 처음에는 Web, WAS, Bastion을 별도 job으로 분리했는데 job이 늘어날수록 설정 파일 관리가 복잡해졌습니다. 이를 단일 job으로 통합하고 EC2 태그 기반의 server_type 라벨로 구분하는 방식으로 변경했습니다.

# prometheus.yml — scrape_configs
scrape_configs:
  - job_name: 'Project-Server'
    scrape_interval: 60s

    ec2_sd_configs:
      - region: ap-northeast-2
        port: 9100

    relabel_configs:
      - source_labels: [__meta_ec2_instance_state]
        regex: running
        action: keep
      - source_labels: [__meta_ec2_tag_Environment]
        regex: production
        action: keep
      - source_labels: [__meta_ec2_tag_type]
        regex: (web|was|bastion)
        action: keep
      - source_labels: [__meta_ec2_tag_type]
        target_label: server_type

ec2_sd_configs를 사용하면 Auto Scaling으로 인스턴스가 추가/제거될 때 static_configs를 수동으로 수정할 필요 없이 자동으로 타겟이 갱신됩니다. relabel_configs로 실행 중인 Production 인스턴스만 scrape 대상에 포함시키고, EC2 태그의 type 값을 server_type 라벨로 변환하여 Grafana에서 서버 유형별 필터링이 가능하도록 구성했습니다.

6-5. 필터링 성과

항목 필터링 전 필터링 후
전송 메트릭 Node Exporter 전체 (수백 개) 대시보드·알림 필수 메트릭만
감소율 — 약 85% 감소
Rate Limit 초과 → 데이터 누락 무료 티어 내 안정 운영
로컬 Prometheus 전체 메트릭 유지 전체 메트릭 유지 (영향 없음)

마무리

Prometheus + Grafana 조합은 AWS 환경에서 CloudWatch를 보완하는 강력한 모니터링 스택입니다. Node Exporter를 통해 OS 레벨의 상세 지표를 확보하고 Grafana의 Alert Rules + Slack Webhook으로 실시간 알림까지 구성하면 운영 가시성과 장애 대응 속도를 크게 끌어올릴 수 있습니다.

다만 Grafana Cloud 같은 SaaS 기반 백엔드를 사용할 때는 비용과 rate limit을 반드시 고려해야 합니다. write_relabel_configs로 전송 메트릭을 선별하고 ec2_sd_configs로 타겟 관리를 자동화하면 비용을 통제하면서도 필요한 가시성은 유지할 수 있습니다.

 

'Project' 카테고리의 다른 글

AWS CUR 기반 비용 시각화 파이프라인 구현  (0) 2026.05.04
'Project' 카테고리의 다른 글
  • AWS CUR 기반 비용 시각화 파이프라인 구현
PARK SEJIN
PARK SEJIN
클라우드 인프라를 직접 설계하고 구축하며 배운 것들을 기록하는 블로그
  • PARK SEJIN
    CloudOps Archive
    PARK SEJIN
  • 전체
    오늘
    어제
    • 분류 전체보기 (2) N
      • Project (2) N
      • Study (0)
  • 블로그 메뉴

    • 홈
    • 태그
  • 인기 글

  • 태그

    Prometheus
    Grafana
    eks
    EC2
    slack
    AWS
  • 최근 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.6
PARK SEJIN
Prometheus + Grafana 모니터링 & Slack 알람 구축
상단으로

티스토리툴바