Задание 1

Что нужно сделать

Соберите следующие метрики:

  • node_cpu_seconds_total — режим iowait.
  • node_cpu_seconds_total — загрузка процессора в процентах. Подсказка: без CPU.
  • node_filesystem_avail_bytesmountpoint /, исключить device tmpfs. Занятое место в процентах.
  • node_load за 15 минут (примечание: тут есть подвох).

Метрики:

node_cpu_seconds_total{mode="iowait"}
100 - (avg without (cpu) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
100 - ((node_filesystem_avail_bytes{mountpoint="/",fstype!~"tmpfs"} / node_filesystem_size_bytes) * 100)
node_load15

Тоже самое в Prometheus WebUI:

Задание 2

Что нужно сделать

Используя Grafana, прикрутите визуализацию для всех метрик, что мы указали выше, плюсом добавьте свои, на ваш вкус и цвет. Пять штук будет вполне достаточно. Чтобы было интереснее, визуализируйте все метрики, используя Stat, Graph, Gauge, Time Series и Pie Chart. Для каких метрик что использовать ― на ваше усмотрение.

Graph и Time Series

Раньше был тип визуализации “Graph”, у которого, как я понимаю, имелся формат “Time Series”, а теперь это просто одна сущность в виде типа визуализации “Time Series” — визуализации под именем “Graph” больше нет.

Использование Slideshow

В разделе “Что оценивается” требовалось “Использование Slideshow”.
Как я понял, имелись в виду плейлисты; использовать их буду в Задании 4, где будет несколько дашбордов, и, следовательно, появится в них нужда.

Dashboard


Data sources

Задание 3

Что нужно сделать

Сделайте четыре алерта:

  1. Хост получает очень много трафика за минуту. Пусть будет выше 50 Mb/s.
  2. Загрузка процессора выше 85%.
  3. У нас упал какой-то таргет up == 0.
  4. У нас упало ВСЁ.

Configuration

docker-compose.yml
# yaml-language-server: $schema=https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json
x-common: &common
  networks:
    - monitoring
  restart: unless-stopped
 
x-shared-env: &shared-env
  TZ: "Europe/Moscow"
 
name: monitoring-practical-work
 
services:
  alertmanager:
    image: prom/alertmanager:v0.28.0
    container_name: alertmanager
    depends_on:
      - envsubst
      - prometheus
    volumes:
      - ./alertmanager:/etc/alertmanager
    environment: *shared-env
    ports:
      - "127.0.0.1:9093:9093"
    command:
      - --config.file=/etc/alertmanager/alertmanager.yml
      - --log.level=debug
    <<: *common
 
  # Source: https://github.com/mrnetops/fastly-dashboards/blob/90e51227356292cc1f0714b5487bdb873b9bdcdf/docker-compose.yml#L16-L21
  envsubst:
    image: bhgedigital/envsubst:v1.0-alpine3.6
    container_name: envsubst
    volumes:
      - ./alertmanager:/mnt
    env_file: .env
    command: sh -c "envsubst < /mnt/alertmanager.template.yml > /mnt/alertmanager.yml"
 
  grafana:
    image: grafana/grafana:11.5.2
    container_name: grafana
    depends_on:
      - prometheus
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning/datasources/datasource.yml:/etc/grafana/provisioning/datasources/datasource.yml
      - ./grafana/provisioning/dashboards/dashboards.yml:/etc/grafana/provisioning/dashboards/dashboards.yml
      - ./grafana/provisioning/dashboards/json:/var/lib/grafana/dashboards
    environment:
      <<: *shared-env
      GF_AUTH_ANONYMOUS_ENABLED: "true"
      GF_AUTH_ANONYMOUS_ORG_ROLE: "Admin"
    ports:
      - "127.0.0.1:3000:3000"
    <<: *common
 
  loki:
    image: grafana/loki:3.4.2
    container_name: loki
    volumes:
      - ./loki/loki-config.yml:/etc/loki/loki-config.yml:ro
    environment: *shared-env
    ports:
      - "127.0.0.1:3100:3100"
    command: -config.file=/etc/loki/loki-config.yml
    <<: *common
 
  node-exporter:
    image: prom/node-exporter:v1.9.0
    container_name: node-exporter
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    environment: *shared-env
    ports:
      - "127.0.0.1:9100:9100"
    command:
      - --path.procfs=/host/proc
      - --path.sysfs=/host/sys
      - --collector.filesystem.ignored-mount-points
      - ^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)
    <<: *common
 
  prometheus:
    image: prom/prometheus:v3.2.1
    container_name: prometheus
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./prometheus/alerts.yml:/etc/prometheus/alerts.yml
      - prometheus-data:/prometheus
    environment: *shared-env
    ports:
      - "127.0.0.1:9090:9090"
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.path=/prometheus/data
      - --web.enable-lifecycle
    <<: *common
 
  promtail:
    image: grafana/promtail:3.4.2
    container_name: promtail
    depends_on:
      - loki
    volumes:
      - ./loki/promtail-config.yml:/etc/promtail/promtail-config.yml:ro
      - /var/log:/var/log:ro
    environment: *shared-env
    command: -config.file=/etc/promtail/promtail-config.yml
    <<: *common
 
networks:
  monitoring:
    driver: bridge
 
volumes:
  prometheus-data: {}
  grafana-data: {}
alertmanager.template.yml
global:
  resolve_timeout: 5m
  telegram_api_url: 'https://api.telegram.org'
 
templates:
  - /etc/alertmanager/templates/telegram.tmpl
 
receivers:
  # Source: https://prometheus.io/docs/alerting/latest/configuration/#telegram_config
  - name: 'telegram'
    telegram_configs:
      - chat_id: ${TELEGRAM_CHAT_ID}
        bot_token: ${TELEGRAM_BOT_TOKEN}
        parse_mode: 'HTML'
        message: '{{ template "telegram.message". }}'
 
route:
  group_by: ['alertname']
  group_wait: 15s
  group_interval: 30s
  repeat_interval: 4h
  receiver: telegram
  routes:
    - receiver: telegram
      continue: true
      matchers:
        - severity =~ "warning|critical"
alerts.yml
groups:
  - name: "Main rules"
    rules:
 
      - alert: HighIncomingTraffic
        expr: sum by (instance) (rate(node_network_receive_bytes_total{device!~"lo|veth.*|docker.*"}[15s])) / (1024 * 1024) > 50
        for: 15s
        labels:
          severity: warning
        annotations:
          summary: "High Incoming network Traffic"
          description: "Incoming network Traffic > 50 MB/s on {{ $labels.instance }}"
 
      - alert: HighCpuLoad
        expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[1m])) * 100) > 85
        for: 5s
        labels:
          severity: warning
        annotations:
          summary: "High CPU Load"
          description: "CPU Load > 85% on {{ $labels.instance }}"
 
      - alert: TargetDown
        expr: up == 0
        for: 5s
        labels:
          severity: critical
        annotations:
          summary: "Prometheus target is DOWN"
          description: "{{ $labels.instance }} is DOWN"
 
      - alert: AllTargetsDown
        expr: count by (job) (up) == 0
        for: 5s
        labels:
          severity: critical
        annotations:
          summary: "All Prometheus targets are DOWN"
          description: "Prometheus can't find NONE of the targets"

Alert messages

Алерты отправляются напрямую в telegram без посредников-сервисов.

telegram.tmpl
{{ define "telegram.message" }}
{{ range .Alerts }}
{{ if eq .Status "firing" }}
{{ if eq .Labels.severity "critical" }}🚨 <code>{{ .Labels.alertname }}</code> {{ else }}⚠️ <code>{{ .Labels.alertname }}</code>{{ end }}
<b>{{ .Annotations.summary }}</b> on <b>{{ .Labels.instance }}</b>
{{ .Annotations.description }}
{{ else if eq .Status "resolved" }}
✅ <b>RESOLVED</b>: <code>{{ .Labels.alertname }}</code> on <b>{{ .Labels.instance }}</b>
{{ end }}
{{ end }}
{{ end }}

Задание 4

Что нужно сделать

Пускай у нас будет условный интернет-магазин.

  1. На первом инстансе у нас веб-приложение.
  2. На втором ― база данных.
  3. На третьем ― Prometheus, Grafana и так далее.

Разверните систему мониторинга, чтобы за всем этим делом следить.