빙응의 공부 블로그

[+/KM] AWS EC2에서 Prometheus와 Grafana로 실시간 시스템 상태 시각화하기 본문

Project/PlusKM

[+/KM] AWS EC2에서 Prometheus와 Grafana로 실시간 시스템 상태 시각화하기

빙응이 2025. 6. 15. 23:40

📝배경

저번 포스팅에서는 Logback을 이용한 로그 저장을 다뤘습니다. 덕분에 애플리케이션 내부에서 발생하는 이벤트들을 효율적으로 기록할 수 있게 되었죠. 하지만 로그를 열심히 쌓는 와중에 한 가지 불편한 점이 생겼습니다. 바로 제가 서비스를 올린 EC2 인스턴스의 상태와 현재 사용률을 파악하기 힘들다는 점이었습니다.

AWS EC2 모니터링

인스턴스의 CPU 사용량, 메모리 점유율, 디스크 I/O 같은 핵심 지표들을 실시간으로 파악하기 어려웠습니다. 결국 인스턴스에 문제가 생겨도 "왜 느려졌지?", "혹시 서버가 다운되지는 않을까?" 하는 불안감 속에서 CloudWatch 기본 지표만으로는 답답함을 느꼈습니다. 그렇기에 저는 이 불편함을 개선해야 한다는 필요성을 절감했고, 다양한 모니터링 툴들을 찾아 나서게 되었습니다.

 

 

📝Prometheus VS InfluxDB

탐색 과정에서  대표적인 시계열 데이터베이스이자 모니터링 솔루션인 PrometheusInfluxDB를 선정하였습니다.

두 도구 모두 메트릭 수집 및 저장, 시각화 도구(Grafana)와의 연동이 가능하다는 공통점이 있었지만, 몇 가지 중요한 차이점이 있었습니다.

 

✅Prometheus vs InfluxDB: 어떤 선택이 나에게 적합할까?

구분 Prometheus InfluxDB
핵심 목적 모니터링 시스템에 특화된 시계열 데이터베이스 범용 시계열 데이터베이스
수집 방식 Pull 방식: Prometheus 서버가 타겟에서 메트릭을 주기적으로 가져옴 Push 방식: 클라이언트가 InfluxDB로 메트릭을 전송
쿼리 언어 PromQL: 강력하고 유연한 모니터링 전용 쿼리 언어 InfluxQL (SQL 유사), Flux (스크립트 언어)
확장성/아키텍처 단일 서버 위주, 클러스터링은 복잡 (Federation, M3DB 등) 클러스터링 지원 (엔터프라이즈 버전)

 

제가 단일 EC2 인스턴스에서 애플리케이션과 OS 레벨의 상세 지표를 모니터링하고 시각화하는 것을 주목적으로 두고 있기 때문에, 두 가지 핵심 이유로 Prometheus를 선택했습니다.

 

첫째, Prometheus의 Pull 방식은 애플리케이션 서버를 변경하지 않고도 Prometheus가 직접 메트릭을 수집하기 때문에, 애플리케이션 코드를 수정하거나 추가 작업 없이도 시스템 모니터링을 시작할 수 있습니다.
이는 단일 EC2 인스턴스에서 여러 애플리케이션을 운영하거나 시스템 레벨의 메트릭을 빠르게 확인하고 싶을 때 매우 유리합니다.

 

둘째, Prometheus는 비교적 가벼운 리소스 요구량과 효율적인 데이터 관리 덕분에, 저사양 EC2 인스턴스에서도 안정적인 모니터링이 가능합니다.
반면, InfluxDB는 대규모 데이터 처리와 복잡한 클러스터링을 위해 설계된 경우가 많아 메모리와 CPU 자원을 많이 소모할 수 있습니다.
따라서 AWS 프리티어 t3.micro 환경에서는 상대적으로 가벼운 Prometheus가 더 적합하다고 판단했습니다. 물론, Prometheus는 장기간 대량 데이터를 저장할 경우 디스크 사용량이 많아질 수 있지만, 저의 주요 목표는 현재 서비스 상태를 실시간으로 파악하고 단기 문제를 빠르게 진단하는 것이기 때문에, 과거 수년 치 데이터를 보관할 필요는 없습니다.

 


 

📝 스프링 부트 애플리케이션 서버 모니터링: Actuator로 메트릭 노출하기

Prometheus가 우리의 EC2 인스턴스에서 메트릭을 '가져오려면' (Pull 방식), 먼저 모니터링 대상인 스프링 부트 애플리케이션이 자신의 상태와 성능 지표들을 외부에 노출할 준비가 되어 있어야 합니다.  저희가 첫 번째로 할 것은 바로 이 스프링 부트 애플리케이션 서버의 모니터링 설정입니다.

이 과정을 통해 애플리케이션의 내부 상태(건강, 활성화 여부 등)와 핵심 메트릭(CPU, 메모리 사용량, HTTP 요청 처리 시간, JVM 상태 등)을 쉽게 확인할 수 있는 엔드포인트를 활성화할 것입니다

 

✅ Spring Boot Actuator 설정하기

Spring Boot Actuator는 스프링 부트 애플리케이션의 운영과 모니터링을 쉽게 할 수 있도록 도와주는 강력한 기능 모음입니다. 복잡한 코드를 추가할 필요 없이, 애플리케이션의 내부 상태, 메트릭, 헬스 체크, 환경 정보 등 다양한 운영 정보를 HTTP 엔드포인트(API) 형태로 외부에 노출해 줍니다. 

 

Actuator를 설정하는 방법은 매우 간단합니다. build.gradle 파일에 다음 의존성을 추가하기만 하면 됩니다.

implementation 'org.springframework.boot:spring-boot-starter-actuator'

 

 

이렇게 의존성을 추가하고 애플리케이션을 재시작하면, /actuator/health, /actuator/info 등 기본적인 엔드포인트들이 자동으로 활성화됩니다.

 

 

 ✅ Prometheus가 이해할 수 있는 형식으로 메트릭 노출하기

우리는 Prometheus가 이 정보를 효율적으로 수집할 수 있도록 Prometheus 전용 형식으로 메트릭을 노출해야 합니다. 여기서 Micrometer 라이브러리와 micrometer-registry-prometheus 의존성이 중요한 역할을 합니다.

 

Micrometer는 다양한 모니터링 시스템(Prometheus, InfluxDB, CloudWatch 등)에 메트릭을 전송할 수 있도록 돕는 파사드(Facade) 계층 라이브러리입니다.

 

이를 위해 다음 의존성을 추가해줍니다.

implementation 'io.micrometer:micrometer-registry-prometheus'

 

✅ Prometheus 엔드포인트 활성화: application.yml 설정

이제 마지막 단계로, Prometheus가 메트릭을 가져갈 수 있도록 /actuator/prometheus 엔드포인트를 명시적으로 활성화해줘야 합니다. 기본적으로 모든 Actuator 엔드포인트가 외부로 노출되는 것은 아니며, 보안상의 이유로 필요한 엔드포인트만 선택적으로 활성화하는 것이 좋습니다.

 

src/main/resources/application.yml 파일에 다음 구문을 추가해줍니다.

management:
  endpoints:
    web:
      exposure:
        # 외부에 노출할 Actuator 엔드포인트 목록
        # prometheus: Prometheus가 메트릭을 가져갈 엔드포인트
        # health: 애플리케이션의 건강 상태를 확인하는 엔드포인트 (기본 활성화되어 있지만 명시)
        # info: 애플리케이션 빌드 정보 등을 확인하는 엔드포인트
        include: prometheus, health, info 
  endpoint:
    prometheus:
      # Prometheus 엔드포인트를 활성화합니다.
      enabled: true

 

이제 스프링 부트 애플리케이션은 Prometheus가 수집할 준비를 마쳤습니다. 다음 단계에서는 EC2 서버 설정과 모니터링 서버 설정에 대해 알아봅시다. 


📝 EC2 서버 모니터링 : Node Exporter로 메트릭 노출하기 

이전 단계에서 스프링 부트 애플리케이션의 내부 상태와 메트릭을 /actuator/prometheus 엔드포인트를 통해 노출하는 방법을 살펴보았습니다. 이제 우리가 애플리케이션을 구동하고 있는 EC2 인스턴스 자체의 건강 상태를 모니터링할 차례입니다. 아무리 애플리케이션이 건강해도, 그 기반이 되는 서버 인스턴스에 문제가 생기면 서비스는 중단될 수밖에 없으니까요.

Prometheus가 EC2 서버의 CPU 사용량, 메모리 사용량, 디스크 I/O, 네트워크 트래픽 등 OS 레벨의 상세 메트릭을 수집하려면, EC2 인스턴스에도 애플리케이션처럼 자신의 메트릭을 Prometheus가 가져갈 수 있는 형태로 노출해 줄 도구가 필요합니다

 

✅ Node Exporter 설정하기

Prometheus 생태계에서 이러한 역할을 담당하는 것이 바로 Node Exporter입니다. Node Exporter는 Linux 및 Unix 시스템의 하드웨어 및 OS 레벨 메트릭을 수집하여 Prometheus가 스크랩할 수 있는 형식으로 노출해 주는 에이전트입니다.

 

저희는 EC2 인스턴스에 Node Exporter를 직접 설치하는 대신, Docker 컨테이너로 쉽고 간편하게 배포할 것입니다. Docker를 사용하면 의존성 관리나 환경 설정의 복잡성을 크게 줄일 수 있습니다.

 

1. Node Exporter Docker 이미지 다운로드

먼저 EC2 인스턴스에 SSH로 접속하여 Node Exporter Docker 이미지를 다운로드합니다.

docker pull prom/node-exporter

 

2. Node Exporter 컨테이너 실행

이제 다운로드한 이미지로 Node Exporter 컨테이너를 실행합니다.

docker run --name node-exporter -d -p 9100:9100 prom/node-exporter

 

3. EC2 보안 그룹(Security Group) 설정: 9100번 포트 허용

Node Exporter는 9100번 포트를 통해 메트릭을 외부에 노출합니다. Prometheus 서버가 이 메트릭을 스크랩하려면, EC2 인스턴스의 보안 그룹에서 9100번 포트에 대한 인바운드(Inbound) 규칙을 허용해야 합니다.

 


해당 설정들이 끝나고 [서버의 도메인]:9100/metrics로 접속해서 다음과 같이 나오면 성공입니다.

 


📝Prometheus 모니터링 서버 개설

이제 스프링 부트 애플리케이션과 EC2 인스턴스 모두 Prometheus가 메트릭을 수집할 준비를 마쳤습니다. 이제 이 메트릭들을 실제로 수집하고 저장할 Prometheus 모니터링 서버를 개설할 차례입니다. 여기서 한 가지 중요한 질문이 생깁니다. "모니터링 서버도 애플리케이션이나 Node Exporter처럼 같은 EC2 인스턴스에 설치하면 안 될까?"

 

원칙적으로, 모니터링 서버는 모니터링 대상과는 별도의 인스턴스에 개설하는 것이 모범 사례입니다. 

  • 치명적인 오류 발생 시 가시성 확보: 만약 모니터링 대상 서버(예: 우리의 애플리케이션 서버)에 치명적인 오류가 발생하여 서버 자체가 다운되거나 응답 불능 상태가 되었을 때, 같은 서버에 모니터링 시스템까지 함께 설치되어 있다면 해당 서버의 상태를 외부에서 확인할 방법이 사라집니다. 

 

이러한 이유로 저는 모니터링의 핵심 원칙을 따르고자 새로운 EC2 인스턴스를 생성하여 Prometheus 서버를 배포하기로 결정했습니다. 기존 애플리케이션 서버와 동일한 규격인 t3.micro 인스턴스를 사용합니다.  Prometheus 서버도 Docker를 활용하여 간편하게 배포할 예정입니다

 

✅ Prometheus 서버 설정 파일(prometheus.yml) 작성

이제 Prometheus가 어떤 대상을 모니터링할지 알려주는 설정 파일을 작성해야 합니다. prometheus.yml 파일은 Prometheus의 핵심 설정 파일로, 메트릭을 스크랩할 대상(targets)을 정의합니다.

 

global:
  scrape_interval: 10s
  evaluation_interval: 10s
scrape_configs:
  - job_name: 'spring-boot-server'
    metrics_path: /actuator/prometheus
    static_configs:
      - targets: ['서버 도메인']

  - job_name: 'ec2-server'
    metrics_path: /metrics
    static_configs:
      - targets: ['서버 도메인:9100']

이 설정 파일은 새로 생성된 Prometheus 서버가 spring-boot-server와 ec2-server라는 두 가지 작업(job)을 통해 각각 스프링 부트 애플리케이션과 Node Exporter로부터 10초마다 메트릭을 스크랩하도록 지시합니다. targets에는 모니터링 대상 서버들의 공인 IP나 도메인, 그리고 해당 포트를 정확히 입력해야 합니다.

 

Docker 이미지 가져오기

먼저, Prometheus와 Grafana 컨테이너를 실행할 Docker 이미지를 미리 다운로드해 둡니다.

docker pull prom/prometheus
docker pull grafana/grafana

 

prom/prometheus는 우리의 모니터링 데이터를 수집하고 저장하는 Prometheus 서버를 위한 이미지이며, grafana/grafana는 수집된 데이터를 직관적인 대시보드로 시각화해 줄 Grafana를 위한 이미지입니다. Prometheus 단독으로도 기본적인 메트릭 확인은 가능하지만, 데이터 시각화와 분석을 위해서는 Grafana와 함께 사용하는 것이 일반적이며, 가독성 측면에서도 압도적으로 유리합니다

 

Docker Compose 설정 파일 (docker-compose.monitoring.yml) 작성

이제 이 두 이미지를 컨테이너로 편하게 사용하고 서로 연동하기 위해 docker-compose.monitoring.yml 파일을 아래와 같이 작성합니다. 이 파일은 Prometheus 서버를 설치할 EC2 인스턴스에 생성합니다.

 

version: '3.8' 

services:
  prometheus:
    image: prom/prometheus
    container_name: prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro 
      - ./prometheus_data:/prometheus
    ports:
      - "9090:9090" 
    command:
      - "--web.enable-lifecycle"
    restart: always
    networks:
      - promnet 
    user: root

  grafana:
    image: grafana/grafana
    container_name: grafana
    volumes:
      # Grafana 
      - ./grafana_data:/var/lib/grafana 
    restart: always 
    networks:
      - promnet 
    ports:
      - "3030:3000"
    user: root 

networks:
  promnet:
    driver: bridge

 

보안 그룹(Security Group) 설정: 포트 허용

Prometheus와 Grafana UI에 외부에서 접근하려면, Prometheus 서버가 설치된 EC2 인스턴스의 보안 그룹에서 해당 포트들에 대한 인바운드(Inbound) 규칙을 허용해야 합니다.

  • 사용자 지정 TCP Port : 9090 
  • 사용자 지정 TCP Port : 3030

컨테이너 실행하기

docker-compose.monitoring.yml 파일을 작성하셨다면, 해당 파일이 있는 디렉토리에서 아래 명령어를 실행하여 Prometheus와 Grafana 컨테이너를 백그라운드로 실행합니다.

sudo docker compose -f docker-compose.monitoring.yml up -d

 

📝 Prometheus, Grafana 작동 확인하기

이제 필요한 모든 설정이 끝났습니다. 다음 단계에서는 설정된 Prometheus에 접속하여 실제로 메트릭이 수집되는지 확인하고, Grafana를 구축하는 방법을 알아보겠습니다.

 

1. Prometheus UI 접속 및 메트릭 수집 확인

먼저 웹 브라우저를 열고 http://[Prometheus 서버 IP]:9090 에 접속하여 Prometheus 웹 UI에 접근합니다.

그리고 Status의 Target health를 두르면 다음과 같이 나옵니다.

 

 

2. Grafana UI 접속 및 데이터 소스 추가

다음으로 Grafana에 접속하여 Prometheus를 데이터 소스로 추가하고 대시보드를 구축해 보겠습니다.

웹 브라우저를 열고 http://[모니터링 서버 IP]:3030 에 접속합니다. 

  • 초기 로그인: Grafana의 기본 로그인 정보는 다음과 같습니다.
    • Username: admin
    • Password: admin
    • 최초 로그인 시 비밀번호 변경을 요청할 수 있습니다. 보안을 위해 강력한 비밀번호로 변경하는 것을 권장합니다.

로그인 후, 왼쪽 메뉴에서 "Connections" 를 클릭한 후 "Data sources"를 선택합니다.

다음 화면에서 "Create Dashboards"를 클릭합니다.

해당 화면에서 "Import dashboard"를 눌러줍니다.

 

다음과 같은 화면이 나오면 해당 사진처럼 1860을 작성하고 Load 해줍니다.

그러면 다음과 같은 화면이 나올텐데 해당 사진처럼 Prometheus를 추가해줘야 합니다.

저는 이미 설정해서 있는 것이며 처음할때는 아래 사진으로 넘어갑니다. 

해당 사진에서 Prometheus를 선택하고 

위 창이 뜨면 Connection에 http://[모니터링 서버 IP]:9090을 입력하면 됩니다.  그 다음 맨밑으로 내려 save를 해주면 됩니다.

 

 

이제 EC2 서버 모니터링이 보입니다. 이제 스프링 애플리케이션 서버 모니터링도 추가하겠습니다.

 

EC2 서버와 다를거 없이 Load 값만 14430으로 해주시면 됩니다. 

 

 


📝결론

지금까지 AWS EC2 환경에서 Prometheus와 Grafana를 활용해 Spring Boot 애플리케이션과 OS 레벨의 상세 지표를 모니터링하고 시각화하는 과정을 단계별로 살펴보았습니다. 단순한 로그 기록을 넘어서, 실시간 메트릭 기반 모니터링의 필요성을 직접 체감하고 이를 구축해본 경험은 매우 뜻깊었습니다.

 

이번 모니터링 시스템 구축 경험은 단순히 새로운 기술 스택을 익히는 것을 넘어, 서비스 운영 안정성에 대한 개발자의 책임감과 문제 해결력을 키울 수 있었던 기회였습니다. 특히, 실시간 지표를 통해 서비스의 상태를 빠르게 파악하고 대응하는 능력의 중요성을 깊이 이해하게 되었습니다.

 

앞으로도 지속적인 학습과 실전 적용을 통해, 더 견고하고 효율적인 시스템을 설계·운영할 수 있는 개발자로 성장해 나가겠습니다.
다음 포스팅에서는 로그 역시 메트릭처럼 수집·시각화하는 방법에 대해 다뤄보겠습니다.