[카테고리:] Monitoring

  • Loki, Promtail 이용한 실시간 로그 모니터링 + Docker

    Loki, Promtail 이용한 실시간 로그 모니터링 + Docker

    구성

    Promtail

    • loki프로젝트에서 제공하는 로그 수집기

    ✅ Promtail 바이너리 다운로드

    # 버전 확인 (예: 2.9.4)
    VERSION="2.9.4"
    
    # 바이너리 다운로드 및 압축 해제
    wget https://github.com/grafana/loki/releases/download/v${VERSION}/promtail-linux-amd64.zip
    unzip promtail-linux-amd64.zip
    chmod +x promtail-linux-amd64
    sudo mv promtail-linux-amd64 /usr/local/bin/promtail

    ✅ Config 파일 작성

    server:
      http_listen_port: 9080
      grpc_listen_port: 0
    
    positions:
      filename: /var/log/positions.yaml
    
    clients:
      - url: http://localhost:3100/loki/api/v1/push  # Loki 주소로 입력해야 함.
    
    scrape_configs:
      - job_name: system
        static_configs:
          - targets:
              - localhost
            labels:
              job: varlogs # QL 에서 잡을 job 이름.
              __path__: /var/log/*.log # 수집할 로그 파일

    ✅ Systemd 서비스 등록

    ## /etc/systemd/system directory
    
    [Unit]
    Description=Promtail Log Collector
    After=network.target
    
    [Service]
    Type=simple
    ExecStart=/usr/local/bin/promtail -config.file=/etc/promtail/config.yaml
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    
    ---
    systemctl daemon-reload 

    🐳 Docker로 Promtail Container

    ✅ Promtail config 파일 작성

    # config-promtail.yaml
    
    server:
      http_listen_port: 9080
      grpc_listen_port: 0
    
    positions:
      filename: /tmp/positions.yaml
    
    clients:
      - url: http://loki:3100/loki/api/v1/push  # Loki의 주소에 맞게 수정
    
    scrape_configs:
      - job_name: system
        static_configs:
          - targets:
              - localhost
            labels:
              job: varlogs
              __path__: /var/log/*.log

    🐳 Docker로 Run

    docker run -dit \
      --name promtail \
      -v /var/log:/var/log \ # volume mount
      -v /$(pwd)/config-promtail.yaml:/etc/promtail/config.yaml \
      grafana/promtail:latest \
      -config.file=/etc/promtail/config.yaml

    🐙 Docker-Compose Version

    version : '3'
    
    services:
      promtail:
        image: grafana/promtail:latest
        volumes:
          - /var/log:/var/log
          - ./config-promtail.yaml:/etc/promtail/config.yaml
         command: -config.file=/etc/promtail/config.yaml
    
    ---
    docker-compose up -d promtail

    네트워크 구성

    🔥 Promtail과 loki 사이 통신 방식은 push. Promtail 에서 loki 쪽으로 데이터를 push 해줌


    Loki

    내가 사용하는 방식의 Loki는 Grafana, Prometheus 등 과 같이 올렸어야 했기 때문에 Docker Container 형식으로 올렸다. 따라서, Docker Container 으로 정리했다.

    🐙 Docker-Compose Version

    • loki-config.yaml
    auth_enabled: false
    
    server:
      http_listen_port: 3100
      log_level: info
    
    ingester:
      lifecycler:
        ring:
          kvstore:
            store: inmemory
          replication_factor: 1
      chunk_idle_period: 3m
      max_chunk_age: 1h
    
    schema_config:
      configs:
        - from: 2022-01-01
          store: boltdb-shipper
          object_store: filesystem
          schema: v11
          index:
            prefix: index_
            period: 24h
    
    storage_config:
      boltdb_shipper:
        active_index_directory: /tmp/loki/index
        cache_location: /tmp/loki/boltdb-cache
      filesystem:
        directory: /tmp/loki/chunks
    
    limits_config:
      allow_structured_metadata: false  # 이 항목이 없으면 최신 Loki에서 기동 실패
    
    common:
      path_prefix: /tmp/loki  # compactor 등 여러 모듈이 이 경로를 사용
    
    compactor:
      working_directory: /tmp/loki/compactor  # 필수
    
    ruler:
      alertmanager_url: http://alertmanager:9093
      enable_alertmanager_v2: true
      enable_api: true
      rule_path: /tmp/loki/rules-temp
      storage:
        type: local
        local:
          directory: /tmp/loki/rules
    loki:
      image: grafana/loki:latest # docker 제공 공식 image
      container_name: loki
      ports:
        - "3100:3100"
      command: -config.file=/etc/loki/config.yaml
      volumes:
        - /home/rocky/grafana/loki/loki-cfg.yaml:/etc/loki/config.yaml
        - /home/rocky/grafana/loki/loki-data/rules:/tmp/loki/rules
        - /home/rocky/grafana/loki/loki-data/rules-temp:/tmp/loki/rules-temp
        - /home/rocky/grafana/loki/loki-data/index:/tmp/loki/index
        - /home/rocky/grafana/loki/loki-data/chunks:/tmp/loki/chunks
        - /home/rocky/grafana/loki/loki-data/boltdb-cache:/tmp/loki/boltdb-cache
        - /home/rocky/grafana/loki/loki-data/compactor:/tmp/loki/compactor
        - /home/rocky/grafana/loki/loki-data/wal:/tmp/loki/wal
      restart: always
    
    
      networks: # 네트워크는 기존 docker-compose에서 Grafana와 같은 네트워크로 설정해주면 된다.(난 따로 설정 안함.)
        - grafana_default
    - /home/rocky/grafana/loki/loki-cfg.yaml:/etc/loki/config.yaml
        - /home/rocky/grafana/loki/loki-data/rules:/tmp/loki/rules
        - /home/rocky/grafana/loki/loki-data/rules-temp:/tmp/loki/rules-temp
        - /home/rocky/grafana/loki/loki-data/index:/tmp/loki/index
        - /home/rocky/grafana/loki/loki-data/chunks:/tmp/loki/chunks
        - /home/rocky/grafana/loki/loki-data/boltdb-cache:/tmp/loki/boltdb-cache
        - /home/rocky/grafana/loki/loki-data/compactor:/tmp/loki/compactor
        - /home/rocky/grafana/loki/loki-data/wal:/tmp/loki/wal

    위의 Volume mount한 디렉토리를 생성하지 않으면 Container가 실행되지 않는다.

    mkdir -p /home/rocky/grafana/loki/loki-data
    mkdir -p /home/rocky/grafana/loki/loki-data/{rules,rules-temp,index,chunks,boltdb-cache,compactor,wal}

    이렇게 먼저 디렉토리 먼저 생성

    퍼미션 부여

    chown -R 10001:10001 /home/rocky/grafana/loki/loki-data
    chmod -R 777 /home/rocky/grafana/loki/loki-data

    위에 처럼 설정을 다 완료하고, 컨테이너가 다 문제 없이 돌고 있다면, Grafana 에서 loki Data source를 등록해주면 된다.

    Grafana > ⚙️ Settings > Data Sources > loki

    URL이 다음 중 하나여야 한다.

    • http://loki:3100 ← Grafana와 Loki가 같은 도커 네트워크일 때 (보통 Compose 환경)
    • http://localhost:3100 ← Grafana가 호스트에 설치되어 있고 Loki도 호스트에서 도는 경우

    이렇게 설정해주면 쿼리를 날려 데이터가 잘 나오는지 확인하면 된다.

  • Grafana, Prometheus를 이용한 서버 모니터링

    Grafana, Prometheus를 이용한 서버 모니터링

    ⚙️ 동기

    가용되는 서버들이 많아 서버들의 리소스 확인 및 서버다운 확인 필요성을 느꼈다.

    서버들의 CPU, RAM, DISK를 모니터링을 하면서 CPU, RAM, DISK 각각 일정 %를 넘으면 알림을 주고, 서버가 다운이 되면 알림을 주도록 구현.

    🛠️ 사용한 Tools.

    서버모니터링 | Grafana
    메트릭 정보 저장 | Prometheus
    서버 CPU, Memory, Disk 정보 제공 | node exporter
    알림 제공 | alertmanager(Prometheus, Telegram)

    
    sudo yum install -y https://dl.grafana.com/oss/release/grafana-11.0.0-1.x86_64.rpm

    Grafana 방화벽 열기

    3000 port 방화벽 open
    # firewall-cmd --zone=public --permanent --add-port=3000/tcp
    # firewall-cmd --reload
    # firewall-cmd --zone=public --list-all

    Grafana 접속

    http://localhost:3000/login에 접속하면 Grafana에 접속할 수 있다.


    prometheus 설치

    prometheus 설치

    wget https://github.com/prometheus/prometheus/releases/download/v2.42.0/prometheus-2.42.0.linux-amd64.tar.gz

    prometheus 압축풀기

    tar -xzvf prometheus-2.42.0.linux-amd64.tar.gz

    prometheus 실행

    ./prometheus --config.file=/파일경로/prometheus.yml

    prometheus 접속

    프로메테우스 default 포트 : 9090
    http://localhost:9090

    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: ["localhost:9093"]
              # - alertmanager:9093
    # Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
    rule_files: ["alert.rules.yml"]
      # - "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: "node"
        # metrics_path defaults to '/metrics'
        # scheme defaults to 'http'.
        static_configs:
         - targets: ["ip:9100"]

    node exporter 설치 및 압축풀기

    # node_exporter 설치.
    wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
    
    # 파일 압출 풀기.
    tar xzvf node_exporter-1.7.0.linux-amd64.tar.gz

    node_exporter 실행

    ./node_exporter
    
    # 백그라운드 실행
    ./node_exporter &

    🧱 Grafana를 이용해서 서버 리소스 알림

    이렇게 Grafana에 접속한 후,

    alerting에 들어간다.

    alerting에 3가지가 나오는데, 먼저 alert rules를 작성해야 한다.

    나는 CPU, Disk, RAM 이렇게 3가지를 모니터링을 할 것이다.

    CPU 설정법

    CPU

    DISK 설정법

    RAM 설정법

    나머지는 CPU 설정법과 동일하다. 이미지 보고 참고 바란다.


    contact Points 에서 Telegram 사용

    이렇게 텔레그램으로 알림을 줄 수 있게 만들어 주면 된다.


    Notification Templates 설정

    template 제목

    monitoring-templete

    template 코드

    {{ define "monitoring-template" }}
    *********** {{ .Status }} ***********
    
    {{ range $key, $value := .CommonLabels }}
      {{$key}}: {{$value}}
    {{ end }}
    {{ range .Alerts.Firing }}
      {{ if gt (len .Annotations) 0 }}
        {{ index .Annotations.Values 0 }}
      {{ end }}
    {{ end }}
    {{ end }}
    
    # 자신의 쓸 알람 스타일에 맞게 변형해서 쓰면 된다.

    alertmanager 설치 및 실행

    • (port : 9093)

    Alertmanager는 Prometheus의 오픈 소스 알림 관리 시스템

    telegram_config를 사용하려면 버전을 0.27.0버전 이상 사용해야 함.

    prometheus — alertmanager 참고 사이트

    1. alertmanager 설치.
    wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz
    
    2. 압축 풀기.
    tar -xzf alertmanager-0.27.0.linux-amd64.tar.gz

    alert.rules.yml 설정

    instance 서버가 다운이 되면 알림을 주는 녀석이다.

    이 파일은 Prometheus 디렉토리에 저장하면 된다.

    groups:
    - name: server_down
      rules:
      - alert: InstanceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Instance {{ $labels.instance }} down"
          description: "{{ $labels.instance }} of job {{ $labels.job }} is down."

    alertmanager.yml 설정

    # 디폴트 내용
    
    #route:
    #  group_by: ['alertname']
    #  group_wait: 30s
    #  group_interval: 5m
    #  repeat_interval: 1h
    #  receiver: 'web.hook'
    #receivers:
    #  - name: 'web.hook'
    #    webhook_configs:
    #      - url: 'http://127.0.0.1:5001/'
    #inhibit_rules:
    #  - source_match:
    #      severity: 'critical'
    #    target_match:
    #      severity: 'warning'
    #    equal: ['alertname', 'dev', 'instance']
    # 텔레그램 설정
    
    global:
      resolve_timeout: 5m
    route:
      group_by: ['alertname', 'instanceDown']
      group_wait: 20s
      group_interval: 2m
      repeat_interval: 1m
      receiver: 'telegram'
    receivers:
    - name: 'telegram'
      telegram_configs:
      - bot_token: '텔레그램 봇 토큰'
        chat_id: 챗 ID

    alertmanager 재시작

    ./alertmanager &