Post

[CICD] Node-exporter, Promtail 운영서버 모니터링 구축하기

아키텍처

이전 글 에서 개발서버에 대한 모니터링 시스템을 구축했었다. 이번에는 운영서버에 대한 모니터링 시스템을 구축해볼려고 한다. 이전 글에서 설명했던 부분은 짧게 설명하고 넘어가겠다.

이미지

개발서버와 모니터링서버는 비용상의 문제로 같은 서버에 구축되어 있다. 편의상 통합해서 개발서버라고 부르겠다. 그리고 개발서버는 EC2 프리티어로 돌아가며, 운영서버는 GCP 에서 무료 크레딧을 이용해 운영되고 있다. 이전 개발서버에서는 모니터링 시스템 전부를 구축했지만, 운영 서버에서는 단순히 로그와 메트릭을 수집해서 개발서버에 구축된 모니터링 시스템에 데이터를 보내주기만 하면된다. 그럼 개발서버에서 운영서버에서 받은 로그와 메트릭을 관리하고 시각화 및 알람을 보내도록 설정한다. 이렇게함으로써 운영서버는 로그와 메트릭을 보내기만 하면되서 많은 리소스를 사용하지 않는다.

운영서버에서는 Node-exporter 와 Promtail 만 docker 로 띄운다. Node-exporter 는 호스트(GCP) 에 대한 메트릭을 수집한다. 개발서버의 Prometheus 가 주기적으로 운영서버의 Spring Boot Actuator 메트릭과 Node-exporter 메트릭 데이터를 pull 요청을 통해 가져간다.

Promtail 은 운영서버의 Logback log 와 Nginx log 데이터를 수집하고 개발서버의 Loki 로 데이터를 전송한다.

docker-compose.yml

운영서버 docker-compose.yml 과 개발서버의 docker-compose-dev.yml 은 기본적으로 내용 구성은 같다. 운영서버 Spring Boot 이미지와 개발서버 Spring Boot 이미지를 가져오는 차이가 있을 뿐이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
version: '3'

networks:
  nainga_prod_network:
    external: true

services:
  server:
    image: [dockerhub_id]/back:latest # 본인의 spring boot 이미지 저장소를 적으면 됩니다
    container_name: server
    networks:
      - nainga_prod_network
    ports:
      - 8080:8080
    environment:
      - "ACTIVE_SPRING_PROFILE=dev"
    volumes:
      - ~/logs:/app/logs # Logback 에서 저장하는 logs 위치를 호스트에 마운트합니다.

  nginx:
    image: nginx:1.25-alpine
    container_name: nginx
    networks:
      - nainga_prod_network
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf 
      - /etc/letsencrypt:/etc/letsencrypt
      - /var/lib/letsencrypt:/var/lib/letsencrypt
      - ./nginx/log/nginx:/var/log/nginx # Nginx 에서 저장하는 logs 위치를 호스트에 마운트합니다.
    ports:
      - 80:80
      - 443:443
    depends_on:
      - server

docker-compose-prod-monitoring.yml

운영서버 모니터링 docker-compose 내용 전체는 아래와 같다. 개발서버는 시각화와 관리를 위해 prometheus, loki, grafana 를 띄웠지만, 운영서버에서는 개발서버로 데이터를 보내주기만 하면되기에 promtail 과 node-exporter 만 띄우면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
version: '3'

networks:
  nainga_prod_network:
    external: true

services:
  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    networks:
      - nainga_prod_network
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.rootfs=/rootfs'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    ports:
      - "9100:9100"

  promtail:
    image: grafana/promtail:latest
    container_name: promtail
    networks:
      - nainga_prod_network
    volumes:
      - ~/logs:/logs
      - ~/nginx/log/nginx:/nginx/logs
      - ./promtail-prod-config.yml:/etc/promtail/config.yml
    command: -config.file=/etc/promtail/config.yml

Node-exporter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    networks:
      - nainga_prod_network
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.rootfs=/rootfs'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    ports:
      - "9100:9100"

개발서버와 다른점은 포트를 열었다는 점이다. 왜냐하면 개발서버와 운영서버는 분리되어있기에 도커 네트워크를 이용해서 통신할 수 없다. 그래서 개발서버에서 {운영 호스트 주소}:9100 으로 요청해야 한다. 주의할점은 이렇게 포트번호를 열어두면 추가로 방확벽을 설정해야한다. GCP 방화벽 정책에서 {개발 호스트 주소} 의 9100 번 포트를 열어두자. (0.0.0.0 으로 열면 모든 사람이 접근가능하기 때문에 꼭 개발 호스트 주소에만 열어두자)

Promtail

1
2
3
4
5
6
7
8
9
10
  promtail:
    image: grafana/promtail:latest
    container_name: promtail
    networks:
      - nainga_prod_network
    volumes:
      - ~/logs:/logs
      - ~/nginx/log/nginx:/nginx/logs
      - ./promtail-prod-config.yml:/etc/promtail/config.yml
    command: -config.file=/etc/promtail/config.yml

기본적으로 promtail 은 개발서버와 동일하나 설정파일이 다르다.

promtail-prod-config.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml # 동기화 작업을 이루기 위해 promtail이 읽은 마지막 로그 정보를 저장하는 곳

clients:
  - url: http://{개발 서버 호스트 주소}:3100/loki/api/v1/push # push할 Loki의 주소

scrape_configs:
  - job_name: debug
    static_configs:
      - targets:
          - localhost
        labels:
          job: debug_logs_prod
          __path__: ./logs/debug/*.log # debug 폴더 내에 log 파일들 모두 수집

  - job_name: info
    static_configs:
      - targets:
          - localhost
        labels:
          job: info_logs_prod
          __path__: ./logs/info/*.log # info 폴더 내에 log 파일들 모두 수집

  - job_name: warn
    static_configs:
      - targets:
          - localhost
        labels:
          job: warn_logs_prod
          __path__: ./logs/warn/*.log # warn 폴더 내에 log 파일들 모두 수집

  - job_name: error
    static_configs:
      - targets:
          - localhost
        labels:
          job: error_logs_prod
          __path__: ./logs/error/*.log # error 폴더 내에 log 파일들 모두 수집

  - job_name: nginx
    static_configs:
      - targets:
          - localhost
        labels:
          job: nginx_log_prod
          __path__: ./nginx/logs/*.log

Push

1
2
clients:
  - url: http://{개발 서버 호스트 주소}:3100/loki/api/v1/push # push할 Loki의 주소

개발서버 Loki 로 로그를 보낼것이기 때문에 개발 서버의 호스트주소를 적어주어야 한다. 개발서버의 보안그룹에는 운영서버의 3100 포트에 대해 열어두어야 한다.

수집

1
2
3
4
5
6
7
- job_name: nginx
    static_configs:
      - targets:
          - localhost
        labels:
          job: nginx_log_prod
          __path__: ./nginx/logs/*.log

해당 수집 내용은 기본적으로 개발서버와 동일하지만, job: 이 개발서버와 이름이 겹치지 않게 주의해야 한다.

prometheus-dev.yml

개발서버의 prometheus 에서 운영서버의 Spring Boot Actuator, Node-expector 메트릭을 수집하기 때문에 해당 파일도 설정할 필요가 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# metrics_path : metric 경로 지정
# scrape_interval : 수집 주기

global:
  scrape_interval:     15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'nainga-dev'
    metrics_path: 'myendpoint/prometheus'
    static_configs:
      - targets: ['server:8080']

  - job_name: 'node-dev'
    metrics_path: '/metrics'
    static_configs:
      - targets: ['node-exporter:9100']

  # 운영 서버 로깅 데이터 수집

  - job_name: 'nainga-prod'
    metrics_path: 'myendpoint/prometheus'
    static_configs:
      - targets: [ '{운영 서버 호스트 주소}:8080' ]

  - job_name: 'node-prod'
    metrics_path: '/metrics'
    static_configs:
      - targets: [ '{운영 서버 호스트 주소}:9100' ]

개발 서버에서 운영서버로 pull 요청을 하기에 운영 서버 호스트 주소를 적어줘야 한다.

Grafana

위와 같이 구성했다면, 최종적으로 개발서버에 있는 Grafana 가 개발서버와 운영서버의 로그와 메트릭 데이터를 시각화해서 보여준다. 운영서버 대시보드도 개발서버 대시보드와 마찬가지로 통합으로 시각화해서 보여주는데 성공했다.

이미지

Reference

운영서버, 개발서버 모니터링 아키텍처 구축

This post is licensed under CC BY 4.0 by the author.