Monitoring/Prometheus

Prometheus > 시작하기

Krevis 2024. 6. 16. 15:28

한줄 소개

https://prometheus.io/docs/introduction/overview/

 

최초 SoundCloud에서 만들어진, 시스템 모니터링과 경보(Alert) 도구 모음이다

 

 

Docker Compose로 Prometheus 실행

https://hub.docker.com/r/prom/prometheus

 

mkdir data

 

vi compose.yml

services:
  some-prometheus:
    container_name: some-prometheus
    image: prom/prometheus:v2.52.0
    ports:
      - 9090:9090
    volumes:
      - ./data:/prometheus

 

docker compose up

 

컨테이너 내부에서 프로메테우스가 사용하는 폴더를 확인해보자

docker exec -it some-prometheus /bin/sh

 

tree /prometheus

/prometheus
├── chunks_head
├── lock
├── queries.active
└── wal
    └── 00000000

2 directories, 3 files

 

tree /usr/share/prometheus

/usr/share/prometheus
├── console_libraries
│   ├── menu.lib
│   └── prom.lib
└── consoles
    ├── index.html.example
    ├── node-cpu.html
    ├── node-disk.html
    ├── node-overview.html
    ├── node.html
    ├── prometheus-overview.html
    └── prometheus.html

2 directories, 9 files

 

tree /etc/prometheus

/etc/prometheus
├── console_libraries -> /usr/share/prometheus/console_libraries
├── consoles -> /usr/share/prometheus/consoles/
└── prometheus.yml

0 directories, 3 files

 

cat /etc/prometheus/prometheus.yml

# my global config
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

 

 

Prometheus 둘러보기

웹 브라우저에서 http://localhost:9090로 진입한다

메뉴 > Status > Command-Line Flags

프로메테우스 실행 시의 옵션 노출

메뉴 > Status > Configuration

prometheus.yml 설정값을 볼 수 있다

메뉴 > Status > Targets

prometheus (1/1 up)이라는 항목이 보일 것이다. show more 버튼을 클릭해보자. 표 하나가 보여진다

 

http://localhost:9090/metrics 라는 종단점(Endpoint)의 상태는 UP이고 키="값" 형태의 레이블들을 가졌고, 수집(Scrape) 시간 정보, 에러 등의 정보를 확인할 수 있다

 

종단점 링크를 클릭해보면 화면에 보여진 localhost가 아닌 http://c94672ef60b1:9090/metrics 이런 URI로 이동한다. 왜 그런지는 모르겠다. 맥에서 Rancher Desktop으로 도커를 사용할 때의 이슈인 거 같다. 혹시 몰라 네트워크 모드를 host로 변경해봤는데 이 때는 http://lima-rancher-desktop:9090/metrics로 접속되었다

 

직접 http://localhost:9090/metrics를 입력해서 진입하면 정상적으로 아래와 같은 내용이 출력된다

# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 3.6707e-05
go_gc_duration_seconds{quantile="0.25"} 0.000121667
go_gc_duration_seconds{quantile="0.5"} 0.000586749
go_gc_duration_seconds{quantile="0.75"} 0.002301834
go_gc_duration_seconds{quantile="1"} 0.027133833
go_gc_duration_seconds_sum 0.096830956
go_gc_duration_seconds_count 53
..

 

이 내용은 무엇일까?

 

프로메테우스는 Target에 해당하는 대상의 HTTP 종단점으로부터 Metric을 주기적으로 Polling(Pulling)하는 방식으로 데이터를 수집한다

 

https://prometheus.io/docs/prometheus/latest/getting_started/#configuring-prometheus-to-monitor-itself

프로메테우스 그 자체도 같은 방식으로 데이터를 노출하기 때문에, 자신의 Health를 수집하고 모니터링할 수 있다. 그렇기 때문에 위와 같이 프로메테우스에 대한 수집 정보가 노출되는 것이다

 

Metric이란 수집되는 시계열 데이터를 의미하며, 시계열(Time series)은 일정 시간 간격으로 배치된 데이터들의 수열을 말한다

 

 

호스트 OS에서 prometheus.yml 설정할 수 있게 하기

프로메테우스 설정도 도커 컨테이너 외부에서 관리되도록 해야한다

 

작업 폴더에서 prometheus.yml 파일을 만들어 도커 볼륨을 통해 컨테이너 내부에 배포되도록 해야한다

 

vi prometheus.yml

앞에서 출력했던 컨테이너 기본 설정을 복붙한다

 

보시다시피 수집 설정에서 잡 이름이 prometheus이고 기본 스킴인 http, 기본 메트릭 경로인 /metrics, 기본 포트인 9090을 사용하고 있다

..
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

 

 

vi compose.yml

services:
  some-prometheus:
    container_name: some-prometheus
    image: prom/prometheus:v2.52.0
    ports:
      - 9090:9090
    volumes:
      - ./data:/prometheus
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

 

docker compose down

docker compose up

 

 

Node Exporter 타겟 추가하기

이제 실용적인 타겟을 추가해보며 프로메테우스를 좀 더 알아보도록 하자

 

노드 익스포터는 호스트 시스템을 모니터링하기 위해 설계되었다. 이로 인해 프로메테우스가 동작하는 호스트의 하드웨어와 커널 관련 메트릭을 수집할 수 있다

Docker Compose로 노드 익스포터 실행

https://hub.docker.com/r/prom/node-exporter

 

컨테이너로 실행하면 추가적으로 해야할 작업들이 꽤 있어보여서 추후에 시도해보도록 하겠다

노드 익스포터 설치 후 OS 서비스로 등록

https://prometheus.io/docs/guides/node-exporter/

 

https://prometheus.io/download/#node_exporter

맥 환경이기 때문에 darwin OS 바이너리를 다운로드한다. (터미널에서 uname을 치면 Darwin이 출력된다)

 

wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.darwin-amd64.tar.gz

tar xvfz node_exporter-1.8.1.darwin-amd64.tar.gz

ln -s node_exporter-1.8.1.darwin-amd64 node-exporter

 

cd node-exporter

./node_exporter

9100번 포트로 노드 익스포터가 실행된다

 

curl http://localhost:9100/metrics

접두사 node_인 항목들이 시스템 메트릭이다

 

OS 서비스로 등록하는 것은 추후에 작성하겠다

Prometheus 타겟에 Node Exporter 추가하기

vi prometheus.yml

..
scrape_configs
..
  - job_name: node-exporter
    static_configs:
      - targets: ["localhost:9100"]

 

docker compose down

docker compose up

 

Targets 화면에 node-exporter 항목이 노출되는 것을 확인할 수 있는데, 상태가 UP이 되지 않는다. 이유는 컨테이너 안에서 프로메테우스는 localhost로 접근이 가능하나, 노드 익스포터는 컨테이너 밖인 호스트 OS에서 실행되기 때문이다

 

컨테이너에서 호스트 포트로 접근할 수 있어야 하는데 host.docker.internal이라는 도메인을 사용하면 접근 가능하다

https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host

 

vi prometheus.yml

..
scrape_configs
..
  - job_name: node-exporter
    static_configs:
      - targets: ["host.docker.internal:9100"]

 

docker compose down

docker compose up

 

이제 상태가 UP이 되는 것을 확인할 수 있다

 

 

Expression browser를 통해 노드 익스포터 메트릭 살펴보기

Graph 메뉴에 진입한다

 

Expression 입력 폼에 타이핑을 하면 자동완성이 된다. Execute 버튼 왼쪽 버튼을 눌러도 된다

 

이곳에서 수집된 메트릭에 대해서 입맛대로 질의를 할 수 있다

 

메모리 사용량을 확인해보자. 단위는 Bytes다

메모리 전체 크기: node_memory_total_bytes

사용 중인 메모리 크기: node_memory_active_bytes

여유 메모리 크기: node_memory_free_bytes

 

메모리 사용률을 확인해보고 싶다면 아래와 같은 식을 사용하면 된다

node_memory_active_bytes / node_memory_total_bytes * 100

 

 

Spring Boot 애플리케이션의 메트릭을 프로메테우스에 맞게 노출

스프링 부트의 Actuator 기능을 사용하면 HTTP 종단점으로부터 메트릭을 수집할 수 있다

https://docs.spring.io/spring-boot/reference/actuator/index.html

 

액추에이터의 metrics 종단점을 노출시키면 현재 애플리케이션의 메트릭 정보를 볼 수 있다

 

application.yml

management:
  endpoints:
    enabled-by-default: false
    web:
      exposure:
        include: "metrics"
  endpoint:
    metrics.enabled: true

위와 같이 설정하고 애플리케이션을 시작한다

 

아래 종단점으로 메트릭 목록을 확인할 수 있다

http://localhost:8080/actuator/metrics

{
  "names": [
    "application.ready.time",
    "application.started.time",
    "disk.free",
    "disk.total",
    "executor.active",
    "executor.completed",
    "executor.pool.core",
    "executor.pool.max",
    "executor.pool.size",
    "executor.queue.remaining",
    "executor.queued",
    "http.server.requests.active",
    "jvm.buffer.count",
    "jvm.buffer.memory.used",
    "jvm.buffer.total.capacity",
    "jvm.classes.loaded",
    "jvm.classes.unloaded",
    "jvm.compilation.time",
    "jvm.gc.live.data.size",
    "jvm.gc.max.data.size",
    "jvm.gc.memory.allocated",
    "jvm.gc.memory.promoted",
    "jvm.gc.overhead",
    "jvm.info",
    "jvm.memory.committed",
    "jvm.memory.max",
    "jvm.memory.usage.after.gc",
    "jvm.memory.used",
    "jvm.threads.daemon",
    "jvm.threads.live",
    "jvm.threads.peak",
    "jvm.threads.started",
    "jvm.threads.states",
    "logback.events",
    "process.cpu.time",
    "process.cpu.usage",
    "process.files.max",
    "process.files.open",
    "process.start.time",
    "process.uptime",
    "system.cpu.count",
    "system.cpu.usage",
    "system.load.average.1m",
    "tomcat.sessions.active.current",
    "tomcat.sessions.active.max",
    "tomcat.sessions.alive.max",
    "tomcat.sessions.created",
    "tomcat.sessions.expired",
    "tomcat.sessions.rejected"
  ]
}

 

위 메트릭 이름 중 하나를 URI에 추가하면 상세 정보를 확인할 수 있다

 

http://localhost:8080/actuator/metrics/jvm.memory.used

 

{
  "name": "jvm.memory.used",
  "description": "The amount of used memory",
  "baseUnit": "bytes",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 85360080
    }
  ],
  "availableTags": [
    {
      "tag": "area",
      "values": [
        "heap",
        "nonheap"
      ]
    },
    {
      "tag": "id",
      "values": [
        "G1 Survivor Space",
        "Compressed Class Space",
        "Metaspace",
        "CodeCache",
        "G1 Old Gen",
        "G1 Eden Space"
      ]
    }
  ]
}

 

여기서 문제가 하나 있는데, 이 메트릭들의 형식은 프로메테우스가 처리하는 형식이 아니란 것이다. 결국 프로메테우스가 원하는 형식으로 제공을 해야하는데 생각만해도 귀찮다

 

이럴 때 Micrometer를 이용하면 모니터링 도구 변경에 유연해진다. 마이크로미터는 마치 로깅 계의 SLF4J와 같은 Fasade다

  • 마이크로미터가 정한 표준 형식으로 메트릭을 전달하고
    • 스프링 부트 액추에이터가 제공하는 종단점 중 /actuator/prometheus 사용
  • 모니터링 도구에 맞는 구현체를 선택하면 끝이다
    • micrometer-registry-prometheus 의존성 사용

 

위 예제를 위해 프로젝트 하나를 만들어 두었다

https://github.com/venzersiz/learn-spring-boot-actuator

 

 

프로메테우스에서 스프링 부트 애플리케이션의 메트릭 수집

vi prometheus.yml

..
  - job_name: spring-boot-application
    static_configs:
      - targets: ["host.docker.internal:8080"]
    metrics_path: /actuator/prometheus

 

 

기존 설정에는 없던 metrics_path 설정이 있는데, 기본적으로 metrics_path는 /metrics로 되어 있어 수집되지 않기 때문이다

 

docker compose down

docker compose up

 

Targets 화면으로 가면 정상적으로 노출이 된다

 

Graph 화면에서 JVM의 Metaspace 크기를 확인해보자

jvm_memory_used_bytes

jvm_memory_used_bytes{id="Metaspace"}

 

 

참고