기술 블로그(Alex)

  • Github Page
    • jekyll
  • Docker
    • guide
    • container
  • 이모저모

Prometheus & Grafana (시스템 모니터링)

Jan 11, 2019

Prometheus & Grafana 란?

  • Prometheus
    • 시스템을 모니터링 하고, 설정한 임계치를 넘으면 알람을 발송해주는 오픈소스프로젝트이다.
    • 다른 모니터링 시스템과 달리 수집하고자 하는 노드들이 서버로 데이터를 전달하는 방식이 아닌
    • 서버가 각노드에 데이터를 요청한다. (pull 방식)
    • 모니터링대상 서버들을 정적으로 yml 파일에 설정하지 않고 동적으로 할 수도 있음.
  • Grafana
    • 측정항목에 대해 쿼리, 시각화, 경고메시지 등을 할 수 있다.

Prometheus 컴포넌트

  • Server : 각 클라이언트로부터 시스템 정보를 수집하고 시계열 데이터를 저장
  • Exporter : Server에서 데이터를 수집하기 위한 Client (모니터링 대상 서버에서 실행)
  • 그외 Push Gateway, Alert Manager 등등의 다양한 툴들이 있음

Prometheus 및 Grafana 실행

아래의 prometheus.yml 파일과 prometheus.sh 파일을 같은 디렉토리에 준비
prometheus.sh 스크립트를 실행하면 해당 노드에는 server 및 grafana 컨테이너를 실행하고
리모트 서버들에는 exporter 컨테이너들을 실행해 준다.

사전작업

  • 스크립트를 실행하는 노드에서 ssh로 리모트 서버에 접속가능 하도록 해당 사용자의 public key 등록
  • ~/.ssh/id_rsa.pub의 값을 리모트 서버의 ~/.ssh/authorized_keys에 등록한다.

Prometheus server 설정파일 (prometheus.yml)

# my global config
global:
  scrape_interval:     5s # 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).
  external_labels:
    alex: 'alexander'

# 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: 'alex'
    scrape_interval: 5s
    static_configs:
    - targets: ['localhost:9090','expoter_ip:port'] # 모니터링 대상이 되는 서버정보 추가

실행스크립트 (prometheus.sh)

#!/bin/bash

Green='\033[0;32m'
Yellow='\033[1;33m'
RED='\033[031m'
NC='\033[0m'

# 컨테이너 이름
PROMETHEUS_SERVER_CONTAINER_NAME="prometheus-server"
PROMETHEUS_EXPORTER_CONTAINER_NAME="prometheus-exporter"
PROMETHEUS_GRAFANA_CONTAINER_NAME="prometheus-grafana"

# 컨테이너에 매핑될 호스트 디렉토리
ROOT_DIR=/data/repositories/docker-repository
PROMETHEUS_SERVER_DIR=${ROOT_DIR}/prometheus-server
PROMETHEUS_EXPORTER_DIR=${ROOT_DIR}/prometheus-exporter
PROMETHEUS_GRAFANA_DIR=${ROOT_DIR}/prometheus-grafana

# 컨테이너에 매핑될 호스트 포트
PROMETHEUS_SERVER_PORT=30001
PROMETHEUS_GRAFANA_PORT=30000
# Grafana admin 비번
PROMETHEUS_GRAFANA_ADMIN_PWD=admin!

# exporter가 설치될 노드 정보
REMOTE_USER="soul"
# ("server_ip1@컨네이너에 매핑될 포트" "server_ip2@컨네이너에 매핑될 포트")
REMOTE_LIST=("remote-ip@port")

runRemote(){
    IDX=0
    for remote in "${REMOTE_LIST[@]}"
    do
        IDX=$((IDX+1))

        IP_PORT=(${remote//@/ })
        echo -e "${Green}Run remote (${IDX}/${#REMOTE_LIST[@]})${NC}"

        ssh -o "StrictHostKeyChecking no" ${REMOTE_USER}@${IP_PORT[0]} docker rm -f ${PROMETHEUS_EXPORTER_CONTAINER_NAME}
        ssh -o "StrictHostKeyChecking no" ${REMOTE_USER}@${IP_PORT[0]} sudo rm -rf ${PROMETHEUS_EXPORTER_DIR}
        ssh -o "StrictHostKeyChecking no" ${REMOTE_USER}@${IP_PORT[0]} sudo mkdir -p ${PROMETHEUS_EXPORTER_DIR}
        ssh -o "StrictHostKeyChecking no" ${REMOTE_USER}@${IP_PORT[0]} sudo chmod 777 ${PROMETHEUS_EXPORTER_DIR}

        docker run -d --name ${PROMETHEUS_EXPORTER_CONTAINER_NAME} \
        --restart=always \
        -v /etc/localtime:/etc/localtime:ro \
        -p ${IP_PORT[1]}:9100 \
        prom/node-exporter

        echo -e "${Green}Done. (${IDX}/${#REMOTE_LIST[@]})${NC}"
    done
}

runServer(){
    echo -e "${Green}Run server${NC}"

    echo -e "${Yellow}Clear${NC}"
    # Clear prometheus server
    docker rm -f ${PROMETHEUS_SERVER_CONTAINER_NAME}
    sudo rm -rf ${PROMETHEUS_SERVER_DIR}
    mkdir -p ${PROMETHEUS_SERVER_DIR}
    chmod 777 ${PROMETHEUS_SERVER_DIR}

    # Clear grafana
    docker rm -f ${PROMETHEUS_GRAFANA_CONTAINER_NAME}
    sudo rm -rf ${PROMETHEUS_GRAFANA_DIR}
    mkdir -p ${PROMETHEUS_SERVER_DIR}/conf
    cp prometheus.yml ${PROMETHEUS_SERVER_DIR}/conf

    # Run prometheus-server (conf location : /etc/prometheus/prometheus.yml)
    docker run -d --name ${PROMETHEUS_SERVER_CONTAINER_NAME} \
    --restart=always \
    -p ${PROMETHEUS_SERVER_PORT}:9090 \
    -v /etc/localtime:/etc/localtime:ro \
    -v ${PROMETHEUS_SERVER_DIR}:/prometheus \
    -v ${PROMETHEUS_SERVER_DIR}/conf/prometheus.yml:/etc/prometheus/prometheus.yml \
    prom/prometheus

    # Run grafana (conf location : /etc/grafana/grafana.ini)
    docker run -d --name ${PROMETHEUS_GRAFANA_CONTAINER_NAME} \
    --restart=always \
    -u $(id -u root):$(id -g root) \
    -p ${PROMETHEUS_GRAFANA_PORT}:3000 \
    -v /etc/localtime:/etc/localtime:ro \
    -v ${PROMETHEUS_GRAFANA_DIR}/data:/var/lib/grafana \
    -e "GF_SERVER_ROOT_URL=http://ip" \
    -e "GF_SECURITY_ADMIN_PASSWORD=${PROMETHEUS_GRAFANA_ADMIN_PWD}" \
    -e "GF_SMTP_SKIP_VERITY=true" \
    -e "GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource,grafana-piechart-panel" \
    grafana/grafana:5.4.2

    echo -e "${Green}Done."
}

runRemote
echo -e "\n"
runServer

서버접속

  • Prometheus server : http://ip:30001 (위에서는 port를 30001로 주었음.)
  • Grafana : http://ip:30000 (위에서는 port를 30000로 주었음.)

Grafana 적용

이제 Grafana를 이용하여 Prometheus에서 수집한 각 서버의 자원정보를 아름답게(?) 시각화하는 설정을 진행한다.

1.Grafana 접속 > Add data source 선택 1

2.Prometheus 선택 1

3.Data source 설정 1

4.Dashboard 설정 1

5.Panel 설정 1

  • 좌측의 Graph 선택
  • 우측 상단의 패널추가 버튼 클릭하여 총4개의 패널이 생성되도록 한다.
  • 패널은 드래그&드롭으로 아래 그림과 같이 배치가능.

6.패널 쿼리설정 1

  • Panel Tile을 클릭하면 위와 같은 메뉴들이 나온다
  • Edit 선택

7.각 리소스 설정
CPU 1

  • Axes 탭 > Unit > none > percent (0.0-1.0)
  • Display 탭 > Mode Options > Line Width > 2

Memory 1

# total
node_memory_MemTotal_bytes{job='alex',instance='remote-ip:30002'}
# used
node_memory_MemTotal_bytes{job='alex',instance='remote-ip:30002'} - node_memory_MemFree_bytes{job='alex',instance='remote-ip:30002'} - node_memory_Buffers_bytes{job='alex',instance='remote-ip:30002'} - node_memory_Cached_bytes{job='alex',instance='remote-ip:30002'}
# buff/cache
node_memory_Buffers_bytes{job='alex',instance='remote-ip:30002'}+node_memory_Cached_bytes{job='alex',instance='remote-ip:30002'}
# free
node_memory_MemFree_bytes{job='alex',instance='remote-ip:30002'}
  • Axes 탭 > Unit > data (Metric) > bytes
  • Display 탭 > Mode Options > Line Width > 2

Disk 1

  • Axes 탭 > Unit > data (Metric) > bytes
  • Display 탭 > Mode Options > Line Width > 2

Network 1

  • Axes 탭 > Unit > data rate > bytes/sec
  • Display 탭 > Mode Options > Line Width > 2

최종 설정된 모습 1

© Alexonepath. All rights reserved. Powered by GitHub Pages.